Doxygen
Loading...
Searching...
No Matches
fortranscanner.l File Reference
#include <stdint.h>
#include <map>
#include <vector>
#include <stack>
#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  BlockState
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 pushBlockState (yyscan_t yyscanner, const QCString &text)
static void popBlockState (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 82 of file fortranscanner.l.

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

◆ INVALID_ENTRY

#define INVALID_ENTRY   ((Entry*)0x8)

Definition at line 274 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 code.l:3982

Definition at line 268 of file fortranscanner.l.

◆ YY_NO_INPUT

#define YY_NO_INPUT   1

Definition at line 84 of file fortranscanner.l.

◆ YY_NO_UNISTD_H

#define YY_NO_UNISTD_H   1

Definition at line 85 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 273 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 88 of file fortranscanner.l.

88{ IF_NONE, IF_SPECIFIC, IF_GENERIC, IF_ABSTRACT };

◆ ScanVar

enum ScanVar
Enumerator
V_IGNORE 
V_VARIABLE 
V_PARAMETER 
V_RESULT 

Definition at line 87 of file fortranscanner.l.

87{ V_IGNORE, V_VARIABLE, V_PARAMETER, V_RESULT};

Function Documentation

◆ addCurrentEntry()

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 2907 of file fortranscanner.l.

2908{
2909 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2910 if (case_insens) yyextra->current->name = yyextra->current->name.lower();
2911 //printf("===Adding entry %s to %s\n", qPrint(yyextra->current->name), qPrint(yyextra->current_root->name));
2912 yyextra->last_entry = yyextra->current;
2913 yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current);
2914 initEntry(yyscanner);
static void initEntry(yyscan_t yyscanner)
2915}

References initEntry().

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

◆ addInterface()

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 2978 of file fortranscanner.l.

2979{
2980 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2981 if (YY_START == Start)
2982 {
2983 addModule(yyscanner);
2984 pushBlockState(yyscanner,QCString(yytext)+" (anonymous program)");
2985 yy_push_state(ModuleBody,yyscanner); //anon program
2986 }
This is an alternative implementation of QCString.
Definition qcstring.h:101
static void pushBlockState(yyscan_t yyscanner, const QCString &text)
static void addModule(yyscan_t yyscanner, const QCString &name=QCString(), bool isModule=FALSE)
2987
2988 yyextra->current->section = EntryType::makeClass(); // was EntryType::Interface;
2989 yyextra->current->spec = TypeSpecifier().setInterface(true);
2990 yyextra->current->name = name;
Wrapper class for a number of boolean properties.
Definition types.h:654
2991
2992 switch (type)
2993 {
2994 case IF_ABSTRACT:
2995 yyextra->current->type = "abstract";
2996 break;
@ IF_ABSTRACT
2997
2998 case IF_GENERIC:
2999 yyextra->current->type = "generic";
3000 break;
@ IF_GENERIC
3001
3002 case IF_SPECIFIC:
3003 case IF_NONE:
3004 default:
3005 yyextra->current->type = "";
3006 }
@ IF_NONE
@ IF_SPECIFIC
3007
3008 /* if type is part of a module, mod name is necessary for output */
3009 if ((yyextra->current_root) &&
3010 (yyextra->current_root->section.isClass() ||
3011 yyextra->current_root->section.isNamespace()))
3012 {
3013 yyextra->current->name= yyextra->current_root->name + "::" + yyextra->current->name;
3014 }
3015
3016 yyextra->current->fileName = yyextra->fileName;
3017 yyextra->current->bodyLine = yyextra->lineNr;
3018 yyextra->current->startLine = yyextra->lineNr;
3019 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
3020}

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

◆ addModule()

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

Definition at line 2917 of file fortranscanner.l.

