Doxygen
Loading...
Searching...
No Matches
fortranscanner.l File Reference
#include <stdint.h>
#include <map>
#include <vector>
#include <algorithm>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <ctype.h>
#include "fortranscanner.h"
#include "entry.h"
#include "message.h"
#include "config.h"
#include "doxygen.h"
#include "util.h"
#include "defargs.h"
#include "language.h"
#include "commentscan.h"
#include "pre.h"
#include "arguments.h"
#include "debug.h"
#include "markdown.h"
#include "doxygen_lex.h"
#include "fortranscanner.l.h"
+ Include dependency graph for fortranscanner.l:

Go to the source code of this file.

Classes

struct  SymbolModifiers
 Holds yyextra->modifiers (ie attributes) for one symbol (variable, function, etc) More...
 
struct  CommentInPrepass
 
struct  fortranscannerYY_state
 
struct  FortranOutlineParser::Private
 

Macros

#define YY_TYPEDEF_YY_SCANNER_T
 
#define DBG_CTX(x)
 
#define YY_NO_INPUT   1
 
#define YY_NO_UNISTD_H   1
 
#define YY_INPUT(buf, result, max_size)
 
#define YY_USER_ACTION   yyextra->colNr+=(int)yyleng;
 
#define INVALID_ENTRY   ((Entry*)0x8)
 

Typedefs

typedef yyguts_t * yyscan_t
 

Enumerations

enum  ScanVar { V_IGNORE , V_VARIABLE , V_PARAMETER , V_RESULT }
 
enum  InterfaceType { IF_NONE , IF_SPECIFIC , IF_GENERIC , IF_ABSTRACT }
 

Functions

static int getAmpersandAtTheStart (const char *buf, int length)
 
static int getAmpOrExclAtTheEnd (const char *buf, int length, char ch)
 
static QCString extractFromParens (const QCString &name)
 
static QCString extractBind (const QCString &name)
 
static int yyread (yyscan_t yyscanner, char *buf, int max_size)
 
static void startCommentBlock (yyscan_t yyscanner, bool)
 
static void handleCommentBlock (yyscan_t yyscanner, const QCString &doc, bool brief)
 
static void subrHandleCommentBlock (yyscan_t yyscanner, const QCString &doc, bool brief)
 Handle parameter description as defined after the declaration of the parameter.
 
static void subrHandleCommentBlockResult (yyscan_t yyscanner, const QCString &doc, bool brief)
 Handle result description as defined after the declaration of the parameter.
 
static void addCurrentEntry (yyscan_t yyscanner, bool case_insens)
 adds yyextra->current entry to yyextra->current_root and creates new yyextra->current
 
static void addModule (yyscan_t yyscanner, const QCString &name=QCString(), bool isModule=FALSE)
 
static void addSubprogram (yyscan_t yyscanner, const QCString &text)
 
static void addInterface (yyscan_t yyscanner, QCString name, InterfaceType type)
 
static ArgumentgetParameter (yyscan_t yyscanner, const QCString &name)
 
static void scanner_abort (yyscan_t yyscanner)
 
static void pop_state (yyscan_t yyscanner)
 
static void startScope (yyscan_t yyscanner, Entry *scope)
 
static bool endScope (yyscan_t yyscanner, Entry *scope, bool isGlobalRoot=FALSE)
 
static void copyEntry (std::shared_ptr< Entry > dest, const std::shared_ptr< Entry > &src)
 used to copy entry to an interface module procedure
 
static void resolveModuleProcedures (yyscan_t yyscanner, Entry *current_root)
 fill empty interface module procedures with info from corresponding module subprogs
 
static void resolveTypeBoundProcedures (Entry *scope)
 
static void truncatePrepass (yyscan_t yyscanner, int index)
 
static void pushBuffer (yyscan_t yyscanner, const QCString &buffer)
 
static void popBuffer (yyscan_t yyscanner)
 
static const CommentInPrepasslocatePrepassComment (yyscan_t yyscanner, int from, int to)
 
static void updateVariablePrepassComment (yyscan_t yyscanner, int from, int to)
 
static void newLine (yyscan_t yyscanner)
 
static void initEntry (yyscan_t yyscanner)
 
static const char * stateToString (int state)
 
static int computeIndent (const char *s)
 
static const char * getLexerFILE ()
 
int yylex (yyscan_t yyscanner)
 fortran parsing states
 
static void insertCharacter (char *contents, int length, int pos, char c)
 
const char * prepassFixedForm (const char *contents, int *hasContLine, int fixedCommentAfter)
 
static ArgumentfindArgument (Entry *subprog, QCString name, bool byTypeName=FALSE)
 
static QCString applyModifiers (QCString typeName, const SymbolModifiers &mdfs)
 
static void applyModifiers (Argument *arg, const SymbolModifiers &mdfs)
 
static void applyModifiers (Entry *ent, const SymbolModifiers &mdfs)
 
static void initParser (yyscan_t yyscanner)
 
static void parseMain (yyscan_t yyscanner, const QCString &fileName, const char *fileBuf, const std::shared_ptr< Entry > &rt, FortranFormat format)
 

Variables

static const char * directionStrs []
 
static const char * directionParam []
 

Macro Definition Documentation

◆ DBG_CTX

#define DBG_CTX ( x)
Value:
do { } while(0)

Definition at line 81 of file fortranscanner.l.

Referenced by addModule(), addSubprogram(), and handleCommentBlock().

◆ INVALID_ENTRY

#define INVALID_ENTRY   ((Entry*)0x8)

Definition at line 264 of file fortranscanner.l.

Referenced by endScope(), and parseMain().

◆ YY_INPUT

#define YY_INPUT ( buf,
result,
max_size )
Value:
result=yyread(yyscanner,buf,max_size);
static int yyread(yyscan_t yyscanner, char *buf, int max_size)

Definition at line 258 of file fortranscanner.l.

◆ YY_NO_INPUT

#define YY_NO_INPUT   1

Definition at line 83 of file fortranscanner.l.

◆ YY_NO_UNISTD_H

#define YY_NO_UNISTD_H   1

Definition at line 84 of file fortranscanner.l.

◆ YY_TYPEDEF_YY_SCANNER_T

#define YY_TYPEDEF_YY_SCANNER_T

Definition at line 48 of file fortranscanner.l.

◆ YY_USER_ACTION

#define YY_USER_ACTION   yyextra->colNr+=(int)yyleng;

Definition at line 263 of file fortranscanner.l.

Typedef Documentation

◆ yyscan_t

typedef yyguts_t* yyscan_t

Definition at line 50 of file fortranscanner.l.

Enumeration Type Documentation

◆ InterfaceType

Enumerator
IF_NONE 
IF_SPECIFIC 
IF_GENERIC 
IF_ABSTRACT 

Definition at line 87 of file fortranscanner.l.

87{ IF_NONE, IF_SPECIFIC, IF_GENERIC, IF_ABSTRACT };

◆ ScanVar

enum ScanVar
Enumerator
V_IGNORE 
V_VARIABLE 
V_PARAMETER 
V_RESULT 

Definition at line 86 of file fortranscanner.l.

86{ V_IGNORE, V_VARIABLE, V_PARAMETER, V_RESULT};

Function Documentation

◆ addCurrentEntry()

static void addCurrentEntry ( yyscan_t yyscanner,
bool case_insens )
static

adds yyextra->current entry to yyextra->current_root and creates new yyextra->current

Definition at line 2898 of file fortranscanner.l.

2899{
2900 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2901 if (case_insens) yyextra->current->name = yyextra->current->name.lower();
2902 //printf("===Adding entry %s to %s\n", qPrint(yyextra->current->name), qPrint(yyextra->current_root->name));
2903 yyextra->last_entry = yyextra->current;
2904 yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
2905 initEntry(yyscanner);
static void initEntry(yyscan_t yyscanner)
2906}

References initEntry().

Referenced by addInterface(), addModule(), and handleCommentBlock().

◆ addInterface()

static void addInterface ( yyscan_t yyscanner,
QCString name,
InterfaceType type )
static

Adds interface to the root entry.

Note
Code was brought to this procedure from the parser, because there was/is idea to use it in several parts of the parser.

Definition at line 2968 of file fortranscanner.l.

2969{
2970 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2971 if (YY_START == Start)
2972 {
2973 addModule(yyscanner);
2974 yy_push_state(ModuleBody,yyscanner); //anon program
2975 }
static void addModule(yyscan_t yyscanner, const QCString &name=QCString(), bool isModule=FALSE)
2976
2977 yyextra->current->section = EntryType::makeClass(); // was EntryType::Interface;
2978 yyextra->current->spec = TypeSpecifier().setInterface(true);
2979 yyextra->current->name = name;
Wrapper class for a number of boolean properties.
Definition types.h:492
2980
2981 switch (type)
2982 {
2983 case IF_ABSTRACT:
2984 yyextra->current->type = "abstract";
2985 break;
@ IF_ABSTRACT
2986
2987 case IF_GENERIC:
2988 yyextra->current->type = "generic";
2989 break;
@ IF_GENERIC
2990
2991 case IF_SPECIFIC:
2992 case IF_NONE:
2993 default:
2994 yyextra->current->type = "";
2995 }
@ IF_NONE
@ IF_SPECIFIC
2996
2997 /* if type is part of a module, mod name is necessary for output */
2998 if ((yyextra->current_root) &&
2999 (yyextra->current_root->section.isClass() ||
3000 yyextra->current_root->section.isNamespace()))
3001 {
3002 yyextra->current->name= yyextra->current_root->name + "::" + yyextra->current->name;
3003 }
3004
3005 yyextra->current->fileName = yyextra->fileName;
3006 yyextra->current->bodyLine = yyextra->lineNr;
3007 yyextra->current->startLine = yyextra->lineNr;
3008 addCurrentEntry(yyscanner,true);
static void addCurrentEntry(yyscan_t yyscanner, bool case_insens)
adds yyextra->current entry to yyextra->current_root and creates new yyextra->current
3009}

References addCurrentEntry(), addModule(), IF_ABSTRACT, IF_GENERIC, IF_NONE, and IF_SPECIFIC.

◆ addModule()

static void addModule ( yyscan_t yyscanner,
const QCString & name = QCString(),
bool isModule = FALSE )
static

Definition at line 2908 of file fortranscanner.l.

2909{
2910 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2911 DBG_CTX((stderr, "0=========> got module %s\n", qPrint(name)));
#define DBG_CTX(x)
const char * qPrint(const char *s)
Definition qcstring.h:672
2912
2913 if (isModule)
2914 yyextra->current->section = EntryType::makeNamespace();
2915 else
2916 yyextra->current->section = EntryType::makeFunction();
2917
2918 if (!name.isEmpty())
2919 {
2920 yyextra->current->name = name;
2921 }
2922 else
2923 {
2924 QCString fname = yyextra->fileName;
2925 int index = std::max(fname.findRev('/'), fname.findRev('\\'));
2926 fname = fname.right(fname.length()-index-1);
2927 if (yyextra->mainPrograms) fname += "__" + QCString().setNum(yyextra->mainPrograms);
2928 yyextra->mainPrograms++;
2929 fname = fname.prepend("__").append("__");
2930 yyextra->current->name = substitute(fname, ".", "_");
2931 }
2932 yyextra->current->type = "program";
2933 yyextra->current->fileName = yyextra->fileName;
2934 yyextra->current->bodyLine = yyextra->lineNr; // used for source reference
2935 yyextra->current->startLine = yyextra->lineNr;
2936 yyextra->current->protection = Protection::Public ;
2937 addCurrentEntry(yyscanner,true);
2938 startScope(yyscanner,yyextra->last_entry.get());
This is an alternative implementation of QCString.
Definition qcstring.h:101
QCString & prepend(const char *s)
Definition qcstring.h:407
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition qcstring.h:153
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:150
QCString & setNum(short n)
Definition qcstring.h:444
QCString & append(char c)
Definition qcstring.h:381
QCString right(size_t len) const
Definition qcstring.h:219
int findRev(char c, int index=-1, bool cs=TRUE) const
Definition qcstring.cpp:91
static void startScope(yyscan_t yyscanner, Entry *scope)
QCString substitute(const QCString &s, const QCString &src, const QCString &dst)
substitute all occurrences of src in s by dst
Definition qcstring.cpp:477
@ Public
Definition types.h:26
2939}

References addCurrentEntry(), QCString::append(), DBG_CTX, QCString::findRev(), QCString::isEmpty(), QCString::length(), QCString::prepend(), Public, qPrint(), QCString::right(), QCString::setNum(), startScope(), and substitute().

Referenced by addInterface().

◆ addSubprogram()

static void addSubprogram ( yyscan_t yyscanner,
const QCString & text )
static

Definition at line 2942 of file fortranscanner.l.

2943{
2944 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2945 DBG_CTX((stderr,"1=========> got subprog, type: %s\n",qPrint(text)));
2946 yyextra->subrCurrent.push_back(yyextra->current);
2947 yyextra->current->section = EntryType::makeFunction();
2948 QCString subtype = text; subtype=subtype.lower().stripWhiteSpace();
2949 yyextra->functionLine = (subtype.find("function") != -1);
2950 yyextra->current->type += " " + subtype;
2951 yyextra->current->type = yyextra->current->type.stripWhiteSpace();
2952 if (yyextra->ifType == IF_ABSTRACT)
2953 {
2954 yyextra->current->virt = Specifier::Virtual;
2955 }
2956 yyextra->current->fileName = yyextra->fileName;
2957 yyextra->current->bodyLine = yyextra->lineNr; // used for source reference start of body of routine
2958 yyextra->current->startLine = yyextra->lineNr; // used for source reference start of definition
2959 yyextra->current->args.clear();
2960 yyextra->current->argList.clear();
2961 yyextra->docBlock.clear();
int find(char c, int index=0, bool cs=TRUE) const
Definition qcstring.cpp:43
QCString lower() const
Definition qcstring.h:234
QCString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
Definition qcstring.h:245
void clear()
Definition qcstring.h:169
@ Virtual
Definition types.h:29
2962}

References QCString::clear(), DBG_CTX, QCString::find(), IF_ABSTRACT, QCString::lower(), qPrint(), QCString::stripWhiteSpace(), and Virtual.

◆ applyModifiers() [1/3]

static void applyModifiers ( Argument * arg,
const SymbolModifiers & mdfs )
static

Apply yyextra->modifiers stored in mdfs to the arg argument.

Definition at line 2528 of file fortranscanner.l.

2529{
2530 arg->type = applyModifiers(arg->type, mdfs);
static QCString applyModifiers(QCString typeName, const SymbolModifiers &mdfs)
QCString type
Definition arguments.h:37
2531}

References applyModifiers(), and Argument::type.

◆ applyModifiers() [2/3]

static void applyModifiers ( Entry * ent,
const SymbolModifiers & mdfs )
static

Apply yyextra->modifiers stored in mdfs to the ent entry.

Definition at line 2534 of file fortranscanner.l.

2535{
2536 ent->type = applyModifiers(ent->type, mdfs);
QCString type
member type
Definition entry.h:173
2537
2540 else if (mdfs.protection == SymbolModifiers::PRIVATE)
Protection protection
class protection
Definition entry.h:180
Protection protection
@ Private
Definition types.h:26
2542
2543 if (mdfs.nonoverridable)
2544 ent->spec.setFinal(true);
2545 if (mdfs.nopass)
2546 ent->isStatic = TRUE;
2547 if (mdfs.deferred)
2548 ent->virt = Specifier::Pure;
Specifier virt
virtualness of the entry
Definition entry.h:191
bool isStatic
static ?
Definition entry.h:185
TypeSpecifier spec
class/member specifiers
Definition entry.h:182
#define TRUE
Definition qcstring.h:37
@ Pure
Definition types.h:29
2549}

References applyModifiers(), SymbolModifiers::deferred, Entry::isStatic, SymbolModifiers::nonoverridable, SymbolModifiers::nopass, SymbolModifiers::PRIVATE, Private, Entry::protection, SymbolModifiers::protection, SymbolModifiers::PUBLIC, Public, Pure, Entry::spec, TRUE, Entry::type, and Entry::virt.

◆ applyModifiers() [3/3]

static QCString applyModifiers ( QCString typeName,
const SymbolModifiers & mdfs )
static

Apply yyextra->modifiers stored in mdfs to the typeName string.

Definition at line 2411 of file fortranscanner.l.

