crackfortran --- read fortran (77,90) code and extract declaration information.
Copyright 1999-2004 Pearu Peterson all rights reserved, Pearu Peterson <pearu@ioc.ee> Permission to use, modify, and distribute this software is given under the terms of the NumPy License.
NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. $Date: 2005/09/27 07:13:49 $ Pearu Peterson
Usage of crackfortran:
- Command line keys: -quiet,-verbose,-fix,-f77,-f90,-show,-h <pyffilename>
- -m <module name for f77 routines>,--ignore-contains
Functions: crackfortran, crack2fortran The following Fortran statements/constructions are supported (or will be if needed):
block data,byte,call,character,common,complex,contains,data, dimension,double complex,double precision,end,external,function, implicit,integer,intent,interface,intrinsic, logical,module,optional,parameter,private,public, program,real,(sequence?),subroutine,type,use,virtual, include,pythonmodule
Note: 'virtual' is mapped to 'dimension'. Note: 'implicit integer (z) static (z)' is 'implicit static (z)' (this is minor bug). Note: code after 'contains' will be ignored until its scope ends. Note: 'common' statement is extended: dimensions are moved to variable definitions Note: f2py directive: <commentchar>f2py<line> is read as <line> Note: pythonmodule is introduced to represent Python module
- Usage:
postlist=crackfortran(files)
postlist
contains declaration information read from the list of filesfiles
.crack2fortran(postlist)
returns a fortran code to be saved to pyf-filepostlist
has the following structure:- *** it is a list of dictionaries containing `blocks':
- B = {'block','body','vars','parent_block'[,'name','prefix','args','result',
- 'implicit','externals','interfaced','common','sortvars', 'commonvars','note']}
- B['block'] = 'interface' | 'function' | 'subroutine' | 'module' |
- 'program' | 'block data' | 'type' | 'pythonmodule' | 'abstract interface'
B['body'] --- list containing `subblocks' with the same structure as `blocks' B['parent_block'] --- dictionary of a parent block:
C['body'][<index>]['parent_block'] is C
B['vars'] --- dictionary of variable definitions B['sortvars'] --- dictionary of variable definitions sorted by dependence (independent first) B['name'] --- name of the block (not if B['block']=='interface') B['prefix'] --- prefix string (only if B['block']=='function') B['args'] --- list of argument names if B['block']== 'function' | 'subroutine' B['result'] --- name of the return value (only if B['block']=='function') B['implicit'] --- dictionary {'a':<variable definition>,'b':...} | None B['externals'] --- list of variables being external B['interfaced'] --- list of variables being external and defined B['common'] --- dictionary of common blocks (list of objects) B['commonvars'] --- list of variables used in common blocks (dimensions are moved to variable definitions) B['from'] --- string showing the 'parents' of the current block B['use'] --- dictionary of modules used in current block:
{<modulename>:{['only':<0|1>],['map':{<local_name1>:<use_name1>,...}]}}
B['note'] --- list of LaTeX comments on the block B['f2pyenhancements'] --- optional dictionary
- {'threadsafe':'','fortranname':<name>,
- 'callstatement':<C-expr>|<multi-line block>, 'callprotoargument':<C-expr-list>, 'usercode':<multi-line block>|<list of multi-line blocks>, 'pymethoddef:<multi-line block>' }
B['entry'] --- dictionary {entryname:argslist,..} B['varnames'] --- list of variable names given in the order of reading the
Fortran code, useful for derived types.
B['saved_interface'] --- a string of scanned routine signature, defines explicit interface
- *** Variable definition is a dictionary
D = B['vars'][<variable name>] = {'typespec'[,'attrspec','kindselector','charselector','=','typename']} D['typespec'] = 'byte' | 'character' | 'complex' | 'double complex' |
'double precision' | 'integer' | 'logical' | 'real' | 'type'
- D['attrspec'] --- list of attributes (e.g. 'dimension(<arrayspec>)',
- 'external','intent(in|out|inout|hide|c|callback|cache|aligned4|aligned8|aligned16)', 'optional','required', etc)
- K = D['kindselector'] = {['*','kind']} (only if D['typespec'] =
- 'complex' | 'integer' | 'logical' | 'real' )
- C = D['charselector'] = {['*','len','kind','f2py_len']}
- (only if D['typespec']=='character')
D['='] --- initialization expression string D['typename'] --- name of the type if D['typespec']=='type' D['dimension'] --- list of dimension bounds D['intent'] --- list of intent specifications D['depend'] --- list of variable names on which current variable depends on D['check'] --- list of C-expressions; if C-expr returns zero, exception is raised D['note'] --- list of LaTeX comments on the variable
- *** Meaning of kind/char selectors (few examples):
- D['typespec>']*K['*'] D['typespec'](kind=K['kind']) character*C['*'] character(len=C['len'],kind=C['kind'], f2py_len=C['f2py_len']) (see also fortran type declaration statement formats below)
Fortran 90 type declaration statement format (F77 is subset of F90)
(Main source: IBM XL Fortran 5.1 Language Reference Manual) type declaration = <typespec> [[<attrspec>]::] <entitydecl> <typespec> = byte |
character[<charselector>] | complex[<kindselector>] | double complex | double precision | integer[<kindselector>] | logical[<kindselector>] | real[<kindselector>] | type(<typename>)
- <charselector> = * <charlen> |
- ([len=]<len>[,[kind=]<kind>]) | (kind=<kind>[,len=<len>])
- <kindselector> = * <intlen> |
- ([kind=]<kind>)
- <attrspec> = comma separated list of attributes.
Only the following attributes are used in building up the interface:
external (parameter --- affects '=' key) optional intent
Other attributes are ignored.
<intentspec> = in | out | inout <arrayspec> = comma separated list of dimension bounds. <entitydecl> = <name> [[*<charlen>][(<arrayspec>)] | [(<arrayspec>)]*<charlen>]
[/<init_expr>/ | =<init_expr>] [,<entitydecl>]
In addition, the following attributes are used: check,depend,note
- TODO:
- Apply 'parameter' attribute (e.g. 'integer parameter :: i=2' 'real x(i)'
- -> 'real x(2)')
The above may be solved by creating appropriate preprocessor program, for example.
Function | analyzeargs |
Undocumented |
Function | analyzebody |
Undocumented |
Function | analyzecommon |
Undocumented |
Function | analyzeline |
Undocumented |
Function | analyzevars |
Undocumented |
Function | appenddecl |
Undocumented |
Function | appendmultiline |
Undocumented |
Function | buildimplicitrules |
Undocumented |
Function | character |
Previously, Fortran character was incorrectly treated as character*1. This hook fixes the usage of the corresponding variables in check , dimension , = , and callstatement expressions. |
Function | common2fortran |
Undocumented |
Function | crack2fortran |
Undocumented |
Function | crack2fortrangen |
Undocumented |
Function | crackfortran |
Undocumented |
Function | crackline |
reset=-1 --- initialize reset=0 --- crack the line reset=1 --- final check if mismatch of blocks occurred |
Function | cracktypespec |
Undocumented |
Function | cracktypespec0 |
Undocumented |
Function | determineexprtype |
Undocumented |
Function | expr2name |
Undocumented |
Function | get |
Undocumented |
Function | get |
No summary |
Function | get |
Undocumented |
Function | get |
Undocumented |
Function | getblockname |
Undocumented |
Function | getextension |
Undocumented |
Function | getlincoef |
Obtain a and b when e == "a*x+b", where x is a symbol in xset. |
Function | is |
Check if file is in free format Fortran. |
Function | markinnerspaces |
The function replace all spaces in the input variable line which are surrounded with quotation marks, with the triplet "@_@". |
Function | markoutercomma |
Undocumented |
Function | markouterparen |
Undocumented |
Function | myeval |
Like eval but returns only integers and floats |
Function | openhook |
Ensures that filename is opened with correct encoding parameter. |
Function | outmess |
Undocumented |
Function | postcrack |
function return values determine expression types if in argument list |
Function | postcrack2 |
Undocumented |
Function | readfortrancode |
Get rid of comments, line continuations, and empty lines; lower cases. |
Function | removespaces |
Undocumented |
Function | reset |
Undocumented |
Function | rmbadname |
Undocumented |
Function | rmbadname1 |
Undocumented |
Function | setattrspec |
Undocumented |
Function | setcharselector |
Undocumented |
Function | setkindselector |
Undocumented |
Function | setmesstext |
Undocumented |
Function | sortvarnames |
Undocumented |
Function | split |
Splits the line into (line[:i], line[i:]), where i is the index of first occurrence of one of the characters not within quotes, or len(line) if no such index exists |
Function | traverse |
Traverse f2py data structure with the following visit function: |
Function | true |
Undocumented |
Function | undo |
Undocumented |
Function | undo |
Undocumented |
Function | unmarkouterparen |
Undocumented |
Function | updatevars |
Undocumented |
Function | use2fortran |
Undocumented |
Function | vars2fortran |
TODO: public sub ... |
Variable | analyzeargs |
Undocumented |
Variable | badnames |
Undocumented |
Variable | beforethisafter |
Undocumented |
Variable | beginpattern |
Undocumented |
Variable | beginpattern77 |
Undocumented |
Variable | beginpattern90 |
Undocumented |
Variable | callfunpattern |
Undocumented |
Variable | callnameargspattern |
Undocumented |
Variable | callpattern |
Undocumented |
Variable | charselector |
Undocumented |
Variable | commonpattern |
Undocumented |
Variable | containspattern |
Undocumented |
Variable | crackline |
Undocumented |
Variable | currentfilename |
Undocumented |
Variable | datapattern |
Undocumented |
Variable | debug |
Undocumented |
Variable | defaultimplicitrules |
Undocumented |
Variable | determineexprtype |
Undocumented |
Variable | determineexprtype |
Undocumented |
Variable | determineexprtype |
Undocumented |
Variable | determineexprtype |
Undocumented |
Variable | determineexprtype |
Undocumented |
Variable | dimensionpattern |
Undocumented |
Variable | dolowercase |
Undocumented |
Variable | endifpattern |
Undocumented |
Variable | endifs |
Undocumented |
Variable | endpattern |
Undocumented |
Variable | entrypattern |
Undocumented |
Variable | expectbegin |
Undocumented |
Variable | externalpattern |
Undocumented |
Variable | f2pyenhancementspattern |
Undocumented |
Variable | f77modulename |
Undocumented |
Variable | f90modulevars |
Undocumented |
Variable | filepositiontext |
Undocumented |
Variable | formatpattern |
Undocumented |
Variable | fortrantypes |
Undocumented |
Variable | functionpattern |
Undocumented |
Variable | getlincoef |
Undocumented |
Variable | gotnextfile |
Undocumented |
Variable | groupbegins77 |
Undocumented |
Variable | groupbegins90 |
Undocumented |
Variable | groupcache |
Undocumented |
Variable | groupcounter |
Undocumented |
Variable | groupends |
Undocumented |
Variable | grouplist |
Undocumented |
Variable | groupname |
Undocumented |
Variable | ignorecontains |
Undocumented |
Variable | implicitpattern |
Undocumented |
Variable | include |
Undocumented |
Variable | intentpattern |
Undocumented |
Variable | intrinsicpattern |
Undocumented |
Variable | invbadnames |
Undocumented |
Variable | is |
Undocumented |
Variable | kindselector |
Undocumented |
Variable | lenarraypattern |
Undocumented |
Variable | lenkindpattern |
Undocumented |
Variable | moduleprocedurepattern |
Undocumented |
Variable | moduleprocedures |
Undocumented |
Variable | multilinepattern |
Undocumented |
Variable | nameargspattern |
Undocumented |
Variable | namepattern |
Undocumented |
Variable | neededmodule |
Undocumented |
Variable | onlyfuncs |
Undocumented |
Variable | operatorpattern |
Undocumented |
Variable | optionalpattern |
Undocumented |
Variable | parameterpattern |
Undocumented |
Variable | post |
Undocumented |
Variable | previous |
Undocumented |
Variable | privatepattern |
Undocumented |
Variable | publicpattern |
Undocumented |
Variable | pyffilename |
Undocumented |
Variable | quiet |
Undocumented |
Variable | real16pattern |
Undocumented |
Variable | real8pattern |
Undocumented |
Variable | requiredpattern |
Undocumented |
Variable | selectpattern |
Undocumented |
Variable | skipblocksuntil |
Undocumented |
Variable | skipemptyends |
Undocumented |
Variable | skipfuncs |
Undocumented |
Variable | skipfunctions |
Undocumented |
Variable | sourcecodeform |
Undocumented |
Variable | strictf77 |
Undocumented |
Variable | subroutinepattern |
Undocumented |
Variable | tabchar |
Undocumented |
Variable | typedefpattern |
Undocumented |
Variable | typespattern |
Undocumented |
Variable | typespattern4implicit |
Undocumented |
Variable | usepattern |
Undocumented |
Variable | usermodules |
Undocumented |
Variable | verbose |
Undocumented |
Variable | word |
Undocumented |
Function | _calc |
Undocumented |
Function | _ensure |
Undocumented |
Function | _eval |
Undocumented |
Function | _eval |
Undocumented |
Function | _get |
Undocumented |
Function | _is |
Undocumented |
Function | _is |
Undocumented |
Function | _kind |
Undocumented |
Function | _resolvenameargspattern |
Undocumented |
Function | _resolvetypedefpattern |
Undocumented |
Function | _selected |
Undocumented |
Function | _selected |
Undocumented |
Function | _simplifyargs |
Undocumented |
Variable | _free |
Undocumented |
Variable | _has |
Undocumented |
Variable | _has |
Undocumented |
Variable | _has |
Undocumented |
Variable | _intentcallbackpattern |
Undocumented |
Variable | _is |
Undocumented |
Previously, Fortran character was incorrectly treated as
character*1. This hook fixes the usage of the corresponding
variables in check
, dimension
, =
, and callstatement
expressions.
The usage of char*
in callprotoargument
expression can be left
unchanged because C character
is C typedef of char
, although,
new implementations should use character*
in the corresponding
expressions.
See https://github.com/numpy/numpy/pull/19388 for more information.
reset=-1 --- initialize reset=0 --- crack the line reset=1 --- final check if mismatch of blocks occurred
Cracked data is saved in grouplist[0].
Obtain a and b when e == "a*x+b", where x is a symbol in xset.
>>> getlincoef('2*x + 1', {'x'}) (2, 1, 'x') >>> getlincoef('3*x + x*2 + 2 + 1', {'x'}) (5, 3, 'x') >>> getlincoef('0', {'x'}) (0, 0, None) >>> getlincoef('0*x', {'x'}) (0, 0, 'x') >>> getlincoef('x*x', {'x'}) (None, None, None)
This can be tricked by sufficiently complex expressions
>>> getlincoef('(x - 0.5)*(x - 1.5)*(x - 1)*x + 2*x + 3', {'x'}) (2.0, 3.0, 'x')
Ensures that filename is opened with correct encoding parameter.
This function uses charset_normalizer package, when available, for determining the encoding of the file to be opened. When charset_normalizer is not available, the function detects only UTF encodings, otherwise, ASCII encoding is used as fallback.
- Read fortran codes from files and
- Get rid of comments, line continuations, and empty lines; lower cases.
- Call dowithline(line) on every line.
- Recursively call itself when statement "include '<filename>'" is met.
Splits the line into (line[:i], line[i:]), where i is the index of first occurrence of one of the characters not within quotes, or len(line) if no such index exists
Traverse f2py data structure with the following visit function:
- def visit(item, parents, result, *args, **kwargs):
"""
parents is a list of key-"f2py data structure" pairs from which items are taken from.
result is a f2py data structure that is filled with the return value of the visit function.
item is 2-tuple (index, value) if parents[-1][1] is a list item is 2-tuple (key, value) if parents[-1][1] is a dict
The return value of visit must be None, or of the same kind as item, that is, if parents[-1] is a list, the return value must be 2-tuple (new_index, new_value), or if parents[-1] is a dict, the return value must be 2-tuple (new_key, new_value).
If new_index or new_value is None, the return value of visit is ignored, that is, it will not be added to the result.
If the return value is None, the content of obj will be traversed, otherwise not. """