2918{
2919 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2920 DBG_CTX((stderr, "0=========> got module %s\n", qPrint(name)));
#define DBG_CTX(x)
const char * qPrint(const char *s)
Definition qcstring.h:687
2921
2922 if (isModule)
2923 yyextra->current->section = EntryType::makeNamespace();
2924 else
2925 yyextra->current->section = EntryType::makeFunction();
2926
2927 if (!name.isEmpty())
2928 {
2929 yyextra->current->name = name;
2930 }
2931 else
2932 {
2933 QCString fname = yyextra->fileName;
2934 int index = std::max(fname.findRev('/'), fname.findRev('\\'));
2935 fname = fname.right(fname.length()-index-1);
2936 if (yyextra->mainPrograms) fname += "__" + QCString().setNum(yyextra->mainPrograms);
2937 yyextra->mainPrograms++;
2938 fname = fname.prepend("__").append("__");
2939 yyextra->current->name = substitute(fname, ".", "_");
2940 }
2941 yyextra->current->type = "program";
2942 yyextra->current->fileName = yyextra->fileName;
2943 yyextra->current->bodyLine = yyextra->lineNr; // used for source reference
2944 yyextra->current->startLine = yyextra->lineNr;
2945 yyextra->current->protection = Protection::Public ;
2946 addCurrentEntry(yyscanner,true);
2947 startScope(yyscanner,yyextra->last_entry.get());
QCString & prepend(const char *s)
Definition qcstring.h:422
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition qcstring.h:166
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:163
QCString & setNum(short n)
Definition qcstring.h:459
QCString & append(char c)
Definition qcstring.h:396
QCString right(size_t len) const
Definition qcstring.h:234
int findRev(char c, int index=-1, bool cs=TRUE) const
Definition qcstring.cpp:96
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:571
2948}

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

Referenced by addInterface().

◆ addSubprogram()

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

Definition at line 2951 of file fortranscanner.l.

2952{
2953 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2954 DBG_CTX((stderr,"1=========> got subprog, type: %s\n",qPrint(text)));
2955 yyextra->subrCurrent.push_back(yyextra->current);
2956 yyextra->current->section = EntryType::makeFunction();
2957 QCString subtype = text; subtype=subtype.lower().stripWhiteSpace();
2958 yyextra->functionLine = (subtype.find("function") != -1);
2959 yyextra->current->type += " " + subtype;
2960 yyextra->current->type = yyextra->current->type.stripWhiteSpace();
2961 if (yyextra->ifType == IF_ABSTRACT)
2962 {
2963 yyextra->current->virt = Specifier::Virtual;
2964 }
2965 yyextra->current->fileName = yyextra->fileName;
2966 yyextra->current->bodyLine = yyextra->lineNr; // used for source reference start of body of routine
2967 yyextra->current->startLine = yyextra->lineNr; // used for source reference start of definition
2968 yyextra->current->args.clear();
2969 yyextra->current->argList.clear();
2970 pushBlockState(yyscanner,text);
2971 yyextra->docBlock.clear();
int find(char c, int index=0, bool cs=TRUE) const
Definition qcstring.cpp:43
QCString lower() const
Definition qcstring.h:249
QCString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
Definition qcstring.h:260
void clear()
Definition qcstring.h:182
2972}

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

◆ applyModifiers() [1/3]

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

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

Definition at line 2537 of file fortranscanner.l.

2538{
2539 arg->type = applyModifiers(arg->type, mdfs);
static QCString applyModifiers(QCString typeName, const SymbolModifiers &mdfs)
QCString type
Definition arguments.h:42
2540}

References applyModifiers(), and Argument::type.

◆ applyModifiers() [2/3]

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

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

Definition at line 2543 of file fortranscanner.l.

2544{
2545 ent->type = applyModifiers(ent->type, mdfs);
QCString type
member type
Definition entry.h:174
2546
2548 ent->protection = Protection::Public;
2549 else if (mdfs.protection == SymbolModifiers::PRIVATE)
2550 ent->protection = Protection::Private;
Protection protection
class protection
Definition entry.h:181
Protection protection
2551
2552 if (mdfs.nonoverridable)
2553 ent->spec.setFinal(true);
2554 if (mdfs.nopass)
2555 ent->isStatic = TRUE;
2556 if (mdfs.deferred)
2557 ent->virt = Specifier::Pure;
Specifier virt
virtualness of the entry
Definition entry.h:192
bool isStatic
static ?
Definition entry.h:186
TypeSpecifier spec
class/member specifiers
Definition entry.h:183
#define TRUE
Definition qcstring.h:37
2558}

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