2412{
2413 if (!mdfs.dimension.isEmpty())
2414 {
2415 if (!typeName.isEmpty()) typeName += ", ";
2416 typeName += mdfs.dimension;
2417 }
2419 {
2420 if (!typeName.isEmpty()) typeName += ", ";
2421 typeName += directionStrs[mdfs.direction];
2422 }
2423 if (mdfs.optional)
2424 {
2425 if (!typeName.isEmpty()) typeName += ", ";
2426 typeName += "optional";
2427 }
2428 if (mdfs.allocatable)
2429 {
2430 if (!typeName.isEmpty()) typeName += ", ";
2431 typeName += "allocatable";
2432 }
2433 if (mdfs.external)
2434 {
2435 if (!typeName.contains("external"))
2436 {
2437 if (!typeName.isEmpty()) typeName += ", ";
2438 typeName += "external";
2439 }
2440 }
2441 if (mdfs.intrinsic)
2442 {
2443 if (!typeName.isEmpty()) typeName += ", ";
2444 typeName += "intrinsic";
2445 }
2446 if (mdfs.parameter)
2447 {
2448 if (!typeName.isEmpty()) typeName += ", ";
2449 typeName += "parameter";
2450 }
2451 if (mdfs.pointer)
2452 {
2453 if (!typeName.isEmpty()) typeName += ", ";
2454 typeName += "pointer";
2455 }
2456 if (mdfs.target)
2457 {
2458 if (!typeName.isEmpty()) typeName += ", ";
2459 typeName += "target";
2460 }
2461 if (mdfs.save)
2462 {
2463 if (!typeName.isEmpty()) typeName += ", ";
2464 typeName += "save";
2465 }
2466 if (mdfs.deferred)
2467 {
2468 if (!typeName.isEmpty()) typeName += ", ";
2469 typeName += "deferred";
2470 }
2471 if (mdfs.nonoverridable)
2472 {
2473 if (!typeName.isEmpty()) typeName += ", ";
2474 typeName += "non_overridable";
2475 }
2476 if (mdfs.nopass)
2477 {
2478 if (!typeName.isEmpty()) typeName += ", ";
2479 typeName += "nopass";
2480 }
2481 if (mdfs.pass)
2482 {
2483 if (!typeName.isEmpty()) typeName += ", ";
2484 typeName += "pass";
2485 if (!mdfs.passVar.isEmpty())
2486 typeName += "(" + mdfs.passVar + ")";
2487 }
2488 if (!mdfs.bindVar.isEmpty())
2489 {
2490 if (!typeName.isEmpty()) typeName += ", ";
2491 typeName += mdfs.bindVar;
2492 }
2494 {
2495 if (!typeName.isEmpty()) typeName += ", ";
2496 typeName += "public";
2497 }
2498 else if (mdfs.protection == SymbolModifiers::PRIVATE)
2499 {
2500 if (!typeName.isEmpty()) typeName += ", ";
2501 typeName += "private";
2502 }
2503 if (mdfs.protect)
2504 {
2505 if (!typeName.isEmpty()) typeName += ", ";
2506 typeName += "protected";
2507 }
2508 if (mdfs.contiguous)
2509 {
2510 if (!typeName.isEmpty()) typeName += ", ";
2511 typeName += "contiguous";
2512 }
2513 if (mdfs.volat)
2514 {
2515 if (!typeName.isEmpty()) typeName += ", ";
2516 typeName += "volatile";
2517 }
2518 if (mdfs.value)
2519 {
2520 if (!typeName.isEmpty()) typeName += ", ";
2521 typeName += "value";
2522 }
int contains(char c, bool cs=TRUE) const
Definition qcstring.cpp:143
static const char * directionStrs[]
Direction direction
2523
2524 return typeName;
2525}

References SymbolModifiers::allocatable, SymbolModifiers::bindVar, QCString::contains(), SymbolModifiers::contiguous, SymbolModifiers::deferred, SymbolModifiers::dimension, SymbolModifiers::direction, directionStrs, SymbolModifiers::external, SymbolModifiers::intrinsic, QCString::isEmpty(), SymbolModifiers::NONE_D, SymbolModifiers::nonoverridable, SymbolModifiers::nopass, SymbolModifiers::optional, SymbolModifiers::parameter, SymbolModifiers::pass, SymbolModifiers::passVar, SymbolModifiers::pointer, SymbolModifiers::PRIVATE, SymbolModifiers::protect, SymbolModifiers::protection, SymbolModifiers::PUBLIC, SymbolModifiers::save, SymbolModifiers::target, SymbolModifiers::value, and SymbolModifiers::volat.

Referenced by applyModifiers(), applyModifiers(), and endScope().

◆ computeIndent()

static int computeIndent ( const char * s)
inlinestatic

Definition at line 1709 of file fortranscanner.l.

1710{
1711 int col=0;
1712 int tabSize=Config_getInt(TAB_SIZE);
1713 const char *p=s;
1714 char c = 0;
1715 while ((c=*p++))
1716 {
1717 if (c=='\t') col+=tabSize-(col%tabSize);
1718 else if (c=='\n') col=0;
1719 else col++;
1720 }
1721 return col;
#define Config_getInt(name)
Definition config.h:34
1722}

References Config_getInt.

◆ copyEntry()

static void copyEntry ( std::shared_ptr< Entry > dest,
const std::shared_ptr< Entry > & src )
static

used to copy entry to an interface module procedure

Definition at line 2148 of file fortranscanner.l.

2149{
2150 dest->type = src->type;
2151 dest->fileName = src->fileName;
2152 dest->startLine = src->startLine;
2153 dest->bodyLine = src->bodyLine;
2154 dest->endBodyLine = src->endBodyLine;
2155 dest->args = src->args;
2156 dest->argList = src->argList;
2157 dest->doc = src->doc;
2158 dest->docLine = src->docLine;
2159 dest->docFile = src->docFile;
2160 dest->brief = src->brief;
2161 dest->briefLine= src->briefLine;
2162 dest->briefFile= src->briefFile;
2163}

Referenced by resolveModuleProcedures().

◆ endScope()

static bool endScope ( yyscan_t yyscanner,
Entry * scope,
bool isGlobalRoot )
static

Ends scope in fortran program: may update subprogram arguments or module variable attributes.

See also
startScope()

Definition at line 2571 of file fortranscanner.l.

2572{
2573 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2574 if (yyextra->global_scope == scope)
2575 {
2576 yyextra->global_scope = nullptr;
2577 return TRUE;
2578 }
2579 if (yyextra->global_scope == INVALID_ENTRY)
2580 {
2581 return TRUE;
2582 }
2583 //cout<<"end scope: "<<scope->name<<endl;
2584 if (yyextra->current_root->parent() || isGlobalRoot)
2585 {
2586 yyextra->current_root= yyextra->current_root->parent(); /* end substructure */
2587 }
2588 else // if (yyextra->current_root != scope)
2589 {
2590 fprintf(stderr,"parse error in end <scopename>\n");
2591 scanner_abort(yyscanner);
2592 return FALSE;
2593 }
#define INVALID_ENTRY
static void scanner_abort(yyscan_t yyscanner)
#define FALSE
Definition qcstring.h:34
2594
2595 // create new current with possibly different defaults...
2596 yyextra->current = std::make_shared<Entry>();
2597 initEntry(yyscanner);
2598
2599 // update variables or subprogram arguments with yyextra->modifiers
2600 std::map<std::string,SymbolModifiers>& mdfsMap = yyextra->modifiers[scope];
2601
2602 if (scope->section.isFunction())
2603 {
2604 // iterate all symbol yyextra->modifiers of the scope
2605 for (const auto &kv : mdfsMap)
2606 {
2607 //cout<<it.key()<<": "<<qPrint(it)<<endl;
2608 Argument *arg = findArgument(scope, QCString(kv.first));
EntryType section
entry type (see Sections);
Definition entry.h:172
static Argument * findArgument(Entry *subprog, QCString name, bool byTypeName=FALSE)
This class contains the information about the argument of a function or template.
Definition arguments.h:27
2609
2610 if (arg)
2611 {
2612 applyModifiers(arg, kv.second);
2613 }
2614 }
2615
2616 // find return type for function
2617 //cout<<"RETURN NAME "<<yyextra->modifiers[yyextra->current_root][scope->name.lower()].returnName<<endl;
2618 QCString returnName = yyextra->modifiers[yyextra->current_root][scope->name.lower().str()].returnName.lower();
2619 if (yyextra->modifiers[scope].find(returnName.str())!=yyextra->modifiers[scope].end())
2620 {
2621 scope->type = yyextra->modifiers[scope][returnName.str()].type; // returning type works
2622 applyModifiers(scope, yyextra->modifiers[scope][returnName.str()]); // returning array works
2623 }
QCString name
member name
Definition entry.h:174
const std::string & str() const
Definition qcstring.h:537
2624
2625 }
2626 if (scope->section.isClass() && scope->spec.isInterface())
2627 { // was INTERFACE_SEC
2628 if (scope->parent() && scope->parent()->section.isFunction())
2629 { // interface within function
2630 // iterate functions of interface and
2631 // try to find types for dummy(ie. argument) procedures.
2632 //cout<<"Search in "<<scope->name<<endl;
2633 for (const auto &ce : scope->children())
2634 {
2635 if (!ce->section.isFunction())
2636 continue;
const std::vector< std::shared_ptr< Entry > > & children() const
Definition entry.h:139
Entry * parent() const
Definition entry.h:134
2637
2638 // remove prefix
2639 QCString name = ce->name.lower();
2640 int ii = name.findRev(":");
2641 if (ii != -1)
2642 {
2643 name.remove(0, ii+1);
2644 }
2645 Argument *arg = findArgument(scope->parent(), name);
2646 if (arg)
2647 {
2648 // set type of dummy procedure argument to interface
2649 arg->type = "external " + ce->type + "(";
2650 for (unsigned int i=0; i<ce->argList.size(); i++)
2651 {
2652 if (i > 0)
2653 {
2654 arg->type = arg->type + ", ";
2655 }
2656 const Argument &subarg = ce->argList.at(i);
2657 arg->type = arg->type + subarg.type + " " + subarg.name;
2658 }
2659 arg->type = arg->type + ")";
2660 arg->name = name;
2661 }
2662 }
2663 // clear all yyextra->modifiers of the scope
2664 yyextra->modifiers.erase(scope);
2665 scope->parent()->removeSubEntry(scope);
2666 scope = nullptr;
2667 return TRUE;
2668 }
2669 }
2670 if (!scope->section.isFunction())
2671 { // not function section
2672 // iterate variables: get and apply yyextra->modifiers
2673 for (const auto &ce : scope->children())
2674 {
2675 if (!ce->section.isVariable() && !ce->section.isFunction() && !ce->section.isClass())
2676 continue;
void removeSubEntry(const Entry *e)
Definition entry.cpp:170
QCString & remove(size_t index, size_t len)
Definition qcstring.h:427
QCString name
Definition arguments.h:39
2677
2678 //cout<<ce->name<<", "<<mdfsMap.contains(ce->name.lower())<<mdfsMap.count()<<endl;
2679 if (mdfsMap.find(ce->name.lower().str())!=mdfsMap.end())
2680 applyModifiers(ce.get(), mdfsMap[ce->name.lower().str()]);
2681
2682 // remove prefix for variable names
2683 if (ce->section.isVariable() || ce->section.isFunction())
2684 {
2685 int end = ce->name.findRev(":");
2686 if (end != -1)
2687 ce->name.remove(0, end+1);
2688 }
2689 }
2690 }
DirIterator end(const DirIterator &) noexcept
Definition dir.cpp:175
2691
2692 // clear all yyextra->modifiers of the scope
2693 yyextra->modifiers.erase(scope);
2694
2695 // resolve procedures in types
static void resolveTypeBoundProcedures(Entry *scope)
2697
2698 return TRUE;
2699}

References applyModifiers(), Entry::children(), end(), FALSE, findArgument(), QCString::findRev(), initEntry(), INVALID_ENTRY, QCString::lower(), Argument::name, Entry::name, Entry::parent(), QCString::remove(), Entry::removeSubEntry(), resolveTypeBoundProcedures(), scanner_abort(), Entry::section, Entry::spec, QCString::str(), TRUE, Argument::type, and Entry::type.

Referenced by parseMain().

◆ extractBind()

static QCString extractBind ( const QCString & name)
static

remove useless spaces from bind statement

Definition at line 2229 of file fortranscanner.l.

2230{
2231 QCString parensPart = extractFromParens(name);
2232 if (parensPart.length() == 1)
2233 {
2234 return "bind(C)";
2235 }
2236 else
2237 {
2238 //strip 'c'
2239 parensPart = parensPart.mid(1).stripWhiteSpace();
2240 // strip ','
2241 parensPart = parensPart.mid(1).stripWhiteSpace();
2242 // name part
2243 parensPart = parensPart.mid(4).stripWhiteSpace();
2244 // = part
2245 parensPart = parensPart.mid(1).stripWhiteSpace();
QCString mid(size_t index, size_t len=static_cast< size_t >(-1)) const
Definition qcstring.h:226
static QCString extractFromParens(const QCString &name)
2246
2247 return "bind(C, name=" + parensPart + ")";
2248 }
2249}

References extractFromParens(), QCString::length(), QCString::mid(), and QCString::stripWhiteSpace().

Referenced by SymbolModifiers::operator|=().

◆ extractFromParens()

static QCString extractFromParens ( const QCString & name)
static

Extracts string which resides within parentheses of provided string.

Definition at line 2209 of file fortranscanner.l.

2210{
2211 QCString extracted = name;
2212 int start = extracted.find("(");
2213 if (start != -1)
2214 {
2215 extracted.remove(0, start+1);
2216 }
2217 int end = extracted.findRev(")");
2218 if (end != -1)
2219 {
2220 size_t length = extracted.length();
2221 extracted.remove(end, length);
2222 }
2223 extracted = extracted.stripWhiteSpace();
2224
2225 return extracted;
2226}

References end(), QCString::find(), QCString::findRev(), QCString::length(), QCString::remove(), and QCString::stripWhiteSpace().

Referenced by extractBind(), and SymbolModifiers::operator|=().

◆ findArgument()

static Argument * findArgument ( Entry * subprog,
QCString name,
bool byTypeName = FALSE )
static

For debugging purposes.

Find argument with given name in subprog entry.

Definition at line 2394 of file fortranscanner.l.

2395{
2396 QCString cname(name.lower());
2397 for (Argument &arg : subprog->argList)
2398 {
2399 if ((!byTypeName && arg.name.lower() == cname) ||
2400 (byTypeName && arg.type.lower() == cname)
2401 )
2402 {
2403 return &arg;
2404 }
2405 }
2406 return nullptr;
ArgumentList argList
member arguments as a list
Definition entry.h:194
2407}

References Entry::argList, FALSE, QCString::lower(), Argument::name, and Argument::type.

Referenced by endScope().

◆ getAmpersandAtTheStart()

static int getAmpersandAtTheStart ( const char * buf,
int length )
static

Definition at line 1756 of file fortranscanner.l.

1757{
1758 for(int i=0; i<length; i++)
1759 {
1760 switch(buf[i])
1761 {
1762 case ' ':
1763 case '\t':
1764 break;
1765 case '&':
1766 return i;
1767 default:
1768 return -1;
1769 }
1770 }
1771 return -1;
1772}

◆ getAmpOrExclAtTheEnd()

static int getAmpOrExclAtTheEnd ( const char * buf,
int length,
char ch )
static

Definition at line 1775 of file fortranscanner.l.

1776{
1777 // Avoid ampersands in string and yyextra->comments
1778 int parseState = Start;
1779 char quoteSymbol = 0;
1780 int ampIndex = -1;
1781 int commentIndex = -1;
1782 quoteSymbol = ch;
1783 if (ch != '\0') parseState = String;
1784
1785 for(int i=0; i<length && parseState!=Comment; i++)
1786 {
1787 // When in string, skip backslashes
1788 // Legacy code, not sure whether this is correct?
1789 if (parseState==String)
1790 {
1791 if (buf[i]=='\\') i++;
1792 }
1793
1794 switch(buf[i])
1795 {
1796 case '\'':
1797 case '"':
1798 // Close string, if quote symbol matches.
1799 // Quote symbol is set iff parseState==String
1800 if (buf[i]==quoteSymbol)
1801 {
1802 parseState = Start;
1803 quoteSymbol = 0;
1804 }
1805 // Start new string, if not already in string or comment
1806 else if (parseState==Start)
1807 {
1808 parseState = String;
1809 quoteSymbol = buf[i];
1810 }
1811 ampIndex = -1; // invalidate prev ampersand
1812 break;
1813 case '!':
1814 // When in string or comment, ignore exclamation mark
1815 if (parseState==Start)
1816 {
1817 parseState = Comment;
1818 commentIndex = i;
1819 }
1820 break;
1821 case ' ': // ignore whitespace
1822 case '\t':
1823 case '\n': // this may be at the end of line
1824 break;
1825 case '&':
1826 ampIndex = i;
1827 break;
1828 default:
1829 ampIndex = -1; // invalidate prev ampersand
1830 }
1831 }
1832
1833 if (ampIndex>=0)
1834 return ampIndex;
1835 else
1836 return commentIndex;
1837}

Referenced by prepassFixedForm().

◆ getLexerFILE()

static const char * getLexerFILE ( )
inlinestatic

Definition at line 261 of file fortranscanner.l.

261{return __FILE__;}

◆ getParameter()

static Argument * getParameter ( yyscan_t yyscanner,
const QCString & name )
static

Get the argument name.

Definition at line 3016 of file fortranscanner.l.

3017{
3018 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3019 // std::cout<<"addFortranParameter(): "<<name<<" DOCS:"<<(docs.isEmpty()?QCString("null"):docs)<<"\n";
3020 Argument *ret = nullptr;
3021 for (Argument &a:yyextra->current_root->argList)
3022 {
3023 if (a.name.lower()==name.lower())
3024 {
3025 ret=&a;
3026 //printf("parameter found: %s\n",(const char*)name);
3027 break;
3028 }
3029 } // for
3030 return ret;
3031}

References QCString::lower(), and Argument::name.

Referenced by updateVariablePrepassComment().

◆ handleCommentBlock()

static void handleCommentBlock ( yyscan_t yyscanner,
const QCString & doc,
bool brief )
static

Definition at line 3051 of file fortranscanner.l.

3052{
3053 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3054 bool hideInBodyDocs = Config_getBool(HIDE_IN_BODY_DOCS);
3055 if (yyextra->docBlockInBody && hideInBodyDocs)
3056 {
3057 yyextra->docBlockInBody = FALSE;
3058 return;
3059 }
3060 DBG_CTX((stderr,"call parseCommentBlock [%s]\n",qPrint(doc)));
3061 int lineNr = brief ? yyextra->current->briefLine : yyextra->current->docLine;
3062 int position=0;
3063 bool needsEntry = FALSE;
3064 Markdown markdown(yyextra->fileName,lineNr);
3065 GuardedSectionStack guards;
3066 QCString strippedDoc = stripIndentation(doc);
3067 QCString processedDoc = Config_getBool(MARKDOWN_SUPPORT) ? markdown.process(strippedDoc,lineNr) : strippedDoc;
3068 while (yyextra->commentScanner.parseCommentBlock(
3069 yyextra->thisParser,
3070 yyextra->docBlockInBody ? yyextra->subrCurrent.back().get() : yyextra->current.get(),
3071 processedDoc, // text
3072 yyextra->fileName, // file
3073 lineNr,
3074 yyextra->docBlockInBody ? FALSE : brief,
3075 yyextra->docBlockInBody ? FALSE : yyextra->docBlockJavaStyle,
3076 yyextra->docBlockInBody,
3077 yyextra->defaultProtection,
3078 position,
3079 needsEntry,
3080 Config_getBool(MARKDOWN_SUPPORT),
3081 &guards
3082 ))
3083 {
3084 DBG_CTX((stderr,"parseCommentBlock position=%d [%s] needsEntry=%d\n",position,doc.data()+position,needsEntry));
3085 if (needsEntry) addCurrentEntry(yyscanner,false);
3086 }
3087 DBG_CTX((stderr,"parseCommentBlock position=%d [%s] needsEntry=%d\n",position,doc.data()+position,needsEntry));
Helper class to process markdown formatted text.
Definition markdown.h:32
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition qcstring.h:159
std::stack< GuardedSection > GuardedSectionStack
Definition commentscan.h:48
#define Config_getBool(name)
Definition config.h:33
QCString stripIndentation(const QCString &s)
Definition util.cpp:6282
3088
3089 if (needsEntry) addCurrentEntry(yyscanner,false);
3090 yyextra->docBlockInBody = FALSE;
3091}

References addCurrentEntry(), Config_getBool, QCString::data(), DBG_CTX, FALSE, Markdown::process(), qPrint(), and stripIndentation().

Referenced by subrHandleCommentBlock(), and subrHandleCommentBlockResult().

◆ initEntry()

static void initEntry ( yyscan_t yyscanner)
static

Definition at line 2869 of file fortranscanner.l.

2870{
2871 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2872 if (yyextra->typeMode)
2873 {
2874 yyextra->current->protection = yyextra->typeProtection;
2875 }
2876 else if (yyextra->current_root && yyextra->current_root->section.isClass() && yyextra->current_root->spec.isInterface())
2877 {
2878 yyextra->current->protection = Protection::Public;
2879 }
2880 else if (yyextra->current_root && yyextra->current_root->section.isFunction())
2881 {
2882 yyextra->current->protection = Protection::Private;
2883 }
2884 else
2885 {
2886 yyextra->current->protection = yyextra->defaultProtection;
2887 }
2888 yyextra->current->mtype = MethodTypes::Method;
2889 yyextra->current->virt = Specifier::Normal;
2890 yyextra->current->isStatic = false;
2891 yyextra->current->lang = SrcLangExt::Fortran;
2892 yyextra->commentScanner.initGroupInfo(yyextra->current.get());
@ Fortran
Definition types.h:53
@ Normal
Definition types.h:29
2893}

References Fortran, Method, Normal, Private, and Public.

Referenced by addCurrentEntry(), addEntry(), addFrom(), endScope(), newEntry(), newEntry(), parseCompounds(), parseCompounds(), parseMain(), parseMain(), and startScope().

◆ initParser()

static void initParser ( yyscan_t yyscanner)
static

Definition at line 2863 of file fortranscanner.l.

2864{
2865 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2866 yyextra->last_entry.reset();
2867}

Referenced by parseMain().

◆ insertCharacter()

static void insertCharacter ( char * contents,
int length,
int pos,
char c )
static

Definition at line 1855 of file fortranscanner.l.

1856{
1857 // shift tail by one character
1858 for(int i=length; i>pos; i--)
1859 contents[i]=contents[i-1];
1860 // set the character
1861 contents[pos] = c;
1862}

Referenced by prepassFixedForm().

◆ locatePrepassComment()

static const CommentInPrepass * locatePrepassComment ( yyscan_t yyscanner,
int from,
int to )
static

Definition at line 1724 of file fortranscanner.l.

1725{
1726 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1727 //printf("Locate %d-%d\n", from, to);
1728 for (const auto &cip : yyextra->comments)
1729 { // todo: optimize
1730 int c = cip.column;
1731 //printf("Candidate %d\n", c);
1732 if (c>=from && c<=to)
1733 {
1734 // comment for previous variable or parameter
1735 return &cip;
1736 }
1737 }
1738 return nullptr;
1739}

References CommentInPrepass::column.

Referenced by updateVariablePrepassComment().

◆ newLine()

static void newLine ( yyscan_t yyscanner)
static

Definition at line 1700 of file fortranscanner.l.

1701{
1702 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1703 yyextra->lineNr++;
1704 yyextra->lineNr+=yyextra->lineCountPrepass;
1705 yyextra->lineCountPrepass=0;
1706 yyextra->comments.clear();
1707}

Referenced by vhdl::parser::CharStream::adjustBeginLineColumn().

◆ parseMain()

static void parseMain ( yyscan_t yyscanner,
const QCString & fileName,
const char * fileBuf,
const std::shared_ptr< Entry > & rt,
FortranFormat format )
static

Definition at line 3230 of file fortranscanner.l.

3232{
3233 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3234 char *tmpBuf = nullptr;
3235 initParser(yyscanner);
static void initParser(yyscan_t yyscanner)
3236
3237 if (fileBuf==nullptr || fileBuf[0]=='\0') return;
3238
3239 yyextra->defaultProtection = Protection::Public;
3240 yyextra->inputString = fileBuf;
3241 yyextra->inputPosition = 0;
3242 yyextra->inputStringPrepass = nullptr;
3243 yyextra->inputPositionPrepass = 0;
3244
3245 //yyextra->anonCount = 0; // don't reset per file
3246 yyextra->current_root = rt.get();
3247 yyextra->global_root = rt;
3248
3249 yyextra->isFixedForm = recognizeFixedForm(fileBuf,format);
bool recognizeFixedForm(const QCString &contents, FortranFormat format)
Definition util.cpp:6671
3250
3251 if (yyextra->isFixedForm)
3252 {
3253 yyextra->fixedCommentAfter = Config_getInt(FORTRAN_COMMENT_AFTER);
3254 msg("Prepassing fixed form of %s\n", qPrint(fileName));
3255 //printf("---strlen=%d\n", strlen(fileBuf));
3256 //clock_t start=clock();
void msg(const char *fmt,...)
Definition message.cpp:98
3257
3258 //printf("Input fixed form string:\n%s\n", fileBuf);
3259 //printf("===========================\n");
3260 yyextra->inputString = prepassFixedForm(fileBuf, nullptr,yyextra->fixedCommentAfter);
3261 Debug::print(Debug::FortranFixed2Free,0,"======== Fixed to Free format =========\n---- Input fixed form string ------- \n%s\n", fileBuf);
3262 Debug::print(Debug::FortranFixed2Free,0,"---- Resulting free form string ------- \n%s\n", yyextra->inputString);
3263 //printf("Resulting free form string:\n%s\n", yyextra->inputString);
3264 //printf("===========================\n");
@ FortranFixed2Free
Definition debug.h:39
static void print(DebugMask mask, int prio, const char *fmt,...)
Definition debug.cpp:81
const char * prepassFixedForm(const char *contents, int *hasContLine, int fixedCommentAfter)
3265
3266 //clock_t end=clock();
3267 //printf("CPU time used=%f\n", ((double) (end-start))/CLOCKS_PER_SEC);
3268 }
3269 else if (yyextra->inputString[strlen(fileBuf)-1] != '\n')
3270 {
3271 tmpBuf = (char *)malloc(strlen(fileBuf)+2);
3272 strcpy(tmpBuf,fileBuf);
3273 tmpBuf[strlen(fileBuf)]= '\n';
3274 tmpBuf[strlen(fileBuf)+1]= '\000';
3275 yyextra->inputString = tmpBuf;
3276 }
3277
3278 yyextra->lineNr= 1 ;
3279 yyextra->fileName = fileName;
3280 msg("Parsing file %s...\n",qPrint(yyextra->fileName));
3281
3282 yyextra->global_scope = rt.get();
3283 startScope(yyscanner,rt.get()); // implies yyextra->current_root = rt
3284 initParser(yyscanner);
3285 yyextra->commentScanner.enterFile(yyextra->fileName,yyextra->lineNr);
3286
3287 // add entry for the file
3288 yyextra->current = std::make_shared<Entry>();
3289 yyextra->current->lang = SrcLangExt::Fortran;
3290 yyextra->current->name = yyextra->fileName;
3291 yyextra->current->section = EntryType::makeSource();
3292 yyextra->file_root = yyextra->current;
3293 yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
3294 yyextra->current->lang = SrcLangExt::Fortran;
3295
3296 fortranscannerYYrestart( nullptr, yyscanner );
3297 {
3298 BEGIN( Start );
3299 }
3300
3301 fortranscannerYYlex(yyscanner);
3302 yyextra->commentScanner.leaveFile(yyextra->fileName,yyextra->lineNr);
3303
3304 if (yyextra->global_scope && yyextra->global_scope != INVALID_ENTRY)
3305 {
3306 endScope(yyscanner,yyextra->current_root, TRUE); // TRUE - global root
3307 }
static bool endScope(yyscan_t yyscanner, Entry *scope, bool isGlobalRoot=FALSE)
3308
3309 //debugCompounds(rt); //debug
3310
3311 rt->program.str(std::string());
3312 //delete yyextra->current; yyextra->current=0;
3313 yyextra->moduleProcedures.clear();
3314 if (tmpBuf)
3315 {
3316 free((char*)tmpBuf);
3317 yyextra->inputString=nullptr;
3318 }
3319 if (yyextra->isFixedForm)
3320 {
3321 free((char*)yyextra->inputString);
3322 yyextra->inputString=nullptr;
3323 }
3324
3325}

References Config_getInt, endScope(), Fortran, Debug::FortranFixed2Free, initParser(), INVALID_ENTRY, msg(), prepassFixedForm(), Debug::print(), Public, qPrint(), recognizeFixedForm(), startScope(), and TRUE.

Referenced by COutlineParser::parseInput(), FortranOutlineParser::parseInput(), LexOutlineParser::parseInput(), and PythonOutlineParser::parseInput().

◆ pop_state()

static void pop_state ( yyscan_t yyscanner)
inlinestatic

Definition at line 3415 of file fortranscanner.l.

3416{
3417 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3418 if ( yyg->yy_start_stack_ptr <= 0 )
3419 warn(yyextra->fileName,yyextra->lineNr,"Unexpected statement '%s'",yytext );
3420 else
3421 yy_pop_state(yyscanner);
#define warn(file, line, fmt,...)
Definition message.h:59
3422}

References warn.

◆ popBuffer()

static void popBuffer ( yyscan_t yyscanner)
static

Definition at line 2138 of file fortranscanner.l.

2139{
2140 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2141 DBG_CTX((stderr, "--POP--"));
2142 yyextra->includeStackPtr --;
2143 yy_delete_buffer( YY_CURRENT_BUFFER, yyscanner );
2144 yy_switch_to_buffer( yyextra->includeStack[yyextra->includeStackPtr], yyscanner );
2145}

References DBG_CTX.

Referenced by FortranOutlineParser::parsePrototype().

◆ prepassFixedForm()

const char * prepassFixedForm ( const char * contents,
int * hasContLine,
int fixedCommentAfter )

Definition at line 1866 of file fortranscanner.l.