◆ applyModifiers() [3/3]

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

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

Definition at line 2420 of file fortranscanner.l.

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

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()

int computeIndent ( const char * s)
inlinestatic

Definition at line 1718 of file fortranscanner.l.

1719{
1720 int col=0;
1721 int tabSize=Config_getInt(TAB_SIZE);
1722 const char *p=s;
1723 char c = 0;
1724 while ((c=*p++))
1725 {
1726 if (c=='\t') col+=tabSize-(col%tabSize);
1727 else if (c=='\n') col=0;
1728 else col++;
1729 }
1730 return col;
#define Config_getInt(name)
Definition config.h:34
1731}

References Config_getInt.

◆ copyEntry()

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 2157 of file fortranscanner.l.

2158{
2159 dest->type = src->type;
2160 dest->fileName = src->fileName;
2161 dest->startLine = src->startLine;
2162 dest->bodyLine = src->bodyLine;
2163 dest->endBodyLine = src->endBodyLine;
2164 dest->args = src->args;
2165 dest->argList = src->argList;
2166 dest->doc = src->doc;
2167 dest->docLine = src->docLine;
2168 dest->docFile = src->docFile;
2169 dest->brief = src->brief;
2170 dest->briefLine= src->briefLine;
2171 dest->briefFile= src->briefFile;
2172}

Referenced by resolveModuleProcedures().

◆ endScope()

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 2580 of file fortranscanner.l.

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

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()

QCString extractBind ( const QCString & name)
static

remove useless spaces from bind statement

Definition at line 2238 of file fortranscanner.l.

2239{
2240 QCString parensPart = extractFromParens(name);
2241 if (parensPart.length() == 1)
2242 {
2243 return "bind(C)";
2244 }
2245 else
2246 {
2247 //strip 'c'
2248 parensPart = parensPart.mid(1).stripWhiteSpace();
2249 // strip ','
2250 parensPart = parensPart.mid(1).stripWhiteSpace();
2251 // name part
2252 parensPart = parensPart.mid(4).stripWhiteSpace();
2253 // = part
2254 parensPart = parensPart.mid(1).stripWhiteSpace();
QCString mid(size_t index, size_t len=static_cast< size_t >(-1)) const
Definition qcstring.h:241
static QCString extractFromParens(const QCString &name)
2255
2256 return "bind(C, name=" + parensPart + ")";
2257 }
2258}

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

Referenced by SymbolModifiers::operator|=().

◆ extractFromParens()

QCString extractFromParens ( const QCString & name)
static

Extracts string which resides within parentheses of provided string.

Definition at line 2218 of file fortranscanner.l.

2219{
2220 QCString extracted = name;
2221 int start = extracted.find("(");
2222 if (start != -1)
2223 {
2224 extracted.remove(0, start+1);
2225 }
2226 int end = extracted.findRev(")");
2227 if (end != -1)
2228 {
2229 size_t length = extracted.length();
2230 extracted.remove(end, length);
2231 }
2232 extracted = extracted.stripWhiteSpace();
2233
2234 return extracted;
2235}

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

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

◆ findArgument()

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

For debugging purposes.

Find argument with given name in subprog entry.

Definition at line 2403 of file fortranscanner.l.

2404{
2405 QCString cname(name.lower());
2406 for (Argument &arg : subprog->argList)
2407 {
2408 if ((!byTypeName && arg.name.lower() == cname) ||
2409 (byTypeName && arg.type.lower() == cname)
2410 )
2411 {
2412 return &arg;
2413 }
2414 }
2415 return nullptr;
ArgumentList argList
member arguments as a list
Definition entry.h:195
2416}

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