1867{
1868 int column=0;
1869 int prevLineLength=0;
1870 int prevLineAmpOrExclIndex=-1;
1871 int skipped = 0;
1872 char prevQuote = '\0';
1873 char thisQuote = '\0';
1874 bool emptyLabel=TRUE;
1875 bool commented=FALSE;
1876 bool inSingle=FALSE;
1877 bool inDouble=FALSE;
1878 bool inBackslash=FALSE;
1879 bool fullCommentLine=TRUE;
1880 bool artificialComment=FALSE;
1881 bool spaces=TRUE;
1882 int newContentsSize = (int)strlen(contents)+3; // \000, \n (when necessary) and one spare character (to avoid reallocation)
1883 char* newContents = (char*)malloc(newContentsSize);
1884 int curLine = 1;
1885 size_t sizCont;
1886
1887 int j = -1;
1888 sizCont = strlen(contents);
1889 for(size_t i=0;i<sizCont;i++) {
1890 column++;
1891 char c = contents[i];
1892 if (artificialComment && c != '\n')
1893 {
1894 if (c == '!' && spaces)
1895 {
1896 newContents[j++] = c;
1897 artificialComment = FALSE;
1898 spaces = FALSE;
1899 skipped = 0;
1900 continue;
1901 }
1902 else if (c == ' ' || c == '\t') continue;
1903 else
1904 {
1905 spaces = FALSE;
1906 skipped++;
1907 continue;
1908 }
1909 }
1910
1911 j++;
1912 if (j>=newContentsSize-3) { // check for spare characters, which may be eventually used below (by & and '! ')
1913 newContents = (char*)realloc(newContents, newContentsSize+1000);
1914 newContentsSize = newContentsSize+1000;
1915 }
1916
1917 switch(c) {
1918 case '\n':
1919 if (!fullCommentLine)
1920 {
1921 prevLineLength=column;
1922 prevLineAmpOrExclIndex=getAmpOrExclAtTheEnd(&contents[i-prevLineLength+1], prevLineLength,prevQuote);
1923 if (prevLineAmpOrExclIndex == -1) prevLineAmpOrExclIndex = column - 1;
1924 if (skipped)
1925 {
1926 prevLineAmpOrExclIndex = -1;
1927 skipped = 0;
1928 }
1929 }
1930 else
1931 {
1932 prevLineLength+=column;
1933 /* 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) */
1934 if (hasContLine)
1935 {
1936 hasContLine[curLine - 1] = 1;
1937 }
1938 }
1939 artificialComment=FALSE;
1940 spaces=TRUE;
1941 fullCommentLine=TRUE;
1942 column=0;
1943 emptyLabel=TRUE;
1944 commented=FALSE;
1945 newContents[j]=c;
1946 prevQuote = thisQuote;
1947 curLine++;
1948 break;
1949 case ' ':
1950 case '\t':
1951 newContents[j]=c;
1952 break;
1953 case '\000':
1954 if (hasContLine)
1955 {
1956 free(newContents);
1957 return nullptr;
1958 }
1959 newContents[j]='\000';
1960 newContentsSize = (int)strlen(newContents);
1961 if (newContents[newContentsSize - 1] != '\n')
1962 {
1963 // to be on the safe side
1964 newContents = (char*)realloc(newContents, newContentsSize+2);
1965 newContents[newContentsSize] = '\n';
1966 newContents[newContentsSize + 1] = '\000';
1967 }
1968 return newContents;
1969 case '"':
1970 case '\'':
1971 case '\\':
1972 if ((column <= fixedCommentAfter) && (column!=6) && !commented)
1973 {
1974 // we have some special cases in respect to strings and escaped string characters
1975 fullCommentLine=FALSE;
1976 newContents[j]=c;
1977 if (c == '\\')
1978 {
1979 inBackslash = !inBackslash;
1980 break;
1981 }
1982 else if (c == '\'')
1983 {
1984 if (!inDouble)
1985 {
1986 inSingle = !inSingle;
1987 if (inSingle) thisQuote = c;
1988 else thisQuote = '\0';
1989 }
1990 break;
1991 }
1992 else if (c == '"')
1993 {
1994 if (!inSingle)
1995 {
1996 inDouble = !inDouble;
1997 if (inDouble) thisQuote = c;
1998 else thisQuote = '\0';
1999 }
2000 break;
2001 }
2002 }
2003 inBackslash = FALSE;
2004 // fallthrough
2005 case '#':
2006 case 'C':
2007 case 'c':
2008 case '*':
2009 case '!':
2010 if ((column <= fixedCommentAfter) && (column!=6))
2011 {
2012 emptyLabel=FALSE;
2013 if (column==1)
2014 {
2015 newContents[j]='!';
2016 commented = TRUE;
2017 }
2018 else if ((c == '!') && !inDouble && !inSingle)
2019 {
2020 newContents[j]=c;
2021 commented = TRUE;
2022 }
2023 else
2024 {
2025 if (!commented) fullCommentLine=FALSE;
2026 newContents[j]=c;
2027 }
2028 break;
2029 }
2030 // fallthrough
2031 default:
2032 if (!commented && (column < 6) && ((c - '0') >= 0) && ((c - '0') <= 9))
2033 { // remove numbers, i.e. labels from first 5 positions.
2034 newContents[j]=' ';
2035 }
2036 else if (column==6 && emptyLabel)
2037 { // continuation
2038 if (!commented) fullCommentLine=FALSE;
2039 if (c != '0')
2040 { // 0 not allowed as continuation character, see f95 standard paragraph 3.3.2.3
2041 newContents[j]=' ';
static int getAmpOrExclAtTheEnd(const char *buf, int length, char ch)
2042
2043 if (prevLineAmpOrExclIndex==-1)
2044 { // add & just before end of previous line
2045 /* first line is not a continuation line in code, just in snippets etc. */
2046 if (curLine != 1) insertCharacter(newContents, j+1, (j+1)-6-1, '&');
2047 j++;
2048 }
2049 else
2050 { // add & just before end of previous line comment
2051 /* first line is not a continuation line in code, just in snippets etc. */
2052 if (curLine != 1) insertCharacter(newContents, j+1, (j+1)-6-prevLineLength+prevLineAmpOrExclIndex+skipped, '&');
2053 skipped = 0;
2054 j++;
2055 }
2056 if (hasContLine)
2057 {
2058 hasContLine[curLine - 1] = 1;
2059 }
2060 }
2061 else
2062 {
2063 newContents[j]=c; // , just handle like space
2064 }
2065 prevLineLength=0;
2066 }
2067 else if ((column > fixedCommentAfter) && !commented)
2068 {
2069 // first non commented non blank character after position fixedCommentAfter
2070 if (c == '&')
2071 {
2072 newContents[j]=' ';
2073 }
2074 else if (c != '!')
2075 {
2076 // I'm not a possible start of doxygen comment
2077 newContents[j]=' ';
2078 artificialComment = TRUE;
2079 spaces=TRUE;
2080 skipped = 0;
2081 }
2082 else
2083 {
2084 newContents[j]=c;
2085 commented = TRUE;
2086 }
2087 }
2088 else
2089 {
2090 if (!commented) fullCommentLine=FALSE;
2091 newContents[j]=c;
2092 emptyLabel=FALSE;
2093 }
2094 break;
2095 }
2096 }
static void insertCharacter(char *contents, int length, int pos, char c)
2097
2098 if (hasContLine)
2099 {
2100 free(newContents);
2101 return nullptr;
2102 }
2103
2104 if (j==-1) // contents was empty
2105 {
2106 newContents = (char*)realloc(newContents, 2);
2107 newContents[0] = '\n';
2108 newContents[1] = '\000';
2109 }
2110 else if (newContents[j] == '\n') // content ended with newline
2111 {
2112 newContents = (char*)realloc(newContents, j+2);
2113 newContents[j + 1] = '\000';
2114 }
2115 else // content did not end with a newline
2116 {
2117 newContents = (char*)realloc(newContents, j+3);
2118 newContents[j + 1] = '\n';
2119 newContents[j + 2] = '\000';
2120 }
2121 return newContents;
2122}

References FALSE, getAmpOrExclAtTheEnd(), insertCharacter(), and TRUE.

Referenced by checkContLines(), and parseMain().

◆ pushBuffer()

static void pushBuffer ( yyscan_t yyscanner,
const QCString & buffer )
static

Definition at line 2124 of file fortranscanner.l.

2125{
2126 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2127 if (yyextra->includeStackCnt <= yyextra->includeStackPtr)
2128 {
2129 yyextra->includeStackCnt++;
2130 yyextra->includeStack = (YY_BUFFER_STATE *)realloc(yyextra->includeStack, yyextra->includeStackCnt * sizeof(YY_BUFFER_STATE));
2131 }
2132 yyextra->includeStack[yyextra->includeStackPtr++] = YY_CURRENT_BUFFER;
2133 yy_switch_to_buffer(yy_scan_string(buffer.data(),yyscanner),yyscanner);
2134
2135 DBG_CTX((stderr, "--PUSH--%s", qPrint(buffer)));
2136}

References QCString::data(), DBG_CTX, and qPrint().

Referenced by FortranOutlineParser::parsePrototype().

◆ resolveModuleProcedures()

void resolveModuleProcedures ( yyscan_t yyscanner,
Entry * current_root )
static

fill empty interface module procedures with info from corresponding module subprogs

TODO: handle procedures in used modules

Definition at line 2170 of file fortranscanner.l.

2171{
2172 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2173 if (yyextra->moduleProcedures.empty()) return;
2174
2175 // build up map of available functions
2176 std::map<std::string,std::shared_ptr<Entry>> procMap;
2177 {
2178 for (const auto& cf: current_root->children())
2179 {
2180 if (!cf->section.isFunction())
2181 continue;
2182
2183 // remove scope from name
2184 QCString name = cf->name;
2185 {
2186 int end = name.findRev(":");
2187 if (end != -1)
2188 name.remove(0, end+1);
2189 }
2190
2191 procMap.emplace(name.str(), cf);
2192 }
2193 }
2194
2195
2196 // for all module procedures
2197 for (const auto& ce1: yyextra->moduleProcedures)
2198 {
2199 if (procMap.find(ce1->name.str())!=procMap.end())
2200 {
2201 std::shared_ptr<Entry> proc = procMap[ce1->name.str()];
2202 copyEntry(ce1, proc);
2203 }
2204 } // for all interface module procedures
2205 yyextra->moduleProcedures.clear();
static void copyEntry(std::shared_ptr< Entry > dest, const std::shared_ptr< Entry > &src)
used to copy entry to an interface module procedure
2206}

References Entry::children(), copyEntry(), end(), QCString::findRev(), QCString::remove(), and QCString::str().

◆ resolveTypeBoundProcedures()

static void resolveTypeBoundProcedures ( Entry * scope)
static

search for types with type bound procedures (e.g. methods) and try to resolve their arguments

Definition at line 2704 of file fortranscanner.l.

2705{
2706 // map of all subroutines/functions
2707 bool procMapCreated = false;
2708 std::unordered_map<std::string,std::shared_ptr<Entry>> procMap;
2709
2710 // map of all abstract interfaces
2711 bool interfMapCreated = false;
2712 std::unordered_map<std::string,std::shared_ptr<Entry>> interfMap;
2713
2714 // iterate over all types
2715 for (const auto &ce: scope->children())
2716 {
2717 if (!ce->section.isClass())
2718 continue;
2719
2720 // handle non-"generic" non-"deferred" methods, copying the arguments from the implementation
2721 std::unordered_map<std::string,std::shared_ptr<Entry>> methodMap;
2722 for (auto &ct: ce->children())
2723 {
2724 if (!ct->section.isFunction())
2725 continue;
2726
2727 if (ct->type=="generic")
2728 continue;
2729
2730 if (ct->virt==Specifier::Pure)
2731 continue;
2732
2733 // set up the procMap
2734 if (!procMapCreated)
2735 {
2736 for (const auto &cf: scope->children())
2737 {
2738 if (cf->section.isFunction())
2739 {
2740 procMap.emplace(cf->name.str(), cf);
2741 }
2742 }
2743 procMapCreated = true;
2744 }
2745
2746 // found a (non-generic) method
2747 QCString implName = ct->args;
2748 if (procMap.find(implName.str())!=procMap.end())
2749 {
2750 std::shared_ptr<Entry> proc = procMap[implName.str()];
2751 ct->args = proc->args;
2752 ct->argList = ArgumentList(proc->argList);
2753 if (ct->brief.isEmpty())
2754 {
2755 ct->brief = proc->brief;
2756 ct->briefLine = proc->briefLine;
2757 ct->briefFile = proc->briefFile;
2758 }
2759 if (ct->doc.isEmpty())
2760 {
2761 ct->doc = proc->doc;
2762 ct->docLine = proc->docLine;
2763 ct->docFile = proc->docFile;
2764 }
2765 methodMap.emplace(ct->name.str(), ct);
2766 }
2767 }
This class represents an function or template argument list.
Definition arguments.h:60
2768
2769 // handle "deferred" methods (pure virtual functions), duplicating with arguments from the target abstract interface
2770 for (auto &ct: ce->children())
2771 {
2772 if (!ct->section.isFunction())
2773 continue;
2774
2775 if (ct->virt != Specifier::Pure)
2776 continue;
2777
2778 // set up the procMap
2779 if (!interfMapCreated)
2780 {
2781 for(const auto &cf: scope->children())
2782 {
2783 if (cf->section.isClass() && cf->spec.isInterface() && cf->type=="abstract")
2784 {
2785 std::shared_ptr<Entry> ci = cf->children().front();
2786 interfMap.emplace(ci->name.str(), ci);
2787 }
2788 }
2789 interfMapCreated = true;
2790 }
2791
2792 // found a (non-generic) method
2793 QCString implName = ct->args;
2794 if (interfMap.find(implName.str())!= interfMap.end() )
2795 {
2796 std::shared_ptr<Entry> proc = interfMap[implName.str()];
2797 ct->args = proc->args;
2798 ct->argList = ArgumentList(proc->argList);
2799 if (ct->brief.isEmpty())
2800 {
2801 ct->brief = proc->brief;
2802 ct->briefLine = proc->briefLine;
2803 ct->briefFile = proc->briefFile;
2804 }
2805 if (ct->doc.isEmpty())
2806 {
2807 ct->doc = proc->doc;
2808 ct->docLine = proc->docLine;
2809 ct->docFile = proc->docFile;
2810 }
2811
2812 methodMap.emplace(ct->name.str(), ct);
2813 }
2814 }
2815
2816 // handle "generic" methods (that is function overloading!), duplicating with arguments from the target method of the type
2817 {
2818 for (auto &ct: ce->children())
2819 {
2820 if (!ct->section.isFunction())
2821 continue;
2822
2823 if (ct->type!="generic")
2824 continue;
2825
2826 // found a generic method (already duplicated for each entry by the parser)
2827 QCString methodName = ct->args;
2828 if (methodMap.find(methodName.str()) != methodMap.end())
2829 {
2830 std::shared_ptr<Entry> method = methodMap[methodName.str()];
2831 ct->args = method->args;
2832 ct->argList = ArgumentList(method->argList);
2833 if (ct->brief.isEmpty())
2834 {
2835 ct->brief = method->brief;
2836 ct->briefLine = method->briefLine;
2837 ct->briefFile = method->briefFile;
2838 }
2839 if (ct->doc.isEmpty())
2840 {
2841 ct->doc = method->doc;
2842 ct->docLine = method->docLine;
2843 ct->docFile = method->docFile;
2844 }
2845 }
2846 }
2847 }
2848 }
2849}

References Entry::children(), Pure, and QCString::str().

Referenced by endScope().

◆ scanner_abort()

static void scanner_abort ( yyscan_t yyscanner)
static

Definition at line 3384 of file fortranscanner.l.

3385{
3386 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3387 fprintf(stderr,"********************************************************************\n");
3388 if (yyextra->blockLineNr == -1)
3389 {
3390 fprintf(stderr,"Error in file %s line: %d, state: %d(%s)\n",
3391 qPrint(yyextra->fileName),yyextra->lineNr,YY_START,stateToString(YY_START));
3392 }
3393 else
3394 {
3395 fprintf(stderr,"Error in file %s line: %d, state: %d(%s), starting command: '%s' probable line reference: %d\n",
3396 qPrint(yyextra->fileName),yyextra->lineNr,YY_START,stateToString(YY_START),qPrint(yyextra->blockString),yyextra->blockLineNr);
3397 }
3398 fprintf(stderr,"********************************************************************\n");
static const char * stateToString(int state)
3399
3400 bool start=FALSE;
3401
3402 for (const auto &ce : yyextra->global_root->children())
3403 {
3404 if (ce == yyextra->file_root) start=TRUE;
3405 if (start) ce->reset();
3406 }
3407
3408 // dummy call to avoid compiler warning
3409 (void)yy_top_state(yyscanner);
3410
3411 return;
3412 //exit(-1);
3413}

References FALSE, qPrint(), stateToString(), and TRUE.

Referenced by endScope().

◆ startCommentBlock()

static void startCommentBlock ( yyscan_t yyscanner,
bool brief )
static

Definition at line 3034 of file fortranscanner.l.

3035{
3036 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3037 if (brief)
3038 {
3039 yyextra->current->briefFile = yyextra->fileName;
3040 yyextra->current->briefLine = yyextra->lineNr;
3041 }
3042 else
3043 {
3044 yyextra->current->docFile = yyextra->fileName;
3045 yyextra->current->docLine = yyextra->lineNr;
3046 }
3047}

Referenced by initSpecialBlock(), initTriDoubleQuoteBlock(), and initTriSingleQuoteBlock().

◆ startScope()

static void startScope ( yyscan_t yyscanner,
Entry * scope )
static

Starts the new scope in fortran program. Consider using this function when starting module, interface, function or other program block.

See also
endScope()

Definition at line 2555 of file fortranscanner.l.

2556{
2557 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2558 //cout<<"start scope: "<<scope->name<<endl;
2559 yyextra->current_root= scope; /* start substructure */
2560
2561 yyextra->modifiers.emplace(scope, std::map<std::string,SymbolModifiers>());
2562
2563 // create new current with possibly different defaults...
2564 yyextra->current = std::make_shared<Entry>();
2565 initEntry(yyscanner);
2566}

References initEntry().

Referenced by addModule(), and parseMain().

◆ stateToString()

static const char * stateToString ( int state)
static

◆ subrHandleCommentBlock()

static void subrHandleCommentBlock ( yyscan_t yyscanner,
const QCString & doc,
bool brief )
static

Handle parameter description as defined after the declaration of the parameter.

Definition at line 3095 of file fortranscanner.l.

3096{
3097 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3098 QCString loc_doc;
3099 loc_doc = doc.stripWhiteSpace();
3100
3101 std::shared_ptr<Entry> tmp_entry = yyextra->current;
3102 yyextra->current = yyextra->subrCurrent.back(); // temporarily switch to the entry of the subroutine / function
3103
3104 // Still in the specification section so no inbodyDocs yet, but parameter documentation
3105 yyextra->current->inbodyDocs = "";
3106
3107 // strip \\param or @param, so we can do some extra checking. We will add it later on again.
3108 if (!loc_doc.stripPrefix("\\param") &&
3109 !loc_doc.stripPrefix("@param")
3110 ) (void)loc_doc; // Do nothing work has been done by stripPrefix; (void)loc_doc: to overcome 'empty controlled statement' warning
3111 loc_doc.stripWhiteSpace();
bool stripPrefix(const QCString &prefix)
Definition qcstring.h:198
3112
3113 // direction as defined with the declaration of the parameter
3114 int dir1 = yyextra->modifiers[yyextra->current_root][yyextra->argName.lower().str()].direction;
3115 // in description [in] is specified
3116 if (loc_doc.lower().find(directionParam[SymbolModifiers::IN]) == 0)
3117 {
3118 // check if with the declaration intent(in) or nothing has been specified
3121 {
3122 // strip direction
3123 loc_doc = loc_doc.right(loc_doc.length()-(int)strlen(directionParam[SymbolModifiers::IN]));
3124 loc_doc.stripWhiteSpace();
3125 // in case of empty documentation or (now) just name, consider it as no documentation
3126 if (!loc_doc.isEmpty() && (loc_doc.lower() != yyextra->argName.lower()))
3127 {
3128 handleCommentBlock(yyscanner,QCString("\n\n@param ") + directionParam[SymbolModifiers::IN] + " " +
3129 yyextra->argName + " " + loc_doc,brief);
3130 }
3131 }
3132 else
3133 {
3134 // something different specified, give warning and leave error.
3135 warn(yyextra->fileName,yyextra->lineNr, "Routine: %s%s inconsistency between intent attribute and documentation for parameter %s:",
3136 qPrint(yyextra->current->name),qPrint(yyextra->current->args),qPrint(yyextra->argName));
3137 handleCommentBlock(yyscanner,QCString("\n\n@param ") + directionParam[dir1] + " " +
3138 yyextra->argName + " " + loc_doc,brief);
3139 }
3140 }
3141 // analogous to the [in] case, here [out] direction specified
3142 else if (loc_doc.lower().find(directionParam[SymbolModifiers::OUT]) == 0)
3143 {
3146 {
3147 loc_doc = loc_doc.right(loc_doc.length()-(int)strlen(directionParam[SymbolModifiers::OUT]));
3148 loc_doc.stripWhiteSpace();
3149 if (loc_doc.isEmpty() || (loc_doc.lower() == yyextra->argName.lower()))
3150 {
3151 yyextra->current = tmp_entry;
3152 return;
3153 }
3154 handleCommentBlock(yyscanner,QCString("\n\n@param ") + directionParam[SymbolModifiers::OUT] + " " +
3155 yyextra->argName + " " + loc_doc,brief);
3156 }
3157 else
3158 {
3159 warn(yyextra->fileName,yyextra->lineNr, "Routine: %s%s inconsistency between intent attribute and documentation for parameter %s:",
3160 qPrint(yyextra->current->name),qPrint(yyextra->current->args),qPrint(yyextra->argName));
3161 handleCommentBlock(yyscanner,QCString("\n\n@param ") + directionParam[dir1] + " " +
3162 yyextra->argName + " " + loc_doc,brief);
3163 }
3164 }
3165 // analogous to the [in] case, here [in,out] direction specified
3166 else if (loc_doc.lower().find(directionParam[SymbolModifiers::INOUT]) == 0)
3167 {
3170 {
3171 loc_doc = loc_doc.right(loc_doc.length()-(int)strlen(directionParam[SymbolModifiers::INOUT]));
3172 loc_doc.stripWhiteSpace();
3173 if (!loc_doc.isEmpty() && (loc_doc.lower() != yyextra->argName.lower()))
3174 {
3175 handleCommentBlock(yyscanner,QCString("\n\n@param ") + directionParam[SymbolModifiers::INOUT] + " " +
3176 yyextra->argName + " " + loc_doc,brief);
3177 }
3178 }
3179 else
3180 {
3181 warn(yyextra->fileName,yyextra->lineNr, "Routine: %s%s inconsistency between intent attribute and documentation for parameter %s:",
3182 qPrint(yyextra->current->name),qPrint(yyextra->current->args),qPrint(yyextra->argName));
3183 handleCommentBlock(yyscanner,QCString("\n\n@param ") + directionParam[dir1] + " " +
3184 yyextra->argName + " " + loc_doc,brief);
3185 }
3186 }
3187 // analogous to the [in] case; here no direction specified
3188 else if (!loc_doc.isEmpty() && (loc_doc.lower() != yyextra->argName.lower()))
3189 {
3190 handleCommentBlock(yyscanner,QCString("\n\n@param ") + directionParam[dir1] + " " +
3191 yyextra->argName + " " + loc_doc,brief);
3192 }
static const char * directionParam[]
static void handleCommentBlock(yyscan_t yyscanner, const QCString &doc, bool brief)
3193
3194 // reset yyextra->current back to the part inside the routine
3195 yyextra->current = tmp_entry;
3196}

References directionParam, QCString::find(), handleCommentBlock(), SymbolModifiers::IN, SymbolModifiers::INOUT, QCString::isEmpty(), QCString::length(), QCString::lower(), SymbolModifiers::NONE_D, SymbolModifiers::OUT, qPrint(), QCString::right(), QCString::stripPrefix(), QCString::stripWhiteSpace(), and warn.

◆ subrHandleCommentBlockResult()

static void subrHandleCommentBlockResult ( yyscan_t yyscanner,
const QCString & doc,
bool brief )
static

Handle result description as defined after the declaration of the parameter.

Definition at line 3199 of file fortranscanner.l.

3200{
3201 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3202 QCString loc_doc;
3203 loc_doc = doc.stripWhiteSpace();
3204
3205 std::shared_ptr<Entry> tmp_entry = yyextra->current;
3206 yyextra->current = yyextra->subrCurrent.back(); // temporarily switch to the entry of the subroutine / function
3207
3208 // Still in the specification section so no inbodyDocs yet, but parameter documentation
3209 yyextra->current->inbodyDocs = "";
3210
3211 // strip \\returns or @returns. We will add it later on again.
3212 if (!loc_doc.stripPrefix("\\returns") &&
3213 !loc_doc.stripPrefix("\\return") &&
3214 !loc_doc.stripPrefix("@returns") &&
3215 !loc_doc.stripPrefix("@return")
3216 ) (void)loc_doc; // Do nothing work has been done by stripPrefix; (void)loc_doc: to overcome 'empty controlled statement' warning
3217 loc_doc.stripWhiteSpace();
3218
3219 if (!loc_doc.isEmpty() && (loc_doc.lower() != yyextra->argName.lower()))
3220 {
3221 handleCommentBlock(yyscanner,QCString("\n\n@returns ") + loc_doc,brief);
3222 }
3223
3224 // reset yyextra->current back to the part inside the routine
3225 yyextra->current = std::move(tmp_entry);
3226}

References handleCommentBlock(), QCString::isEmpty(), QCString::lower(), QCString::stripPrefix(), and QCString::stripWhiteSpace().

◆ truncatePrepass()

void truncatePrepass ( yyscan_t yyscanner,
int index )
static

Definition at line 1842 of file fortranscanner.l.

1843{
1844 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1845 size_t length = yyextra->inputStringPrepass.length();
1846 for (size_t i=index+1; i<length; i++) {
1847 if (yyextra->inputStringPrepass[i]=='!' && i<length-1 && yyextra->inputStringPrepass[i+1]=='<') { // save comment
1848 yyextra->comments.emplace_back(index, yyextra->inputStringPrepass.right(length-i-2));
1849 }
1850 }
1851 yyextra->inputStringPrepass.resize(index);
1852}

◆ updateVariablePrepassComment()

static void updateVariablePrepassComment ( yyscan_t yyscanner,
int from,
int to )
static

Definition at line 1741 of file fortranscanner.l.

1742{
1743 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1744 const CommentInPrepass *c = locatePrepassComment(yyscanner,from, to);
1745 if (c && yyextra->vtype == V_VARIABLE)
1746 {
1747 yyextra->last_entry->brief = c->str;
1748 }
1749 else if (c && yyextra->vtype == V_PARAMETER)
1750 {
1751 Argument *parameter = getParameter(yyscanner,yyextra->argName);
1752 if (parameter) parameter->docs = c->str;
1753 }
@ V_VARIABLE
@ V_PARAMETER
static const CommentInPrepass * locatePrepassComment(yyscan_t yyscanner, int from, int to)
static Argument * getParameter(yyscan_t yyscanner, const QCString &name)
QCString docs
Definition arguments.h:42
1754}

References Argument::docs, getParameter(), locatePrepassComment(), CommentInPrepass::str, V_PARAMETER, and V_VARIABLE.

◆ yylex()

int yylex ( yyscan_t yyscanner)

fortran parsing states

comment parsing states prototype parsing

Definition at line 369 of file fortranscanner.l.