Referenced by endScope().

◆ getAmpersandAtTheStart()

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

Definition at line 1765 of file fortranscanner.l.

1766{
1767 for(int i=0; i<length; i++)
1768 {
1769 switch(buf[i])
1770 {
1771 case ' ':
1772 case '\t':
1773 break;
1774 case '&':
1775 return i;
1776 default:
1777 return -1;
1778 }
1779 }
1780 return -1;
1781}

◆ getAmpOrExclAtTheEnd()

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

Definition at line 1784 of file fortranscanner.l.

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

Referenced by prepassFixedForm().

◆ getLexerFILE()

const char * getLexerFILE ( )
inlinestatic

Definition at line 271 of file fortranscanner.l.

271{return __FILE__;}

◆ getParameter()

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

Get the argument name.

Definition at line 3027 of file fortranscanner.l.

3028{
3029 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3030 // std::cout<<"addFortranParameter(): "<<name<<" DOCS:"<<(docs.isEmpty()?QCString("null"):docs)<<"\n";
3031 Argument *ret = nullptr;
3032 for (Argument &a:yyextra->current_root->argList)
3033 {
3034 if (a.name.lower()==name.lower())
3035 {
3036 ret=&a;
3037 //printf("parameter found: %s\n",(const char*)name);
3038 break;
3039 }
3040 } // for
3041 return ret;
3042}

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

Referenced by updateVariablePrepassComment().

◆ handleCommentBlock()

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

Definition at line 3062 of file fortranscanner.l.

3063{
3064 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3065 bool hideInBodyDocs = Config_getBool(HIDE_IN_BODY_DOCS);
3066 if (yyextra->docBlockInBody && hideInBodyDocs)
3067 {
3068 yyextra->docBlockInBody = FALSE;
3069 return;
3070 }
3071 DBG_CTX((stderr,"call parseCommentBlock [%s]\n",qPrint(doc)));
3072 int lineNr = brief ? yyextra->current->briefLine : yyextra->current->docLine;
3073 int position=0;
3074 bool needsEntry = FALSE;
3075 Markdown markdown(yyextra->fileName,lineNr);
3076 GuardedSectionStack guards;
3077 QCString strippedDoc = stripIndentation(doc);
3078 QCString processedDoc = Config_getBool(MARKDOWN_SUPPORT) ? markdown.process(strippedDoc,lineNr) : strippedDoc;
3079 while (yyextra->commentScanner.parseCommentBlock(
3080 yyextra->thisParser,
3081 yyextra->docBlockInBody ? yyextra->subrCurrent.back().get() : yyextra->current.get(),
3082 processedDoc, // text
3083 yyextra->fileName, // file
3084 lineNr,
3085 yyextra->docBlockInBody ? FALSE : brief,
3086 yyextra->docBlockInBody ? FALSE : yyextra->docBlockJavaStyle,
3087 yyextra->docBlockInBody,
3088 yyextra->defaultProtection,
3089 position,
3090 needsEntry,
3091 Config_getBool(MARKDOWN_SUPPORT),
3092 &guards
3093 ))
3094 {
3095 DBG_CTX((stderr,"parseCommentBlock position=%d [%s] needsEntry=%d\n",position,doc.data()+position,needsEntry));
3096 if (needsEntry) addCurrentEntry(yyscanner,false);
3097 }
3098 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:172
std::stack< GuardedSection > GuardedSectionStack
Definition commentscan.h:48
#define Config_getBool(name)
Definition config.h:33
QCString stripIndentation(const QCString &s, bool skipFirstLine)
Definition util.cpp:5967
3099
3100 if (needsEntry) addCurrentEntry(yyscanner,false);
3101 yyextra->docBlockInBody = FALSE;
3102}

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

Referenced by subrHandleCommentBlock(), and subrHandleCommentBlockResult().

◆ initEntry()

void initEntry ( yyscan_t yyscanner)
static

Definition at line 2878 of file fortranscanner.l.

2879{
2880 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2881 if (yyextra->typeMode)
2882 {
2883 yyextra->current->protection = yyextra->typeProtection;
2884 }
2885 else if (yyextra->current_root && yyextra->current_root->section.isClass() && yyextra->current_root->spec.isInterface())
2886 {
2887 yyextra->current->protection = Protection::Public;
2888 }
2889 else if (yyextra->current_root && yyextra->current_root->section.isFunction())
2890 {
2891 yyextra->current->protection = Protection::Private;
2892 }
2893 else
2894 {
2895 yyextra->current->protection = yyextra->defaultProtection;
2896 }
2897 yyextra->current->mtype = MethodTypes::Method;
2898 yyextra->current->virt = Specifier::Normal;
2899 yyextra->current->isStatic = false;
2900 yyextra->current->lang = SrcLangExt::Fortran;
2901 yyextra->commentScanner.initGroupInfo(yyextra->current.get());
2902}

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

◆ initParser()

void initParser ( yyscan_t yyscanner)
static

Definition at line 2872 of file fortranscanner.l.

2873{
2874 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2875 yyextra->last_entry.reset();
2876}

Referenced by parseMain().

◆ insertCharacter()

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

Definition at line 1864 of file fortranscanner.l.

1865{
1866 // shift tail by one character
1867 for(int i=length; i>pos; i--)
1868 contents[i]=contents[i-1];
1869 // set the character
1870 contents[pos] = c;
1871}

Referenced by prepassFixedForm().

◆ locatePrepassComment()

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

Definition at line 1733 of file fortranscanner.l.

1734{
1735 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1736 //printf("Locate %d-%d\n", from, to);
1737 for (const auto &cip : yyextra->comments)
1738 { // todo: optimize
1739 int c = cip.column;
1740 //printf("Candidate %d\n", c);
1741 if (c>=from && c<=to)
1742 {
1743 // comment for previous variable or parameter
1744 return &cip;
1745 }
1746 }
1747 return nullptr;
1748}

References CommentInPrepass::column.

Referenced by updateVariablePrepassComment().

◆ newLine()

void newLine ( yyscan_t yyscanner)
static

Definition at line 1709 of file fortranscanner.l.

1710{
1711 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1712 yyextra->lineNr++;
1713 yyextra->lineNr+=yyextra->lineCountPrepass;
1714 yyextra->lineCountPrepass=0;
1715 yyextra->comments.clear();
1716}

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

◆ parseMain()

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

Definition at line 3241 of file fortranscanner.l.

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

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

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

◆ pop_state()

void pop_state ( yyscan_t yyscanner)
inlinestatic

Definition at line 3429 of file fortranscanner.l.

3430{
3431 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3432 if ( yyg->yy_start_stack_ptr <= 0 )
3433 warn(yyextra->fileName,yyextra->lineNr,"Unexpected statement '{}'",yytext );
3434 else
3435 yy_pop_state(yyscanner);
#define warn(file, line, fmt,...)
Definition message.h:97
3436}

References warn.

◆ popBlockState()

void popBlockState ( yyscan_t yyscanner)
static

Definition at line 3446 of file fortranscanner.l.

3447{
3448 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3449 if (yyextra->blockStack.empty())
3450 {
3451 warn(yyextra->fileName,yyextra->lineNr,"Internal inconsistency: empty stack while attempting popBlockState");
3452 }
3453 else
3454 {
3455 yyextra->blockStack.pop();
3456 }
3457 if (yyextra->blockStack.empty())
3458 {
3459 yyextra->blockString.clear();
3460 yyextra->blockLineNr=-1;
3461 }
3462 else
3463 {
3464 yyextra->blockString=yyextra->blockStack.top().blockString;
3465 yyextra->blockLineNr=yyextra->blockStack.top().blockLineNr;
3466 }
3467}

References warn.

◆ popBuffer()

void popBuffer ( yyscan_t yyscanner)
static