373 {BS}[&]*{BS}!.*\n { /* skip lines with just comment. Note code was in free format or has been converted to it */
374 yyextra->lineCountPrepass ++;
375 }
376<Prepass>^{BS}\n { /* skip empty lines */
377 yyextra->lineCountPrepass ++;
378 }
379<*>^.*\n { // prepass: look for line continuations
380 yyextra->functionLine = FALSE;
381
382 DBG_CTX((stderr, "---%s", yytext));
383
384 int indexStart = getAmpersandAtTheStart(yytext, (int)yyleng);
385 int indexEnd = getAmpOrExclAtTheEnd(yytext, (int)yyleng, '\0');
386 if (indexEnd>=0 && yytext[indexEnd]!='&') //we are only interested in amp
387 {
388 indexEnd=-1;
389 }
static int getAmpersandAtTheStart(const char *buf, int length)
390
391 if (indexEnd<0)
392 { // ----- no ampersand as line continuation
393 if (YY_START == Prepass)
394 { // last line in "continuation"
395
396 // Only take input after initial ampersand
397 yyextra->inputStringPrepass+=(const char*)(yytext+(indexStart+1));
398
399 //printf("BUFFER:%s\n", (const char*)yyextra->inputStringPrepass);
400 pushBuffer(yyscanner,yyextra->inputStringPrepass);
401 yyextra->colNr = 0;
402 pop_state(yyscanner);
403 }
404 else
405 { // simple line
406 yyextra->colNr = 0;
407 REJECT;
408 }
409 }
410 else
411 { // ----- line with continuation
412 if (YY_START != Prepass)
413 {
414 yyextra->comments.clear();
415 yyextra->inputStringPrepass=QCString();
416 yy_push_state(Prepass,yyscanner);
417 }
static void pop_state(yyscan_t yyscanner)
static void pushBuffer(yyscan_t yyscanner, const QCString &buffer)
418
419 size_t length = yyextra->inputStringPrepass.length();
420
421 // Only take input after initial ampersand
422 yyextra->inputStringPrepass+=(const char*)(yytext+(indexStart+1));
423 yyextra->lineCountPrepass ++;
424
425 // cut off & and remove following comment if present
426 truncatePrepass(yyscanner,static_cast<int>(length) + indexEnd - indexStart - 1);
427 }
428 }
static void truncatePrepass(yyscan_t yyscanner, int index)
429
430
431 /*------ ignore strings that are not initialization strings */
432<String>\"|\' { // string ends with next quote without previous backspace
433 if (yytext[0]!=yyextra->stringStartSymbol)
434 {
435 yyextra->colNr -= (int)yyleng;
436 REJECT;
437 } // single vs double quote
438 if (yy_top_state(yyscanner) == Initialization ||
439 yy_top_state(yyscanner) == ArrayInitializer)
440 {
441 yyextra->initializer+=yytext;
442 }
443 pop_state(yyscanner);
444 }
445<String>[\x80-\xFF]* |
446<String>. { if (yy_top_state(yyscanner) == Initialization ||
447 yy_top_state(yyscanner) == ArrayInitializer)
448 {
449 yyextra->initializer+=yytext;
450 }
451 }
452<*>\"|\' { /* string starts */
453 if (YY_START == StrIgnore)
454 { yyextra->colNr -= (int)yyleng;
455 REJECT;
456 }; // ignore in simple yyextra->comments
457 yy_push_state(YY_START,yyscanner);
458 if (yy_top_state(yyscanner) == Initialization ||
459 yy_top_state(yyscanner) == ArrayInitializer)
460 {
461 yyextra->initializer+=yytext;
462 }
463 yyextra->stringStartSymbol=yytext[0]; // single or double quote
464 BEGIN(String);
465 }
466
467 /*------ ignore simple comment (not documentation yyextra->comments) */
468
469<*>"!"/[^<>\n] { if (YY_START == String || YY_START == DocCopyBlock)
470 { yyextra->colNr -= (int)yyleng;
471 REJECT;
472 } // "!" is ignored in strings
473 // skip comment line (without docu yyextra->comments "!>" "!<" )
474 /* ignore further "!" and ignore yyextra->comments in Strings */
475 if ((YY_START != StrIgnore) && (YY_START != String))
476 {
477 yy_push_state(YY_START,yyscanner);
478 BEGIN(StrIgnore);
479 yyextra->debugStr="*!";
480 DBG_CTX((stderr,"start comment %d\n",yyextra->lineNr));
481 }
482 }
483<StrIgnore>.?/\n { pop_state(yyscanner); // comment ends with endline character
484 DBG_CTX((stderr,"end comment %d %s\n",yyextra->lineNr,qPrint(yyextra->debugStr)));
485 } // comment line ends
486<StrIgnore>[\x80-\xFF]* |
487<StrIgnore>. { yyextra->debugStr+=yytext; }
488
489
490 /*------ use handling ------------------------------------------------------------*/
491
492<Start,ModuleBody,SubprogBody>"use"{BS_} {
493 if (YY_START == Start)
494 {
495 addModule(yyscanner);
496 yy_push_state(ModuleBody,yyscanner); //anon program
497 }
498 yy_push_state(Use,yyscanner);
499 }
500<Use>{ID} {
501 DBG_CTX((stderr,"using dir %s\n",yytext));
502 yyextra->current->name=yytext;
503 yyextra->current->name=yyextra->current->name.lower();
504 yyextra->current->fileName = yyextra->fileName;
505 yyextra->current->section=EntryType::makeUsingDir();
506 yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
507 yyextra->current->lang = SrcLangExt::Fortran;
508 pop_state(yyscanner);
509 }
510<Use>{ID}/, {
511 yyextra->useModuleName=yytext;
512 yyextra->useModuleName=yyextra->useModuleName.lower();
513 }
514<Use>,{BS}"ONLY" { BEGIN(UseOnly);
515 }
516<UseOnly>{BS},{BS} {}
517<UseOnly>{ID} {
518 yyextra->current->name= yyextra->useModuleName+"::"+yytext;
519 yyextra->current->name=yyextra->current->name.lower();
520 yyextra->current->fileName = yyextra->fileName;
521 yyextra->current->section=EntryType::makeUsingDecl();
522 yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
523 yyextra->current->lang = SrcLangExt::Fortran;
524 }
525<Use,UseOnly>"\n" {
526 yyextra->colNr -= 1;
527 unput(*yytext);
528 pop_state(yyscanner);
529 }
530
531 /* INTERFACE definitions */
532<Start,ModuleBody,SubprogBody>{
533^{BS}interface{IDSYM}+ { /* variable with interface prefix */ }
534^{BS}interface { yyextra->ifType = IF_SPECIFIC;
535 yy_push_state(InterfaceBody,yyscanner);
536 // do not start a scope here, every
537 // interface body is a scope of its own
538 }
539
540^{BS}abstract{BS_}interface { yyextra->ifType = IF_ABSTRACT;
541 yy_push_state(InterfaceBody,yyscanner);
542 // do not start a scope here, every
543 // interface body is a scope of its own
544 }
545
546^{BS}interface{BS_}{ID}{ARGS}? { yyextra->ifType = IF_GENERIC;
547 yyextra->current->bodyLine = yyextra->lineNr + yyextra->lineCountPrepass + 1; // we have to be at the line after the definition and we have to take continuation lines into account.
548 yy_push_state(InterfaceBody,yyscanner);
549
550 // extract generic name
551 QCString name = QCString(yytext).stripWhiteSpace();
552 name = name.right(name.length() - 9).stripWhiteSpace().lower();
553 addInterface(yyscanner,name, yyextra->ifType);
554 startScope(yyscanner,yyextra->last_entry.get());
555 }
static void addInterface(yyscan_t yyscanner, QCString name, InterfaceType type)
556}
557
558<InterfaceBody>^{BS}end{BS}interface({BS_}{ID})? {
559 // end scope only if GENERIC interface
560 if (yyextra->ifType == IF_GENERIC)
561 {
562 yyextra->last_entry->parent()->endBodyLine = yyextra->lineNr - 1;
563 }
564 if (yyextra->ifType == IF_GENERIC && !endScope(yyscanner,yyextra->current_root))
565 {
566 yyterminate();
567 }
568 yyextra->ifType = IF_NONE;
569 pop_state(yyscanner);
570 }
#define yyterminate()
static void endScope(yyscan_t yyscanner)
end scope
571<InterfaceBody>module{BS}procedure { yy_push_state(YY_START,yyscanner);
572 BEGIN(ModuleProcedure);
573 }
574<ModuleProcedure>{ID} { QCString name = QCString(yytext).lower();
575 if (yyextra->ifType == IF_ABSTRACT || yyextra->ifType == IF_SPECIFIC)
576 {
577 addInterface(yyscanner,name, yyextra->ifType);
578 startScope(yyscanner,yyextra->last_entry.get());
579 }
580
581 yyextra->current->section = EntryType::makeFunction();
582 yyextra->current->name = name;
583 yyextra->moduleProcedures.push_back(yyextra->current);
584 addCurrentEntry(yyscanner,true);
585 }
586<ModuleProcedure>"\n" { yyextra->colNr -= 1;
587 unput(*yytext);
588 pop_state(yyscanner);
589 }
590<InterfaceBody>. {}
591
592 /*-- Contains handling --*/
593<Start>^{BS}{CONTAINS}/({BS}|\n|!|;) {
594 if (YY_START == Start)
595 {
596 addModule(yyscanner);
597 yy_push_state(ModuleBodyContains,yyscanner); //anon program
598 }
599 }
600<ModuleBody>^{BS}{CONTAINS}/({BS}|\n|!|;) { BEGIN(ModuleBodyContains); }
601<SubprogBody>^{BS}{CONTAINS}/({BS}|\n|!|;) { BEGIN(SubprogBodyContains); }
602<TypedefBody>^{BS}{CONTAINS}/({BS}|\n|!|;) { BEGIN(TypedefBodyContains); }
603
604 /*------ module handling ------------------------------------------------------------*/
605<Start>block{BS}data{BS}{ID_} { //
606 yyextra->vtype = V_IGNORE;
607 yy_push_state(BlockData,yyscanner);
608 yyextra->defaultProtection = Protection::Public;
609 }
@ V_IGNORE
610<Start>module|program{BS_} { //
611 yyextra->vtype = V_IGNORE;
612 if (yytext[0]=='m' || yytext[0]=='M')
613 {
614 yy_push_state(Module,yyscanner);
615 }
616 else
617 {
618 yy_push_state(Program,yyscanner);
619 }
620 yyextra->defaultProtection = Protection::Public;
621 }
622<BlockData>^{BS}"end"({BS}(block{BS}data)({BS_}{ID})?)?{BS}/(\n|!|;) { // end block data
623 //if (!endScope(yyscanner,yyextra->current_root))
624 // yyterminate();
625 yyextra->defaultProtection = Protection::Public;
626 pop_state(yyscanner);
627 }
628<Start,ModuleBody,ModuleBodyContains>"end"({BS}(module|program)({BS_}{ID})?)?{BS}/(\n|!|;) { // end module
629 resolveModuleProcedures(yyscanner,yyextra->current_root);
630 if (!endScope(yyscanner,yyextra->current_root))
631 {
632 yyterminate();
633 }
634 yyextra->defaultProtection = Protection::Public;
635 if (yyextra->global_scope)
636 {
637 if (yyextra->global_scope != INVALID_ENTRY)
638 {
639 yy_push_state(Start,yyscanner);
640 }
641 else
642 {
643 pop_state(yyscanner); // cannot pop artrificial entry
644 }
645 }
646 else
647 {
648 yy_push_state(Start,yyscanner);
649 yyextra->global_scope = INVALID_ENTRY; // signal that the yyextra->global_scope has already been used.
650 }
651 }
static void resolveModuleProcedures(yyscan_t yyscanner, Entry *current_root)
fill empty interface module procedures with info from corresponding module subprogs
652<Module>{ID} {
653 addModule(yyscanner, QCString(yytext), TRUE);
654 BEGIN(ModuleBody);
655 }
656<Program>{ID} {
657 addModule(yyscanner, QCString(yytext), FALSE);
658 BEGIN(ModuleBody);
659 }
660
661 /*------- access specification --------------------------------------------------------------------------*/
662
663<ModuleBody,TypedefBody,TypedefBodyContains>private/{BS}(\n|"!") {
664 yyextra->defaultProtection = Protection::Private;
665 yyextra->current->protection = yyextra->defaultProtection ;
666 }
667<ModuleBody,TypedefBody,TypedefBodyContains>public/{BS}(\n|"!") {
668 yyextra->defaultProtection = Protection::Public;
669 yyextra->current->protection = yyextra->defaultProtection ;
670 }
671
672 /*------- type definition -------------------------------------------------------------------------------*/
673
674<ModuleBody>^{BS}type{BS}"=" {}
675<Start,ModuleBody>^{BS}type/[^a-z0-9_] {
676 if (YY_START == Start)
677 {
678 addModule(yyscanner,QCString());
679 yy_push_state(ModuleBody,yyscanner); //anon program
680 }
681
682 yy_push_state(Typedef,yyscanner);
683 yyextra->current->protection = Protection::Package; // invalid in Fortran, replaced below
684 yyextra->typeProtection = Protection::Public;
685 yyextra->typeMode = true;
686 }
@ Package
Definition types.h:26
687<Typedef>{
688{COMMA} {}
689
690{BS}"::"{BS} {}
691
692abstract {
693 yyextra->current->spec.setAbstractClass(true);
694 }
695extends{ARGS} {
696 QCString basename = extractFromParens(yytext).lower();
697 yyextra->current->extends.emplace_back(basename, Protection::Public, Specifier::Normal);
698 }
699public {
700 yyextra->current->protection = Protection::Public;
701 }
702private {
703 yyextra->current->protection = Protection::Private;
704 }
705{LANGUAGE_BIND_SPEC} {
706 /* ignored for now */
707 }
708{ID} { /* type name found */
709 yyextra->current->section = EntryType::makeClass();
710 yyextra->current->spec.setStruct(true);
711 yyextra->current->name = yytext;
712 yyextra->current->fileName = yyextra->fileName;
713 yyextra->current->bodyLine = yyextra->lineNr;
714 yyextra->current->startLine = yyextra->lineNr;
715
716 /* if type is part of a module, mod name is necessary for output */
717 if (yyextra->current_root &&
718 (yyextra->current_root->section.isClass() ||
719 yyextra->current_root->section.isNamespace()))
720 {
721 yyextra->current->name = yyextra->current_root->name + "::" + yyextra->current->name;
722 }
723
724 // set modifiers to allow adjusting public/private in surrounding module scope
725 if( yyextra->current->protection == Protection::Package )
726 {
727 yyextra->current->protection = yyextra->defaultProtection;
728 }
729 else if( yyextra->current->protection == Protection::Public )
730 {
731 yyextra->modifiers[yyextra->current_root][yyextra->current->name.lower().str()] |= QCString("public");
732 }
733 else if( yyextra->current->protection == Protection::Private )
734 {
735 yyextra->modifiers[yyextra->current_root][yyextra->current->name.lower().str()] |= QCString("private");
736 }
737
738 addCurrentEntry(yyscanner,true);
739 startScope(yyscanner,yyextra->last_entry.get());
740 BEGIN(TypedefBody);
741 }
742}
743
744<TypedefBodyContains>{ /* Type Bound Procedures */
745^{BS}PROCEDURE{ARGS}? {
746 yyextra->current->type = QCString(yytext).simplifyWhiteSpace().lower();
747 }
QCString simplifyWhiteSpace() const
return a copy of this string with leading and trailing whitespace removed and multiple whitespace cha...
Definition qcstring.cpp:185
748^{BS}final {
749 yyextra->current->spec.setFinal(true);
750 yyextra->current->type = QCString(yytext).simplifyWhiteSpace();
751 }
752^{BS}generic {
753 yyextra->current->type = QCString(yytext).simplifyWhiteSpace();
754 }
755{COMMA} {
756 }
757{ATTR_SPEC} {
758 yyextra->currentModifiers |= QCString(yytext).stripWhiteSpace();
759 }
760{BS}"::"{BS} {
761 }
762{ID} {
763 QCString name = yytext;
764 yyextra->modifiers[yyextra->current_root][name.lower().str()] |= yyextra->currentModifiers;
765 yyextra->current->section = EntryType::makeFunction();
766 yyextra->current->name = name;
767 // check for procedure(name)
768 if (yyextra->current->type.find('(') != -1)
769 {
770 yyextra->current->args = extractFromParens(yyextra->current->type).stripWhiteSpace();
771 }
772 else
773 {
774 yyextra->current->args = name.lower(); // target procedure name if no => is given
775 }
776 yyextra->current->fileName = yyextra->fileName;
777 yyextra->current->bodyLine = yyextra->lineNr;
778 yyextra->current->startLine = yyextra->lineNr;
779 addCurrentEntry(yyscanner,true);
780 }
781{BS}"=>"[^(\n|\!)]* { /* Specific bindings come after the ID. */
782 QCString tmp = yytext;
783 int i = tmp.find("=>");
784 if (i!=-1)
785 {
786 tmp.remove(0, i+2);
787 }
788 tmp = tmp.simplifyWhiteSpace().lower();
789 if (yyextra->last_entry->type == "generic")
790 {
791 // duplicate entries for each overloaded variant
792 // (parse through medhod1,method2, methodN, ...
793 //printf("Parsing through %s for generic method %s.\n", tmp.data(), last_entry->name.data());
794 i = tmp.find(",");
795 while (i>0)
796 {
797 copyEntry(yyextra->current, yyextra->last_entry);
798 yyextra->current->name = yyextra->last_entry->name;
799 yyextra->current->section = EntryType::makeFunction();
800 yyextra->last_entry->args = tmp.left(i).stripWhiteSpace();
801 //printf("Found %s.\n", last_entry->args.data());
802 addCurrentEntry(yyscanner,true);
803 tmp = tmp.remove(0,i+1).stripWhiteSpace();
804 i = tmp.find(",");
805 }
806 }
807 //printf("Target function: %s\n", tmp.data());
808 yyextra->last_entry->args = tmp;
809 }
QCString left(size_t len) const
Definition qcstring.h:214
810"\n" {
811 yyextra->currentModifiers = SymbolModifiers();
812 newLine(yyscanner);
813 yyextra->docBlock.clear();
814 }
static void newLine(yyscan_t yyscanner)
Holds yyextra->modifiers (ie attributes) for one symbol (variable, function, etc)
815}
816
817
818<TypedefBody,TypedefBodyContains>{
819^{BS}"end"{BS}"type"({BS_}{ID})?{BS}/(\n|!|;) { /* end type definition */
820 yyextra->last_entry->parent()->endBodyLine = yyextra->lineNr;
821 if (!endScope(yyscanner,yyextra->current_root))
822 {
823 yyterminate();
824 }
825 yyextra->typeMode = false;
826 pop_state(yyscanner);
827 }
828^{BS}"end"{BS}/(\n|!|;) { /* incorrect end type definition */
829 warn(yyextra->fileName,yyextra->lineNr, "Found 'END' instead of 'END TYPE'");
830 yyextra->last_entry->parent()->endBodyLine = yyextra->lineNr;
831 if (!endScope(yyscanner,yyextra->current_root))
832 {
833 yyterminate();
834 }
835 yyextra->typeMode = false;
836 pop_state(yyscanner);
837 }
838}
839
840 /*------- module/global/typedef variable ---------------------------------------------------*/
841
842<SubprogBody,SubprogBodyContains>^{BS}[0-9]*{BS}"end"({BS}{SUBPROG}({BS_}{ID})?)?{BS}/(\n|!|;) {
843 //
844 // ABSTRACT and specific interfaces are stored
845 // in a scope of their own, even if multiple
846 // are group in one INTERFACE/END INTERFACE block.
847 //
848 if (yyextra->ifType == IF_ABSTRACT || yyextra->ifType == IF_SPECIFIC)
849 {
850 endScope(yyscanner,yyextra->current_root);
851 yyextra->last_entry->endBodyLine = yyextra->lineNr - 1;
852 }
853 yyextra->current_root->endBodyLine = yyextra->lineNr - 1;
854
855 if (!endScope(yyscanner,yyextra->current_root))
856 {
857 yyterminate();
858 }
859 yyextra->subrCurrent.pop_back();
860 yyextra->vtype = V_IGNORE;
861 pop_state(yyscanner) ;
862 }
863<BlockData>{
864{ID} {
865 }
866}
867<Start,ModuleBody,TypedefBody,SubprogBody,FEnum>{
868^{BS}{TYPE_SPEC}/{SEPARATE} {
869 yyextra->last_enum.reset();
870 if (YY_START == FEnum)
871 {
872 yyextra->argType = "@"; // enum marker
873 }
874 else
875 {
876 yyextra->argType = QCString(yytext).simplifyWhiteSpace().lower();
877 }
878 yyextra->current->bodyLine = yyextra->lineNr + 1;
879 yyextra->current->endBodyLine = yyextra->lineNr + yyextra->lineCountPrepass;
880 /* variable declaration starts */
881 if (YY_START == Start)
882 {
883 addModule(yyscanner);
884 yy_push_state(ModuleBody,yyscanner); //anon program
885 }
886 yy_push_state(AttributeList,yyscanner);
887 }
888{EXTERNAL_STMT}/({BS}"::"|{BS_}{ID}) {
889 /* external can be a "type" or an attribute */
890 if (YY_START == Start)
891 {
892 addModule(yyscanner);
893 yy_push_state(ModuleBody,yyscanner); //anon program
894 }
895 QCString tmp = yytext;
896 yyextra->currentModifiers |= tmp.stripWhiteSpace();
897 yyextra->argType = QCString(yytext).simplifyWhiteSpace().lower();
898 yy_push_state(AttributeList,yyscanner);
899 }
900{ATTR_STMT}/{BS_}{ID} |
901{ATTR_STMT}/{BS}"::" {
902 /* attribute statement starts */
903 DBG_CTX((stderr,"5=========> Attribute statement: %s\n", yytext));
904 if (YY_START == Start)
905 {
906 addModule(yyscanner);
907 yy_push_state(ModuleBody,yyscanner); //anon program
908 }
909 QCString tmp = yytext;
910 yyextra->currentModifiers |= tmp.stripWhiteSpace();
911 yyextra->argType="";
912 yy_push_state(YY_START,yyscanner);
913 BEGIN( AttributeList ) ;
914 }
915"common" {
916 if (YY_START == Start)
917 {
918 addModule(yyscanner);
919 yy_push_state(ModuleBody,yyscanner); //anon program
920 }
921 }
922{ID} {
923 if (YY_START == Start)
924 {
925 addModule(yyscanner);
926 yy_push_state(ModuleBody,yyscanner); //anon program
927 }
928 }
929^{BS}"type"{BS_}"is"/{BT_} {}
930^{BS}"type"{BS}"=" {}
931^{BS}"class"{BS_}"is"/{BT_} {}
932^{BS}"class"{BS_}"default" {}
933}
934<AttributeList>{
935{COMMA} {}
936{BS} {}
937{LANGUAGE_BIND_SPEC} {
938 yyextra->currentModifiers |= yytext;
939 }
940{ATTR_SPEC}. { /* update yyextra->current yyextra->modifiers when it is an ATTR_SPEC and not a variable name */
941 /* buyyextra->625519 */
942 char chr = yytext[(int)yyleng-1];
943 if (isId(chr))
944 {
945 yyextra->colNr -= (int)yyleng;
946 REJECT;
947 }
948 else
949 {
950 QCString tmp = yytext;
951 tmp = tmp.left(tmp.length() - 1);
952 yyextra->colNr -= 1;
953 unput(yytext[(int)yyleng-1]);
954 yyextra->currentModifiers |= (tmp);
955 }
956 }
bool isId(int c)
Definition util.h:202
957"::" { /* end attribute list */
958 BEGIN( FVariable );
959 }
960. { /* unknown attribute, consider variable name */
961 //cout<<"start variables, unput "<<*yytext<<endl;
962 yyextra->colNr -= 1;
963 unput(*yytext);
964 BEGIN( FVariable );
965 }
966}
967
968<FVariable>{BS} {}
969<FVariable>{OPERATOR_ID} { /* parse operator access statements "public :: operator(==)" */
970 QCString name = QCString(yytext).stripWhiteSpace().lower();
971 /* if variable/type/etc is part of a module, mod name is necessary for output */
972 // get surrounding state
973 int currentState = YY_START;
974 pop_state(yyscanner);
975 int outerState = YY_START;
976 yy_push_state(currentState,yyscanner);
977 if( outerState == Start || outerState == ModuleBody )
978 {
979 if ((yyextra->current_root) &&
980 (yyextra->current_root->section.isClass() ||
981 yyextra->current_root->section.isNamespace()))
982 {
983 name = yyextra->current_root->name + "::" + name;
984 }
985 }
986 /* remember attributes for the symbol */
987 yyextra->modifiers[yyextra->current_root][name.str()] |= yyextra->currentModifiers;
988 }
989<FVariable>{ID} { /* parse variable declaration */
990 //cout << "5=========> got variable: " << yyextra->argType << "::" << yytext << endl;
991 /* work around for bug in QCString.replace (QCString works) */
992 QCString name=yytext;
993 name = name.lower();
994 /* if variable/type/etc is part of a module, mod name is necessary for output */
995 if ((yyextra->current_root) && yyextra->current_root->section.isNamespace())
996 {
997 name = yyextra->current_root->name + "::" + name;
998 }
999 /* remember attributes for the symbol */
1000 yyextra->modifiers[yyextra->current_root][name.lower().str()] |= yyextra->currentModifiers;
1001 yyextra->argName= name;
1002
1003 yyextra->vtype= V_IGNORE;
1004 if (!yyextra->argType.isEmpty() && !yyextra->current_root->section.isFunction())
1005 { // new variable entry
1006 yyextra->vtype = V_VARIABLE;
1007 yyextra->current->section = EntryType::makeVariable();
1008 yyextra->current->name = yyextra->argName;
1009 yyextra->current->type = yyextra->argType;
1010 yyextra->current->fileName = yyextra->fileName;
1011 yyextra->current->bodyLine = yyextra->lineNr; // used for source reference
1012 yyextra->current->startLine = yyextra->lineNr;
1013 if (yyextra->argType == "@")
1014 {
1015 yyextra->current_root->copyToSubEntry(yyextra->current);
1016 // add to the scope surrounding the enum (copy!)
1017 yyextra->last_enum = yyextra->current;
1018 yyextra->current_root->parent()->moveToSubEntryAndRefresh(yyextra->current);
1019 initEntry(yyscanner);
1020 }
1021 else
1022 {
1023 addCurrentEntry(yyscanner,true);
1024 }
1025 }
1026 else if (!yyextra->argType.isEmpty())
1027 { // declaration of parameter list: add type for corr. parameter
1028 Argument *parameter = getParameter(yyscanner,yyextra->argName);
1029 if (parameter)
1030 {
1031 yyextra->vtype= V_PARAMETER;
1032 if (!yyextra->argType.isEmpty()) parameter->type=yyextra->argType.stripWhiteSpace();
1033 if (!yyextra->docBlock.isEmpty())
1034 {
1035 subrHandleCommentBlock(yyscanner,yyextra->docBlock,TRUE);
1036 }
1037 }
1038 // save, it may be function return type
1039 if (parameter)
1040 {
1041 yyextra->modifiers[yyextra->current_root][name.lower().str()].type = yyextra->argType;
1042 }
1043 else
1044 {
1045 if ((yyextra->current_root->name.lower() == yyextra->argName.lower()) ||
1046 (yyextra->modifiers[yyextra->current_root->parent()][yyextra->current_root->name.lower().str()].returnName.lower() == yyextra->argName.lower()))
1047 {
1048 int strt = yyextra->current_root->type.find("function");
1049 QCString lft;
1050 QCString rght;
1051 if (strt != -1)
1052 {
1053 yyextra->vtype = V_RESULT;
1054 lft = "";
1055 rght = "";
1056 if (strt != 0) lft = yyextra->current_root->type.left(strt).stripWhiteSpace();
1057 if ((yyextra->current_root->type.length() - strt - strlen("function"))!= 0)
1058 {
1059 rght = yyextra->current_root->type.right(yyextra->current_root->type.length() - strt - (int)strlen("function")).stripWhiteSpace();
1060 }
1061 yyextra->current_root->type = lft;
1062 if (rght.length() > 0)
1063 {
1064 if (yyextra->current_root->type.length() > 0) yyextra->current_root->type += " ";
1065 yyextra->current_root->type += rght;
1066 }
1067 if (yyextra->argType.stripWhiteSpace().length() > 0)
1068 {
1069 if (yyextra->current_root->type.length() > 0) yyextra->current_root->type += " ";
1070 yyextra->current_root->type += yyextra->argType.stripWhiteSpace();
1071 }
1072 if (yyextra->current_root->type.length() > 0) yyextra->current_root->type += " ";
1073 yyextra->current_root->type += "function";
1074 if (!yyextra->docBlock.isEmpty())
1075 {
1076 subrHandleCommentBlockResult(yyscanner,yyextra->docBlock,TRUE);
1077 }
1078 }
1079 else
1080 {
1081 yyextra->current_root->type += " " + yyextra->argType.stripWhiteSpace();
1082 }
1083 yyextra->current_root->type = yyextra->current_root->type.stripWhiteSpace();
1084 yyextra->modifiers[yyextra->current_root][name.lower().str()].type = yyextra->current_root->type;
1085 }
1086 else
1087 {
1088 yyextra->modifiers[yyextra->current_root][name.lower().str()].type = yyextra->argType;
1089 }
1090 }
1091 // any accumulated doc for argument should be emptied,
1092 // because it is handled other way and this doc can be
1093 // unexpectedly passed to the next member.
1094 yyextra->current->doc.clear();
1095 yyextra->current->brief.clear();
1096 }
1097 }
@ V_RESULT
static void subrHandleCommentBlock(yyscan_t yyscanner, const QCString &doc, bool brief)
Handle parameter description as defined after the declaration of the parameter.
static void subrHandleCommentBlockResult(yyscan_t yyscanner, const QCString &doc, bool brief)
Handle result description as defined after the declaration of the parameter.
1098<FVariable>{ARGS} { /* dimension of the previous entry. */
1099 QCString name(yyextra->argName);
1100 QCString attr("dimension");
1101 attr += yytext;
1102 yyextra->modifiers[yyextra->current_root][name.lower().str()] |= attr;
1103 }
1104<FVariable>{COMMA} { //printf("COMMA: %d<=..<=%d\n", yyextra->colNr-(int)yyleng, yyextra->colNr);
1105 // locate !< comment
1106 updateVariablePrepassComment(yyscanner,yyextra->colNr-(int)yyleng, yyextra->colNr);
1107 }
static void updateVariablePrepassComment(yyscan_t yyscanner, int from, int to)
1108<FVariable>{BS}"=" {
1109 yy_push_state(YY_START,yyscanner);
1110 yyextra->initializer="=";
1111 yyextra->initializerScope = yyextra->initializerArrayScope = 0;
1112 BEGIN(Initialization);
1113 }
1114<FVariable>"\n" { yyextra->currentModifiers = SymbolModifiers();
1115 pop_state(yyscanner); // end variable declaration list
1116 newLine(yyscanner);
1117 yyextra->docBlock.clear();
1118 }
1119<FVariable>";".*"\n" { yyextra->currentModifiers = SymbolModifiers();
1120 pop_state(yyscanner); // end variable declaration list
1121 yyextra->docBlock.clear();
1122 yyextra->inputStringSemi = " \n"+QCString(yytext+1);
1123 yyextra->lineNr--;
1124 pushBuffer(yyscanner,yyextra->inputStringSemi);
1125 }
1126<*>";".*"\n" {
1127 if (YY_START == FVariable) REJECT; // Just be on the safe side
1128 if (YY_START == String) REJECT; // ";" ignored in strings
1129 if (YY_START == StrIgnore) REJECT; // ";" ignored in regular yyextra->comments
1130 if (YY_START == DocBlock) REJECT; // ";" ignored in documentation blocks
1131 yyextra->inputStringSemi = " \n"+QCString(yytext+1);
1132 yyextra->lineNr--;
1133 pushBuffer(yyscanner,yyextra->inputStringSemi);
1134 }
1135
1136<Initialization,ArrayInitializer>"[" |
1137<Initialization,ArrayInitializer>"(/" { yyextra->initializer+=yytext;
1138 yyextra->initializerArrayScope++;
1139 BEGIN(ArrayInitializer); // initializer may contain comma
1140 }
1141<ArrayInitializer>"]" |
1142<ArrayInitializer>"/)" { yyextra->initializer+=yytext;
1143 yyextra->initializerArrayScope--;
1144 if (yyextra->initializerArrayScope<=0)
1145 {
1146 yyextra->initializerArrayScope = 0; // just in case
1147 BEGIN(Initialization);
1148 }
1149 }
1150<ArrayInitializer>. { yyextra->initializer+=yytext; }
1151<Initialization>"(" { yyextra->initializerScope++;
1152 yyextra->initializer+=yytext;
1153 }
1154<Initialization>")" { yyextra->initializerScope--;
1155 yyextra->initializer+=yytext;
1156 }
1157<Initialization>{COMMA} { if (yyextra->initializerScope == 0)
1158 {
1159 updateVariablePrepassComment(yyscanner,yyextra->colNr-(int)yyleng, yyextra->colNr);
1160 pop_state(yyscanner); // end initialization
1161 if (yyextra->last_enum)
1162 {
1163 yyextra->last_enum->initializer.str(yyextra->initializer.str());
1164 }
1165 else
1166 {
1167 if (yyextra->vtype == V_VARIABLE) yyextra->last_entry->initializer.str(yyextra->initializer.str());
1168 }
1169 }
1170 else
1171 {
1172 yyextra->initializer+=", ";
1173 }
1174 }
1175<Initialization>"\n"|"!" { //|
1176 pop_state(yyscanner); // end initialization
1177 if (yyextra->last_enum)
1178 {
1179 yyextra->last_enum->initializer.str(yyextra->initializer.str());
1180 }
1181 else
1182 {
1183 if (yyextra->vtype == V_VARIABLE) yyextra->last_entry->initializer.str(yyextra->initializer.str());
1184 }
1185 yyextra->colNr -= 1;
1186 unput(*yytext);
1187 }
1188<Initialization>. { yyextra->initializer+=yytext; }
1189
1190<*>{BS}"enum"{BS}","{BS}"bind"{BS}"("{BS}"c"{BS}")"{BS} {
1191 if (YY_START == Start)
1192 {
1193 addModule(yyscanner);
1194 yy_push_state(ModuleBody,yyscanner); //anon program
1195 }
1196
1197 yy_push_state(FEnum,yyscanner);
1198 yyextra->current->protection = yyextra->defaultProtection;
1199 yyextra->typeProtection = yyextra->defaultProtection;
1200 yyextra->typeMode = true;
1201
1202 yyextra->current->spec.setStruct(true);
1203 yyextra->current->name.clear();
1204 yyextra->current->args.clear();
1205 yyextra->current->name.sprintf("@%d",yyextra->anonCount++);
1206
1207 yyextra->current->section = EntryType::makeEnum();
1208 yyextra->current->fileName = yyextra->fileName;
1209 yyextra->current->startLine = yyextra->lineNr;
1210 yyextra->current->bodyLine = yyextra->lineNr;
1211 if ((yyextra->current_root) &&
1212 (yyextra->current_root->section.isClass() ||
1213 yyextra->current_root->section.isNamespace()))
1214 {
1215 yyextra->current->name = yyextra->current_root->name + "::" + yyextra->current->name;
1216 }
1217
1218 addCurrentEntry(yyscanner,true);
1219 startScope(yyscanner,yyextra->last_entry.get());
1220 BEGIN( FEnum ) ;
1221 }
1222<FEnum>"end"{BS}"enum" {
1223 yyextra->last_entry->parent()->endBodyLine = yyextra->lineNr;
1224 if (!endScope(yyscanner,yyextra->current_root))
1225 {
1226 yyterminate();
1227 }
1228 yyextra->typeMode = false;
1229 pop_state(yyscanner);
1230 }
1231 /*------ fortran subroutine/function handling ------------------------------------------------------------*/
1232 /* Start is initial condition */
1233
1234<Start,ModuleBody,SubprogBody,InterfaceBody,ModuleBodyContains,SubprogBodyContains>^{BS}({PREFIX}{BS_})?{TYPE_SPEC}{BS}({PREFIX}{BS_})?/{SUBPROG}{BS_} {
1235 if (yyextra->ifType == IF_ABSTRACT || yyextra->ifType == IF_SPECIFIC)
1236 {
1237 addInterface(yyscanner,"$interface$", yyextra->ifType);
1238 startScope(yyscanner,yyextra->last_entry.get());
1239 }
1240
1241 // TYPE_SPEC is for old function style function result
1242 yyextra->current->type = QCString(yytext).stripWhiteSpace().lower();
1243 yy_push_state(SubprogPrefix,yyscanner);
1244 }
1245
1246<SubprogPrefix>{BS}{SUBPROG}{BS_} {
1247 // Fortran subroutine or function found
1248 yyextra->vtype = V_IGNORE;
1249 QCString result=yytext;
1250 result=result.stripWhiteSpace();
1251 addSubprogram(yyscanner,result);
1252 BEGIN(Subprog);
1253 yyextra->current->bodyLine = yyextra->lineNr + yyextra->lineCountPrepass + 1; // we have to be at the line after the definition and we have to take continuation lines into account.
1254 yyextra->current->startLine = yyextra->lineNr;
1255 }
static void addSubprogram(yyscan_t yyscanner, const QCString &text)
1256
1257<Start,ModuleBody,SubprogBody,InterfaceBody,ModuleBodyContains,SubprogBodyContains>^{BS}({PREFIX}{BS_})?{SUBPROG}{BS_} {
1258 // Fortran subroutine or function found
1259 yyextra->vtype = V_IGNORE;
1260 if (yyextra->ifType == IF_ABSTRACT || yyextra->ifType == IF_SPECIFIC)
1261 {
1262 addInterface(yyscanner,"$interface$", yyextra->ifType);
1263 startScope(yyscanner,yyextra->last_entry.get());
1264 }
1265
1266 QCString result = QCString(yytext).stripWhiteSpace();
1267 addSubprogram(yyscanner,result);
1268 yy_push_state(Subprog,yyscanner);
1269 yyextra->current->bodyLine = yyextra->lineNr + yyextra->lineCountPrepass + 1; // we have to be at the line after the definition and we have to take continuation lines into account.
1270 yyextra->current->startLine = yyextra->lineNr;
1271 }
1272
1273<Subprog>{BS} { /* ignore white space */ }
1274<Subprog>{ID} { yyextra->current->name = yytext;
1275 //cout << "1a==========> got " << yyextra->current->type << " " << yytext << " " << yyextra->lineNr << endl;
1276 QCString returnName = yyextra->current->name.lower();
1277 /* if type is part of a module, mod name is necessary for output */
1278 if ((yyextra->current_root) &&
1279 (yyextra->current_root->section.isClass() ||
1280 yyextra->current_root->section.isNamespace()))
1281 {
1282 yyextra->current->name= yyextra->current_root->name + "::" + yyextra->current->name;
1283 }
1284 yyextra->modifiers[yyextra->current_root][yyextra->current->name.lower().str()].returnName = std::move(returnName);
1285
1286 if (yyextra->ifType == IF_ABSTRACT || yyextra->ifType == IF_SPECIFIC)
1287 {
1288 yyextra->current_root->name = substitute(
1289 yyextra->current_root->name, "$interface$", QCString(yytext).lower());
1290 }
1291
1292 BEGIN(Parameterlist);
1293 }
1294<Parameterlist>"(" { yyextra->current->args = "("; }
1295<Parameterlist>")" {
1296 yyextra->current->args += ")";
1297 yyextra->current->args = removeRedundantWhiteSpace(yyextra->current->args);
1298 addCurrentEntry(yyscanner,true);
1299 startScope(yyscanner,yyextra->last_entry.get());
1300 BEGIN(SubprogBody);
1301 }
QCString removeRedundantWhiteSpace(const QCString &s)
Definition util.cpp:578
1302<Parameterlist>{COMMA}|{BS} { yyextra->current->args += yytext;
1303 const CommentInPrepass *c = locatePrepassComment(yyscanner,yyextra->colNr-(int)yyleng, yyextra->colNr);
1304 if (c)
1305 {
1306 if (!yyextra->current->argList.empty())
1307 {
1308 yyextra->current->argList.back().docs = c->str;
1309 }
1310 }
1311 }
1312<Parameterlist>{ID} {
1313 //yyextra->current->type not yet available
1314 QCString param = QCString(yytext).lower();
1315 // std::cout << "3=========> got parameter " << param << "\n";
1316 yyextra->current->args += param;
1317 Argument arg;
1318 arg.name = param;
1319 arg.type = "";
1320 yyextra->current->argList.push_back(arg);
1321 }
1322<Parameterlist>{NOARGS} {
1323 newLine(yyscanner);
1324 //printf("3=========> without parameterlist \n");
1325 addCurrentEntry(yyscanner,true);
1326 startScope(yyscanner,yyextra->last_entry.get());
1327 BEGIN(SubprogBody);
1328 }
1329<SubprogBody>result{BS}\‍({BS}{ID} {
1330 if (yyextra->functionLine)
1331 {
1332 QCString result= yytext;
1333 result= result.right(result.length()-result.find("(")-1);
1334 result= result.stripWhiteSpace();
1335 yyextra->modifiers[yyextra->current_root->parent()][yyextra->current_root->name.lower().str()].returnName = result;
1336 }
1337 //cout << "=====> got result " << result << endl;
1338 }
1339
1340 /*---- documentation yyextra->comments --------------------------------------------------------------------*/
1341
1342<FVariable,SubprogBody,ModuleBody,TypedefBody,TypedefBodyContains>"!<" { /* backward docu comment */
1343 if (yyextra->vtype != V_IGNORE)
1344 {
1345 yyextra->current->docLine = yyextra->lineNr;
1346 yyextra->docBlockJavaStyle = FALSE;
1347 yyextra->docBlock.clear();
1348 yyextra->docBlockJavaStyle = Config_getBool(JAVADOC_AUTOBRIEF);
1349 startCommentBlock(yyscanner,FALSE);
1350 yy_push_state(DocBackLine,yyscanner);
1351 }
1352 else
1353 {
1354 /* handle out of place !< comment as a normal comment */
1355 if (YY_START == String)
1356 {
1357 yyextra->colNr -= (int)yyleng;
1358 REJECT;
1359 } // "!" is ignored in strings
1360 // skip comment line (without docu yyextra->comments "!>" "!<" )
1361 /* ignore further "!" and ignore yyextra->comments in Strings */
1362 if ((YY_START != StrIgnore) && (YY_START != String))
1363 {
1364 yy_push_state(YY_START,yyscanner);
1365 BEGIN(StrIgnore);
1366 yyextra->debugStr="*!";
1367 }
1368 }
1369 }
static void startCommentBlock(yyscan_t yyscanner, bool)
1370<DocBackLine>.* { // contents of yyextra->current comment line
1371 yyextra->docBlock+=yytext;
1372 }
1373<DocBackLine>"\n"{BS}"!"("<"|"!"+) { // comment block (next line is also comment line)
1374 yyextra->docBlock+="\n"; // \n is necessary for lists
1375 newLine(yyscanner);
1376 }
1377<DocBackLine>"\n" { // comment block ends at the end of this line
1378 //cout <<"3=========> comment block : "<< yyextra->docBlock << endl;
1379 yyextra->colNr -= 1;
1380 unput(*yytext);
1381 if (yyextra->vtype == V_VARIABLE)
1382 {
1383 std::shared_ptr<Entry> tmp_entry = yyextra->current;
1384 // temporarily switch to the previous entry
1385 if (yyextra->last_enum)
1386 {
1387 yyextra->current = yyextra->last_enum;
1388 }
1389 else
1390 {
1391 yyextra->current = yyextra->last_entry;
1392 }
1393 handleCommentBlock(yyscanner,stripIndentation(yyextra->docBlock),TRUE);
1394 // switch back
1395 yyextra->current = std::move(tmp_entry);
1396 }
1397 else if (yyextra->vtype == V_PARAMETER)
1398 {
1399 subrHandleCommentBlock(yyscanner,yyextra->docBlock,TRUE);
1400 }
1401 else if (yyextra->vtype == V_RESULT)
1402 {
1403 subrHandleCommentBlockResult(yyscanner,yyextra->docBlock,TRUE);
1404 }
1405 pop_state(yyscanner);
1406 yyextra->docBlock.clear();
1407 }
1408
1409<Start,SubprogBody,ModuleBody,TypedefBody,InterfaceBody,ModuleBodyContains,SubprogBodyContains,TypedefBodyContains,FEnum>^{BS} {
1410 yyextra->curIndent = computeIndent(yytext);
1411 }
static int computeIndent(const char *s)
1412<Start,SubprogBody,ModuleBody,TypedefBody,InterfaceBody,ModuleBodyContains,SubprogBodyContains,TypedefBodyContains,FEnum>"!>" {
1413 yy_push_state(YY_START,yyscanner);
1414 yyextra->current->docLine = yyextra->lineNr;
1415 yyextra->docBlockJavaStyle = FALSE;
1416 if (YY_START==SubprogBody) yyextra->docBlockInBody = TRUE;
1417 yyextra->docBlock.clear();
1418 yyextra->docBlockJavaStyle = Config_getBool(JAVADOC_AUTOBRIEF);
1419 startCommentBlock(yyscanner,FALSE);
1420 BEGIN(DocBlock);
1421 //cout << "start DocBlock " << endl;
1422 }
1423
1424
1425<DocBlock>({CMD}{CMD}){ID}/[^a-z_A-Z0-9] { // escaped command
1426 yyextra->docBlock += yytext;
1427 }
1428<DocBlock>{CMD}("f$"|"f["|"f{"|"f(") {
1429 yyextra->docBlock += yytext;
1430 yyextra->docBlockName=&yytext[1];
1431 if (yyextra->docBlockName.at(1)=='[')
1432 {
1433 yyextra->docBlockName.at(1)=']';
1434 }
1435 if (yyextra->docBlockName.at(1)=='{')
1436 {
1437 yyextra->docBlockName.at(1)='}';
1438 }
1439 if (yyextra->docBlockName.at(1)=='(')
1440 {
1441 yyextra->docBlockName.at(1)=')';
1442 }
1443 yyextra->fencedSize=0;
1444 yyextra->blockString=yytext;
1445 yyextra->blockLineNr=yyextra->lineNr;
1446 BEGIN(DocCopyBlock);
1447 }
1448<DocBlock>{CMD}"ifile"{B}+"\""[^\n\"]+"\"" {
1449 yyextra->fileName = &yytext[6];
1450 yyextra->fileName = yyextra->fileName.stripWhiteSpace();
1451 yyextra->fileName = yyextra->fileName.mid(1,yyextra->fileName.length()-2);
1452 yyextra->docBlock += yytext;
1453 }
1454<DocBlock>{CMD}"ifile"{B}+{FILEMASK} {
1455 yyextra->fileName = &yytext[6];
1456 yyextra->fileName = yyextra->fileName.stripWhiteSpace();
1457 yyextra->docBlock += yytext;
1458 }
1459<DocBlock>{CMD}"iline"{LINENR}/[\n\.] |
1460<DocBlock>{CMD}"iline"{LINENR}{B} {
1461 bool ok = false;
1462 int nr = QCString(&yytext[6]).toInt(&ok);
1463 if (!ok)
1464 {
1465 warn(yyextra->fileName,yyextra->lineNr,"Invalid line number '%s' for iline command",yytext);
1466 }
1467 else
1468 {
1469 yyextra->lineNr = nr;
1470 }
1471 yyextra->docBlock += yytext;
1472 }
int toInt(bool *ok=nullptr, int base=10) const
Definition qcstring.cpp:249
1473<DocBlock>{B}*"<"{PRE}">" {
1474 yyextra->docBlock += yytext;
1475 yyextra->docBlockName="<pre>";
1476 yyextra->fencedSize=0;
1477 yyextra->blockString=yytext;
1478 yyextra->blockLineNr=yyextra->lineNr;
1479 BEGIN(DocCopyBlock);
1480 }
1481<DocBlock>{B}*"<"<CODE>">" {
1482 yyextra->docBlock += yytext;
1483 yyextra->docBlockName="<code>";
1484 yyextra->fencedSize=0;
1485 yyextra->blockString=yytext;
1486 yyextra->blockLineNr=yyextra->lineNr;
1487 BEGIN(DocCopyBlock);
1488 }
1489<DocBlock>{CMD}"startuml"/[^a-z_A-Z0-9\-] { // verbatim command
1490 yyextra->docBlock += yytext;
1491 yyextra->docBlockName="uml";
1492 yyextra->fencedSize=0;
1493 yyextra->blockString=yytext;
1494 yyextra->blockLineNr=yyextra->lineNr;
1495 BEGIN(DocCopyBlock);
1496 }
1497<DocBlock>{CMD}("verbatim"|"iliteral"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"msc"|"code")/[^a-z_A-Z0-9\-] { // verbatim command
1498 yyextra->docBlock += yytext;
1499 yyextra->docBlockName=&yytext[1];
1500 yyextra->fencedSize=0;
1501 yyextra->blockString=yytext;
1502 yyextra->blockLineNr=yyextra->lineNr;
1503 BEGIN(DocCopyBlock);
1504 }
1505<DocBlock>"~~~"[~]* {
1506 QCString pat = yytext;
1507 yyextra->docBlock += pat;
1508 yyextra->docBlockName="~~~";
1509 yyextra->fencedSize=pat.length();
1510 yyextra->blockString=yytext;
1511 yyextra->blockLineNr=yyextra->lineNr;
1512 BEGIN(DocCopyBlock);
1513 }
1514<DocBlock>"```"[`]*/(".")?[a-zA-Z0-9#_-]+ |
1515<DocBlock>"```"[`]*/"{"[^}]+"}" |
1516<DocBlock>"```"[`]* {
1517 QCString pat = yytext;
1518 yyextra->docBlock += pat;
1519 yyextra->docBlockName="```";
1520 yyextra->fencedSize=pat.length();
1521 yyextra->blockString=yytext;
1522 yyextra->blockLineNr=yyextra->lineNr;
1523 BEGIN(DocCopyBlock);
1524 }
1525<DocBlock>"\\ilinebr "{BS} {
1526 QCString indent;
1527 int extraSpaces = std::max(0,static_cast<int>(yyleng-9-yyextra->curIndent-2));
1528 indent.fill(' ',extraSpaces);
1529 //printf("extraSpaces=%d\n",extraSpaces);
1530 yyextra->docBlock += "\\ilinebr ";
1531 yyextra->docBlock += indent;
1532 }
void fill(char c, int len=-1)
Fills a string with a predefined character.
Definition qcstring.h:180
1533
1534<DocBlock>[^@*`~\/\\\n]+ { // any character that isn't special
1535 yyextra->docBlock += yytext;
1536 }
1537<DocBlock>"\n"{BS}"!"(">"|"!"+) { // comment block (next line is also comment line)
1538 yyextra->docBlock+="\n"; // \n is necessary for lists
1539 newLine(yyscanner);
1540 }
1541<DocBlock>"\n" { // comment block ends at the end of this line
1542 //cout <<"3=========> comment block : "<< yyextra->docBlock << endl;
1543 yyextra->colNr -= 1;
1544 unput(*yytext);
1545 handleCommentBlock(yyscanner,stripIndentation(yyextra->docBlock),TRUE);
1546 pop_state(yyscanner);
1547 }
1548<DocBlock>. { // command block
1549 yyextra->docBlock += *yytext;
1550 }
1551
1552 /* ---- Copy verbatim sections ------ */
1553
1554<DocCopyBlock>"</"{PRE}">" { // end of a <pre> block
1555 yyextra->docBlock += yytext;
1556 if (yyextra->docBlockName=="<pre>")
1557 {
1558 yyextra->docBlockName="";
1559 yyextra->blockString.clear();
1560 yyextra->blockLineNr=-1;
1561 BEGIN(DocBlock);
1562 }
1563 }
1564<DocCopyBlock>"</"{CODE}">" { // end of a <code> block
1565 yyextra->docBlock += yytext;
1566 if (yyextra->docBlockName=="<code>")
1567 {
1568 yyextra->docBlockName="";
1569 yyextra->blockString.clear();
1570 yyextra->blockLineNr=-1;
1571 BEGIN(DocBlock);
1572 }
1573 }
1574<DocCopyBlock>[\\@]("f$"|"f]"|"f}"|"f)") {
1575 yyextra->docBlock += yytext;
1576 if (yyextra->docBlockName==&yytext[1])
1577 {
1578 yyextra->docBlockName="";
1579 yyextra->blockString.clear();
1580 yyextra->blockLineNr=-1;
1581 BEGIN(DocBlock);
1582 }
1583 }
1584<DocCopyBlock>[\\@]("endverbatim"|"endiliteral"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"endmsc"|"enduml"|"endcode")/[^a-z_A-Z0-9] { // end of verbatim block
1585 yyextra->docBlock += yytext;
1586 if (&yytext[4]==yyextra->docBlockName)
1587 {
1588 yyextra->docBlockName="";
1589 yyextra->blockString.clear();
1590 yyextra->blockLineNr=-1;
1591 BEGIN(DocBlock);
1592 }
1593 }
1594
1595<DocCopyBlock>^{B}*{COMM} { // start of a comment line
1596 if (yyextra->docBlockName=="verbatim")
1597 {
1598 REJECT;
1599 }
1600 else
1601 {
1602 QCString indent;
1603 indent.fill(' ',computeIndent(yytext) + 2);
1604 yyextra->docBlock += indent;
1605 }
1606 }
1607<DocCopyBlock>"~~~"[~]* {
1608 QCString pat = yytext;
1609 yyextra->docBlock += pat;
1610 if (yyextra->docBlockName == "~~~" && yyextra->fencedSize==pat.length())
1611 {
1612 yyextra->blockString.clear();
1613 yyextra->blockLineNr=-1;
1614 BEGIN(DocBlock);
1615 }
1616 }
1617<DocCopyBlock>"```"[`]* {
1618 QCString pat = yytext;
1619 yyextra->docBlock += pat;
1620 if (yyextra->docBlockName == "```" && yyextra->fencedSize==pat.length())
1621 {
1622 yyextra->blockString.clear();
1623 yyextra->blockLineNr=-1;
1624 BEGIN(DocBlock);
1625 }
1626 }
1627
1628<DocCopyBlock>[^<@/\*\]!`~"\$\\\n]+ { // any character that is not special
1629 yyextra->docBlock += yytext;
1630 }
1631<DocCopyBlock>\n { // newline
1632 yyextra->docBlock += *yytext;
1633 newLine(yyscanner);
1634 }
1635<DocCopyBlock>. { // any other character
1636 yyextra->docBlock += *yytext;
1637 }
1638
1639 /*-----Prototype parsing -------------------------------------------------------------------------*/
1640<Prototype>{BS}{SUBPROG}{BS_} {
1641 BEGIN(PrototypeSubprog);
1642 }
1643<Prototype,PrototypeSubprog>{BS}{SCOPENAME}?{BS}{ID} {
1644 yyextra->current->name = QCString(yytext).lower();
1645 yyextra->current->name.stripWhiteSpace();
1646 BEGIN(PrototypeArgs);
1647 }
1648<PrototypeArgs>{
1649"("|")"|","|{BS_} { yyextra->current->args += yytext; }
1650{ID} { yyextra->current->args += yytext;
1651 Argument a;
1652 a.name = QCString(yytext).lower();
1653 yyextra->current->argList.push_back(a);
1654 }
1655}
1656
1657 /*------------------------------------------------------------------------------------------------*/
1658
1659<*>"\n" {
1660 newLine(yyscanner);
1661 //if (yyextra->debugStr.stripWhiteSpace().length() > 0) cout << "ignored text: " << yyextra->debugStr << " state: " <<YY_START << endl;
1662 yyextra->debugStr="";
1663 }
1664
1665
1666 /*---- error: EOF in wrong state --------------------------------------------------------------------*/
1667
1668<*><<EOF>> {
1669 if (yyextra->parsingPrototype)
1670 {
1671 yyterminate();
1672 }
1673 else if ( yyextra->includeStackPtr <= 0 )
1674 {
1675 if (YY_START!=INITIAL && YY_START!=Start)
1676 {
1677 DBG_CTX((stderr,"==== Error: EOF reached in wrong state (end missing)"));
1678 scanner_abort(yyscanner);
1679 }
1680 yyterminate();
1681 }
1682 else
1683 {
1684 popBuffer(yyscanner);
1685 }
1686 }
static void popBuffer(yyscan_t yyscanner)
1687<*>{LOG_OPER} { // Fortran logical comparison keywords
1688 }
1689<*>. {
1690 //yyextra->debugStr+=yytext;
1691 //printf("I:%c\n", *yytext);
1692 } // ignore remaining text
1693
1694 /**********************************************************************************/
1695 /**********************************************************************************/
1696 /**********************************************************************************/
1697%%

◆ yyread()

static int yyread ( yyscan_t yyscanner,
char * buf,
int max_size )
static

Definition at line 2851 of file fortranscanner.l.

2852{
2853 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2854 int c=0;
2855 while ( c < max_size && yyextra->inputString[yyextra->inputPosition] )
2856 {
2857 *buf = yyextra->inputString[yyextra->inputPosition++] ;
2858 c++; buf++;
2859 }
2860 return c;
2861}

Variable Documentation

◆ directionParam

const char* directionParam[]
static
Initial value:
=
{
"", "[in]", "[out]", "[in,out]"
}

Definition at line 137 of file fortranscanner.l.

138{
139 "", "[in]", "[out]", "[in,out]"
140};

Referenced by subrHandleCommentBlock().

◆ directionStrs

const char* directionStrs[]
static
Initial value:
=
{
"", "intent(in)", "intent(out)", "intent(inout)"
}

Definition at line 133 of file fortranscanner.l.

134{
135 "", "intent(in)", "intent(out)", "intent(inout)"
136};

Referenced by applyModifiers().