Definition at line 2147 of file fortranscanner.l.

2148{
2149 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2150 DBG_CTX((stderr, "--POP--"));
2151 yyextra->includeStackPtr --;
2152 yy_delete_buffer( YY_CURRENT_BUFFER, yyscanner );
2153 yy_switch_to_buffer( yyextra->includeStack[yyextra->includeStackPtr], yyscanner );
2154}

References DBG_CTX.

Referenced by FortranOutlineParser::parsePrototype().

◆ prepassFixedForm()

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

Definition at line 1875 of file fortranscanner.l.

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

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

Referenced by checkContLines(), and parseMain().

◆ pushBlockState()

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

Definition at line 3438 of file fortranscanner.l.

3439{
3440 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3441 yyextra->blockString = text;
3442 yyextra->blockLineNr = yyextra->lineNr;
3443 yyextra->blockStack.emplace(yyextra->blockString,yyextra->blockLineNr);
3444}

Referenced by addInterface(), and addSubprogram().

◆ pushBuffer()

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

Definition at line 2133 of file fortranscanner.l.

2134{
2135 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2136 if (yyextra->includeStackCnt <= yyextra->includeStackPtr)
2137 {
2138 yyextra->includeStackCnt++;
2139 yyextra->includeStack = (YY_BUFFER_STATE *)realloc(yyextra->includeStack, yyextra->includeStackCnt * sizeof(YY_BUFFER_STATE));
2140 }
2141 yyextra->includeStack[yyextra->includeStackPtr++] = YY_CURRENT_BUFFER;
2142 yy_switch_to_buffer(yy_scan_string(buffer.data(),yyscanner),yyscanner);
2143
2144 DBG_CTX((stderr, "--PUSH--%s", qPrint(buffer)));
2145}

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 2179 of file fortranscanner.l.

2180{
2181 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2182 if (yyextra->moduleProcedures.empty()) return;
2183
2184 // build up map of available functions
2185 std::map<std::string,std::shared_ptr<Entry>> procMap;
2186 {
2187 for (const auto& cf: current_root->children())
2188 {
2189 if (!cf->section.isFunction())
2190 continue;
2191
2192 // remove scope from name
2193 QCString name = cf->name;
2194 {
2195 int end = name.findRev(":");
2196 if (end != -1)
2197 name.remove(0, end+1);
2198 }
2199
2200 procMap.emplace(name.str(), cf);
2201 }
2202 }
2203
2204
2205 // for all module procedures
2206 for (const auto& ce1: yyextra->moduleProcedures)
2207 {
2208 if (procMap.find(ce1->name.str())!=procMap.end())
2209 {
2210 std::shared_ptr<Entry> proc = procMap[ce1->name.str()];
2211 copyEntry(ce1, proc);
2212 }
2213 } // for all interface module procedures
2214 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
2215}

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

◆ resolveTypeBoundProcedures()

void resolveTypeBoundProcedures ( Entry * scope)
static

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

Definition at line 2713 of file fortranscanner.l.

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

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

Referenced by endScope().

◆ scanner_abort()

void scanner_abort ( yyscan_t yyscanner)
static

Definition at line 3395 of file fortranscanner.l.

3396{
3397 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3398 fprintf(stderr,"********************************************************************\n");
3399 if (yyextra->blockLineNr == -1)
3400 {
3401 fprintf(stderr,"Error in file %s line: %d, state: %d(%s)\n",
3402 qPrint(yyextra->fileName),yyextra->lineNr,YY_START,stateToString(YY_START));
3403 }
3404 else
3405 {
3406 fprintf(stderr,"Error in file %s line: %d, state: %d(%s), starting command: '%s' probable line reference: %d\n",
3407 qPrint(yyextra->fileName),yyextra->lineNr,YY_START,stateToString(YY_START),qPrint(yyextra->blockString),yyextra->blockLineNr);
3408 }
3409 fprintf(stderr,"********************************************************************\n");
static const char * stateToString(int state)
3410
3411 // empty the stack
3412 while (!yyextra->blockStack.empty()) yyextra->blockStack.pop();
3413
3414 bool start=FALSE;
3415
3416 for (const auto &ce : yyextra->global_root->children())
3417 {
3418 if (ce == yyextra->file_root) start=TRUE;
3419 if (start) ce->reset();
3420 }
3421
3422 // dummy call to avoid compiler warning
3423 (void)yy_top_state(yyscanner);
3424
3425 return;
3426 //exit(-1);
3427}

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

Referenced by endScope().

◆ startCommentBlock()

void startCommentBlock ( yyscan_t yyscanner,
bool brief )
static

Definition at line 3045 of file fortranscanner.l.

3046{
3047 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3048 if (brief)
3049 {
3050 yyextra->current->briefFile = yyextra->fileName;
3051 yyextra->current->briefLine = yyextra->lineNr;
3052 }
3053 else
3054 {
3055 yyextra->current->docFile = yyextra->fileName;
3056 yyextra->current->docLine = yyextra->lineNr;
3057 }
3058}

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

◆ startScope()

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 2564 of file fortranscanner.l.

2565{
2566 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2567 //cout<<"start scope: "<<scope->name<<endl;
2568 yyextra->current_root= scope; /* start substructure */
2569
2570 yyextra->modifiers.emplace(scope, std::map<std::string,SymbolModifiers>());
2571
2572 // create new current with possibly different defaults...
2573 yyextra->current = std::make_shared<Entry>();
2574 initEntry(yyscanner);
2575}

References initEntry().

Referenced by addModule(), and parseMain().

◆ stateToString()

const char * stateToString ( int state)
static

◆ subrHandleCommentBlock()

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 3106 of file fortranscanner.l.

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

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

◆ subrHandleCommentBlockResult()

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 3210 of file fortranscanner.l.

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

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

◆ truncatePrepass()

void truncatePrepass ( yyscan_t yyscanner,
int index )
static

Definition at line 1851 of file fortranscanner.l.

1852{
1853 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1854 size_t length = yyextra->inputStringPrepass.length();
1855 for (size_t i=index+1; i<length; i++) {
1856 if (yyextra->inputStringPrepass[i]=='!' && i<length-1 && yyextra->inputStringPrepass[i+1]=='<') { // save comment
1857 yyextra->comments.emplace_back(index, yyextra->inputStringPrepass.right(length-i-2));
1858 }
1859 }
1860 yyextra->inputStringPrepass.resize(index);
1861}

◆ updateVariablePrepassComment()

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

Definition at line 1750 of file fortranscanner.l.

1751{
1752 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
1753 const CommentInPrepass *c = locatePrepassComment(yyscanner,from, to);
1754 if (c && yyextra->vtype == V_VARIABLE)
1755 {
1756 yyextra->last_entry->brief = c->str;
1757 }
1758 else if (c && yyextra->vtype == V_PARAMETER)
1759 {
1760 Argument *parameter = getParameter(yyscanner,yyextra->argName);
1761 if (parameter) parameter->docs = c->str;
1762 }
@ 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:47
1763}

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 379 of file fortranscanner.l.

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

◆ yyread()

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

Definition at line 2860 of file fortranscanner.l.

2861{
2862 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
2863 int c=0;
2864 while ( c < max_size && yyextra->inputString[yyextra->inputPosition] )
2865 {
2866 *buf = yyextra->inputString[yyextra->inputPosition++] ;
2867 c++; buf++;
2868 }
2869 return c;
2870}

Variable Documentation

◆ directionParam

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

Definition at line 144 of file fortranscanner.l.

144 {
145 "", "[in]", "[out]", "[in,out]"
146};

Referenced by subrHandleCommentBlock().

◆ directionStrs

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

Definition at line 140 of file fortranscanner.l.

140 {
141 "", "intent(in)", "intent(out)", "intent(inout)"
142};

Referenced by applyModifiers().