annotate DEPENDENCIES/mingw32/Python27/Lib/site-packages/numpy/f2py/crackfortran.py @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2a2c65a20a8b
children
rev   line source
Chris@87 1 #!/usr/bin/env python
Chris@87 2 """
Chris@87 3 crackfortran --- read fortran (77,90) code and extract declaration information.
Chris@87 4
Chris@87 5 Copyright 1999-2004 Pearu Peterson all rights reserved,
Chris@87 6 Pearu Peterson <pearu@ioc.ee>
Chris@87 7 Permission to use, modify, and distribute this software is given under the
Chris@87 8 terms of the NumPy License.
Chris@87 9
Chris@87 10 NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
Chris@87 11 $Date: 2005/09/27 07:13:49 $
Chris@87 12 Pearu Peterson
Chris@87 13
Chris@87 14
Chris@87 15 Usage of crackfortran:
Chris@87 16 ======================
Chris@87 17 Command line keys: -quiet,-verbose,-fix,-f77,-f90,-show,-h <pyffilename>
Chris@87 18 -m <module name for f77 routines>,--ignore-contains
Chris@87 19 Functions: crackfortran, crack2fortran
Chris@87 20 The following Fortran statements/constructions are supported
Chris@87 21 (or will be if needed):
Chris@87 22 block data,byte,call,character,common,complex,contains,data,
Chris@87 23 dimension,double complex,double precision,end,external,function,
Chris@87 24 implicit,integer,intent,interface,intrinsic,
Chris@87 25 logical,module,optional,parameter,private,public,
Chris@87 26 program,real,(sequence?),subroutine,type,use,virtual,
Chris@87 27 include,pythonmodule
Chris@87 28 Note: 'virtual' is mapped to 'dimension'.
Chris@87 29 Note: 'implicit integer (z) static (z)' is 'implicit static (z)' (this is minor bug).
Chris@87 30 Note: code after 'contains' will be ignored until its scope ends.
Chris@87 31 Note: 'common' statement is extended: dimensions are moved to variable definitions
Chris@87 32 Note: f2py directive: <commentchar>f2py<line> is read as <line>
Chris@87 33 Note: pythonmodule is introduced to represent Python module
Chris@87 34
Chris@87 35 Usage:
Chris@87 36 `postlist=crackfortran(files,funcs)`
Chris@87 37 `postlist` contains declaration information read from the list of files `files`.
Chris@87 38 `crack2fortran(postlist)` returns a fortran code to be saved to pyf-file
Chris@87 39
Chris@87 40 `postlist` has the following structure:
Chris@87 41 *** it is a list of dictionaries containing `blocks':
Chris@87 42 B = {'block','body','vars','parent_block'[,'name','prefix','args','result',
Chris@87 43 'implicit','externals','interfaced','common','sortvars',
Chris@87 44 'commonvars','note']}
Chris@87 45 B['block'] = 'interface' | 'function' | 'subroutine' | 'module' |
Chris@87 46 'program' | 'block data' | 'type' | 'pythonmodule'
Chris@87 47 B['body'] --- list containing `subblocks' with the same structure as `blocks'
Chris@87 48 B['parent_block'] --- dictionary of a parent block:
Chris@87 49 C['body'][<index>]['parent_block'] is C
Chris@87 50 B['vars'] --- dictionary of variable definitions
Chris@87 51 B['sortvars'] --- dictionary of variable definitions sorted by dependence (independent first)
Chris@87 52 B['name'] --- name of the block (not if B['block']=='interface')
Chris@87 53 B['prefix'] --- prefix string (only if B['block']=='function')
Chris@87 54 B['args'] --- list of argument names if B['block']== 'function' | 'subroutine'
Chris@87 55 B['result'] --- name of the return value (only if B['block']=='function')
Chris@87 56 B['implicit'] --- dictionary {'a':<variable definition>,'b':...} | None
Chris@87 57 B['externals'] --- list of variables being external
Chris@87 58 B['interfaced'] --- list of variables being external and defined
Chris@87 59 B['common'] --- dictionary of common blocks (list of objects)
Chris@87 60 B['commonvars'] --- list of variables used in common blocks (dimensions are moved to variable definitions)
Chris@87 61 B['from'] --- string showing the 'parents' of the current block
Chris@87 62 B['use'] --- dictionary of modules used in current block:
Chris@87 63 {<modulename>:{['only':<0|1>],['map':{<local_name1>:<use_name1>,...}]}}
Chris@87 64 B['note'] --- list of LaTeX comments on the block
Chris@87 65 B['f2pyenhancements'] --- optional dictionary
Chris@87 66 {'threadsafe':'','fortranname':<name>,
Chris@87 67 'callstatement':<C-expr>|<multi-line block>,
Chris@87 68 'callprotoargument':<C-expr-list>,
Chris@87 69 'usercode':<multi-line block>|<list of multi-line blocks>,
Chris@87 70 'pymethoddef:<multi-line block>'
Chris@87 71 }
Chris@87 72 B['entry'] --- dictionary {entryname:argslist,..}
Chris@87 73 B['varnames'] --- list of variable names given in the order of reading the
Chris@87 74 Fortran code, useful for derived types.
Chris@87 75 B['saved_interface'] --- a string of scanned routine signature, defines explicit interface
Chris@87 76 *** Variable definition is a dictionary
Chris@87 77 D = B['vars'][<variable name>] =
Chris@87 78 {'typespec'[,'attrspec','kindselector','charselector','=','typename']}
Chris@87 79 D['typespec'] = 'byte' | 'character' | 'complex' | 'double complex' |
Chris@87 80 'double precision' | 'integer' | 'logical' | 'real' | 'type'
Chris@87 81 D['attrspec'] --- list of attributes (e.g. 'dimension(<arrayspec>)',
Chris@87 82 'external','intent(in|out|inout|hide|c|callback|cache|aligned4|aligned8|aligned16)',
Chris@87 83 'optional','required', etc)
Chris@87 84 K = D['kindselector'] = {['*','kind']} (only if D['typespec'] =
Chris@87 85 'complex' | 'integer' | 'logical' | 'real' )
Chris@87 86 C = D['charselector'] = {['*','len','kind']}
Chris@87 87 (only if D['typespec']=='character')
Chris@87 88 D['='] --- initialization expression string
Chris@87 89 D['typename'] --- name of the type if D['typespec']=='type'
Chris@87 90 D['dimension'] --- list of dimension bounds
Chris@87 91 D['intent'] --- list of intent specifications
Chris@87 92 D['depend'] --- list of variable names on which current variable depends on
Chris@87 93 D['check'] --- list of C-expressions; if C-expr returns zero, exception is raised
Chris@87 94 D['note'] --- list of LaTeX comments on the variable
Chris@87 95 *** Meaning of kind/char selectors (few examples):
Chris@87 96 D['typespec>']*K['*']
Chris@87 97 D['typespec'](kind=K['kind'])
Chris@87 98 character*C['*']
Chris@87 99 character(len=C['len'],kind=C['kind'])
Chris@87 100 (see also fortran type declaration statement formats below)
Chris@87 101
Chris@87 102 Fortran 90 type declaration statement format (F77 is subset of F90)
Chris@87 103 ====================================================================
Chris@87 104 (Main source: IBM XL Fortran 5.1 Language Reference Manual)
Chris@87 105 type declaration = <typespec> [[<attrspec>]::] <entitydecl>
Chris@87 106 <typespec> = byte |
Chris@87 107 character[<charselector>] |
Chris@87 108 complex[<kindselector>] |
Chris@87 109 double complex |
Chris@87 110 double precision |
Chris@87 111 integer[<kindselector>] |
Chris@87 112 logical[<kindselector>] |
Chris@87 113 real[<kindselector>] |
Chris@87 114 type(<typename>)
Chris@87 115 <charselector> = * <charlen> |
Chris@87 116 ([len=]<len>[,[kind=]<kind>]) |
Chris@87 117 (kind=<kind>[,len=<len>])
Chris@87 118 <kindselector> = * <intlen> |
Chris@87 119 ([kind=]<kind>)
Chris@87 120 <attrspec> = comma separated list of attributes.
Chris@87 121 Only the following attributes are used in
Chris@87 122 building up the interface:
Chris@87 123 external
Chris@87 124 (parameter --- affects '=' key)
Chris@87 125 optional
Chris@87 126 intent
Chris@87 127 Other attributes are ignored.
Chris@87 128 <intentspec> = in | out | inout
Chris@87 129 <arrayspec> = comma separated list of dimension bounds.
Chris@87 130 <entitydecl> = <name> [[*<charlen>][(<arrayspec>)] | [(<arrayspec>)]*<charlen>]
Chris@87 131 [/<init_expr>/ | =<init_expr>] [,<entitydecl>]
Chris@87 132
Chris@87 133 In addition, the following attributes are used: check,depend,note
Chris@87 134
Chris@87 135 TODO:
Chris@87 136 * Apply 'parameter' attribute (e.g. 'integer parameter :: i=2' 'real x(i)'
Chris@87 137 -> 'real x(2)')
Chris@87 138 The above may be solved by creating appropriate preprocessor program, for example.
Chris@87 139
Chris@87 140 """
Chris@87 141 from __future__ import division, absolute_import, print_function
Chris@87 142
Chris@87 143 import sys
Chris@87 144 import string
Chris@87 145 import fileinput
Chris@87 146 import re
Chris@87 147 import pprint
Chris@87 148 import os
Chris@87 149 import copy
Chris@87 150 import platform
Chris@87 151
Chris@87 152 from . import __version__
Chris@87 153 from .auxfuncs import *
Chris@87 154
Chris@87 155 f2py_version = __version__.version
Chris@87 156
Chris@87 157 # Global flags:
Chris@87 158 strictf77=1 # Ignore `!' comments unless line[0]=='!'
Chris@87 159 sourcecodeform='fix' # 'fix','free'
Chris@87 160 quiet=0 # Be verbose if 0 (Obsolete: not used any more)
Chris@87 161 verbose=1 # Be quiet if 0, extra verbose if > 1.
Chris@87 162 tabchar=4*' '
Chris@87 163 pyffilename=''
Chris@87 164 f77modulename=''
Chris@87 165 skipemptyends=0 # for old F77 programs without 'program' statement
Chris@87 166 ignorecontains=1
Chris@87 167 dolowercase=1
Chris@87 168 debug=[]
Chris@87 169
Chris@87 170 # Global variables
Chris@87 171 groupcounter=0
Chris@87 172 grouplist={groupcounter:[]}
Chris@87 173 neededmodule=-1
Chris@87 174 expectbegin=1
Chris@87 175 skipblocksuntil=-1
Chris@87 176 usermodules=[]
Chris@87 177 f90modulevars={}
Chris@87 178 gotnextfile=1
Chris@87 179 filepositiontext=''
Chris@87 180 currentfilename=''
Chris@87 181 skipfunctions=[]
Chris@87 182 skipfuncs=[]
Chris@87 183 onlyfuncs=[]
Chris@87 184 include_paths=[]
Chris@87 185 previous_context = None
Chris@87 186
Chris@87 187
Chris@87 188 def reset_global_f2py_vars():
Chris@87 189 global groupcounter, grouplist, neededmodule, expectbegin, \
Chris@87 190 skipblocksuntil, usermodules, f90modulevars, gotnextfile, \
Chris@87 191 filepositiontext, currentfilename, skipfunctions, skipfuncs, \
Chris@87 192 onlyfuncs, include_paths, previous_context, \
Chris@87 193 strictf77, sourcecodeform, quiet, verbose, tabchar, pyffilename, \
Chris@87 194 f77modulename, skipemptyends, ignorecontains, dolowercase, debug
Chris@87 195
Chris@87 196 # flags
Chris@87 197 strictf77 = 1
Chris@87 198 sourcecodeform = 'fix'
Chris@87 199 quiet = 0
Chris@87 200 verbose = 1
Chris@87 201 tabchar = 4*' '
Chris@87 202 pyffilename = ''
Chris@87 203 f77modulename = ''
Chris@87 204 skipemptyends = 0
Chris@87 205 ignorecontains = 1
Chris@87 206 dolowercase = 1
Chris@87 207 debug = []
Chris@87 208 # variables
Chris@87 209 groupcounter = 0
Chris@87 210 grouplist = {groupcounter:[]}
Chris@87 211 neededmodule =-1
Chris@87 212 expectbegin = 1
Chris@87 213 skipblocksuntil = -1
Chris@87 214 usermodules = []
Chris@87 215 f90modulevars = {}
Chris@87 216 gotnextfile = 1
Chris@87 217 filepositiontext = ''
Chris@87 218 currentfilename = ''
Chris@87 219 skipfunctions = []
Chris@87 220 skipfuncs = []
Chris@87 221 onlyfuncs = []
Chris@87 222 include_paths = []
Chris@87 223 previous_context = None
Chris@87 224
Chris@87 225
Chris@87 226 ###### Some helper functions
Chris@87 227 def show(o,f=0):pprint.pprint(o)
Chris@87 228 errmess=sys.stderr.write
Chris@87 229 def outmess(line,flag=1):
Chris@87 230 global filepositiontext
Chris@87 231 if not verbose: return
Chris@87 232 if not quiet:
Chris@87 233 if flag:sys.stdout.write(filepositiontext)
Chris@87 234 sys.stdout.write(line)
Chris@87 235 re._MAXCACHE=50
Chris@87 236 defaultimplicitrules={}
Chris@87 237 for c in "abcdefghopqrstuvwxyz$_": defaultimplicitrules[c]={'typespec':'real'}
Chris@87 238 for c in "ijklmn": defaultimplicitrules[c]={'typespec':'integer'}
Chris@87 239 del c
Chris@87 240 badnames={}
Chris@87 241 invbadnames={}
Chris@87 242 for n in ['int', 'double', 'float', 'char', 'short', 'long', 'void', 'case', 'while',
Chris@87 243 'return', 'signed', 'unsigned', 'if', 'for', 'typedef', 'sizeof', 'union',
Chris@87 244 'struct', 'static', 'register', 'new', 'break', 'do', 'goto', 'switch',
Chris@87 245 'continue', 'else', 'inline', 'extern', 'delete', 'const', 'auto',
Chris@87 246 'len', 'rank', 'shape', 'index', 'slen', 'size', '_i',
Chris@87 247 'max', 'min',
Chris@87 248 'flen', 'fshape',
Chris@87 249 'string', 'complex_double', 'float_double', 'stdin', 'stderr', 'stdout',
Chris@87 250 'type', 'default']:
Chris@87 251 badnames[n]=n+'_bn'
Chris@87 252 invbadnames[n+'_bn']=n
Chris@87 253
Chris@87 254 def rmbadname1(name):
Chris@87 255 if name in badnames:
Chris@87 256 errmess('rmbadname1: Replacing "%s" with "%s".\n'%(name, badnames[name]))
Chris@87 257 return badnames[name]
Chris@87 258 return name
Chris@87 259
Chris@87 260 def rmbadname(names): return [rmbadname1(_m) for _m in names]
Chris@87 261
Chris@87 262 def undo_rmbadname1(name):
Chris@87 263 if name in invbadnames:
Chris@87 264 errmess('undo_rmbadname1: Replacing "%s" with "%s".\n'\
Chris@87 265 %(name, invbadnames[name]))
Chris@87 266 return invbadnames[name]
Chris@87 267 return name
Chris@87 268
Chris@87 269 def undo_rmbadname(names): return [undo_rmbadname1(_m) for _m in names]
Chris@87 270
Chris@87 271 def getextension(name):
Chris@87 272 i=name.rfind('.')
Chris@87 273 if i==-1: return ''
Chris@87 274 if '\\' in name[i:]: return ''
Chris@87 275 if '/' in name[i:]: return ''
Chris@87 276 return name[i+1:]
Chris@87 277
Chris@87 278 is_f_file = re.compile(r'.*[.](for|ftn|f77|f)\Z', re.I).match
Chris@87 279 _has_f_header = re.compile(r'-[*]-\s*fortran\s*-[*]-', re.I).search
Chris@87 280 _has_f90_header = re.compile(r'-[*]-\s*f90\s*-[*]-', re.I).search
Chris@87 281 _has_fix_header = re.compile(r'-[*]-\s*fix\s*-[*]-', re.I).search
Chris@87 282 _free_f90_start = re.compile(r'[^c*]\s*[^\s\d\t]', re.I).match
Chris@87 283 def is_free_format(file):
Chris@87 284 """Check if file is in free format Fortran."""
Chris@87 285 # f90 allows both fixed and free format, assuming fixed unless
Chris@87 286 # signs of free format are detected.
Chris@87 287 result = 0
Chris@87 288 f = open(file, 'r')
Chris@87 289 line = f.readline()
Chris@87 290 n = 15 # the number of non-comment lines to scan for hints
Chris@87 291 if _has_f_header(line):
Chris@87 292 n = 0
Chris@87 293 elif _has_f90_header(line):
Chris@87 294 n = 0
Chris@87 295 result = 1
Chris@87 296 while n>0 and line:
Chris@87 297 if line[0]!='!' and line.strip():
Chris@87 298 n -= 1
Chris@87 299 if (line[0]!='\t' and _free_f90_start(line[:5])) or line[-2:-1]=='&':
Chris@87 300 result = 1
Chris@87 301 break
Chris@87 302 line = f.readline()
Chris@87 303 f.close()
Chris@87 304 return result
Chris@87 305
Chris@87 306
Chris@87 307 ####### Read fortran (77,90) code
Chris@87 308 def readfortrancode(ffile,dowithline=show,istop=1):
Chris@87 309 """
Chris@87 310 Read fortran codes from files and
Chris@87 311 1) Get rid of comments, line continuations, and empty lines; lower cases.
Chris@87 312 2) Call dowithline(line) on every line.
Chris@87 313 3) Recursively call itself when statement \"include '<filename>'\" is met.
Chris@87 314 """
Chris@87 315 global gotnextfile, filepositiontext, currentfilename, sourcecodeform, strictf77,\
Chris@87 316 beginpattern, quiet, verbose, dolowercase, include_paths
Chris@87 317 if not istop:
Chris@87 318 saveglobals=gotnextfile, filepositiontext, currentfilename, sourcecodeform, strictf77,\
Chris@87 319 beginpattern, quiet, verbose, dolowercase
Chris@87 320 if ffile==[]: return
Chris@87 321 localdolowercase = dolowercase
Chris@87 322 cont=0
Chris@87 323 finalline=''
Chris@87 324 ll=''
Chris@87 325 commentline=re.compile(r'(?P<line>([^"]*["][^"]*["][^"!]*|[^\']*\'[^\']*\'[^\'!]*|[^!\'"]*))!{1}(?P<rest>.*)')
Chris@87 326 includeline=re.compile(r'\s*include\s*(\'|")(?P<name>[^\'"]*)(\'|")', re.I)
Chris@87 327 cont1=re.compile(r'(?P<line>.*)&\s*\Z')
Chris@87 328 cont2=re.compile(r'(\s*&|)(?P<line>.*)')
Chris@87 329 mline_mark = re.compile(r".*?'''")
Chris@87 330 if istop: dowithline('', -1)
Chris@87 331 ll, l1='', ''
Chris@87 332 spacedigits=[' '] + [str(_m) for _m in range(10)]
Chris@87 333 filepositiontext=''
Chris@87 334 fin=fileinput.FileInput(ffile)
Chris@87 335 while True:
Chris@87 336 l=fin.readline()
Chris@87 337 if not l: break
Chris@87 338 if fin.isfirstline():
Chris@87 339 filepositiontext=''
Chris@87 340 currentfilename=fin.filename()
Chris@87 341 gotnextfile=1
Chris@87 342 l1=l
Chris@87 343 strictf77=0
Chris@87 344 sourcecodeform='fix'
Chris@87 345 ext = os.path.splitext(currentfilename)[1]
Chris@87 346 if is_f_file(currentfilename) and \
Chris@87 347 not (_has_f90_header(l) or _has_fix_header(l)):
Chris@87 348 strictf77=1
Chris@87 349 elif is_free_format(currentfilename) and not _has_fix_header(l):
Chris@87 350 sourcecodeform='free'
Chris@87 351 if strictf77: beginpattern=beginpattern77
Chris@87 352 else: beginpattern=beginpattern90
Chris@87 353 outmess('\tReading file %s (format:%s%s)\n'\
Chris@87 354 %(repr(currentfilename), sourcecodeform,
Chris@87 355 strictf77 and ',strict' or ''))
Chris@87 356
Chris@87 357 l=l.expandtabs().replace('\xa0', ' ')
Chris@87 358 while not l=='': # Get rid of newline characters
Chris@87 359 if l[-1] not in "\n\r\f": break
Chris@87 360 l=l[:-1]
Chris@87 361 if not strictf77:
Chris@87 362 r=commentline.match(l)
Chris@87 363 if r:
Chris@87 364 l=r.group('line')+' ' # Strip comments starting with `!'
Chris@87 365 rl=r.group('rest')
Chris@87 366 if rl[:4].lower()=='f2py': # f2py directive
Chris@87 367 l = l + 4*' '
Chris@87 368 r=commentline.match(rl[4:])
Chris@87 369 if r: l=l+r.group('line')
Chris@87 370 else: l = l + rl[4:]
Chris@87 371 if l.strip()=='': # Skip empty line
Chris@87 372 cont=0
Chris@87 373 continue
Chris@87 374 if sourcecodeform=='fix':
Chris@87 375 if l[0] in ['*', 'c', '!', 'C', '#']:
Chris@87 376 if l[1:5].lower()=='f2py': # f2py directive
Chris@87 377 l=' '+l[5:]
Chris@87 378 else: # Skip comment line
Chris@87 379 cont=0
Chris@87 380 continue
Chris@87 381 elif strictf77:
Chris@87 382 if len(l)>72: l=l[:72]
Chris@87 383 if not (l[0] in spacedigits):
Chris@87 384 raise Exception('readfortrancode: Found non-(space,digit) char '
Chris@87 385 'in the first column.\n\tAre you sure that '
Chris@87 386 'this code is in fix form?\n\tline=%s' % repr(l))
Chris@87 387
Chris@87 388 if (not cont or strictf77) and (len(l)>5 and not l[5]==' '):
Chris@87 389 # Continuation of a previous line
Chris@87 390 ll=ll+l[6:]
Chris@87 391 finalline=''
Chris@87 392 origfinalline=''
Chris@87 393 else:
Chris@87 394 if not strictf77:
Chris@87 395 # F90 continuation
Chris@87 396 r=cont1.match(l)
Chris@87 397 if r: l=r.group('line') # Continuation follows ..
Chris@87 398 if cont:
Chris@87 399 ll=ll+cont2.match(l).group('line')
Chris@87 400 finalline=''
Chris@87 401 origfinalline=''
Chris@87 402 else:
Chris@87 403 l=' '+l[5:] # clean up line beginning from possible digits.
Chris@87 404 if localdolowercase: finalline=ll.lower()
Chris@87 405 else: finalline=ll
Chris@87 406 origfinalline=ll
Chris@87 407 ll=l
Chris@87 408 cont=(r is not None)
Chris@87 409 else:
Chris@87 410 l=' '+l[5:] # clean up line beginning from possible digits.
Chris@87 411 if localdolowercase: finalline=ll.lower()
Chris@87 412 else: finalline=ll
Chris@87 413 origfinalline =ll
Chris@87 414 ll=l
Chris@87 415
Chris@87 416 elif sourcecodeform=='free':
Chris@87 417 if not cont and ext=='.pyf' and mline_mark.match(l):
Chris@87 418 l = l + '\n'
Chris@87 419 while True:
Chris@87 420 lc = fin.readline()
Chris@87 421 if not lc:
Chris@87 422 errmess('Unexpected end of file when reading multiline\n')
Chris@87 423 break
Chris@87 424 l = l + lc
Chris@87 425 if mline_mark.match(lc):
Chris@87 426 break
Chris@87 427 l = l.rstrip()
Chris@87 428 r=cont1.match(l)
Chris@87 429 if r: l=r.group('line') # Continuation follows ..
Chris@87 430 if cont:
Chris@87 431 ll=ll+cont2.match(l).group('line')
Chris@87 432 finalline=''
Chris@87 433 origfinalline=''
Chris@87 434 else:
Chris@87 435 if localdolowercase: finalline=ll.lower()
Chris@87 436 else: finalline=ll
Chris@87 437 origfinalline =ll
Chris@87 438 ll=l
Chris@87 439 cont=(r is not None)
Chris@87 440 else:
Chris@87 441 raise ValueError("Flag sourcecodeform must be either 'fix' or 'free': %s"%repr(sourcecodeform))
Chris@87 442 filepositiontext='Line #%d in %s:"%s"\n\t' % (fin.filelineno()-1, currentfilename, l1)
Chris@87 443 m=includeline.match(origfinalline)
Chris@87 444 if m:
Chris@87 445 fn=m.group('name')
Chris@87 446 if os.path.isfile(fn):
Chris@87 447 readfortrancode(fn, dowithline=dowithline, istop=0)
Chris@87 448 else:
Chris@87 449 include_dirs = [os.path.dirname(currentfilename)] + include_paths
Chris@87 450 foundfile = 0
Chris@87 451 for inc_dir in include_dirs:
Chris@87 452 fn1 = os.path.join(inc_dir, fn)
Chris@87 453 if os.path.isfile(fn1):
Chris@87 454 foundfile = 1
Chris@87 455 readfortrancode(fn1, dowithline=dowithline, istop=0)
Chris@87 456 break
Chris@87 457 if not foundfile:
Chris@87 458 outmess('readfortrancode: could not find include file %s in %s. Ignoring.\n'%(repr(fn), os.pathsep.join(include_dirs)))
Chris@87 459 else:
Chris@87 460 dowithline(finalline)
Chris@87 461 l1=ll
Chris@87 462 if localdolowercase:
Chris@87 463 finalline=ll.lower()
Chris@87 464 else: finalline=ll
Chris@87 465 origfinalline = ll
Chris@87 466 filepositiontext='Line #%d in %s:"%s"\n\t' % (fin.filelineno()-1, currentfilename, l1)
Chris@87 467 m=includeline.match(origfinalline)
Chris@87 468 if m:
Chris@87 469 fn=m.group('name')
Chris@87 470 if os.path.isfile(fn):
Chris@87 471 readfortrancode(fn, dowithline=dowithline, istop=0)
Chris@87 472 else:
Chris@87 473 include_dirs = [os.path.dirname(currentfilename)] + include_paths
Chris@87 474 foundfile = 0
Chris@87 475 for inc_dir in include_dirs:
Chris@87 476 fn1 = os.path.join(inc_dir, fn)
Chris@87 477 if os.path.isfile(fn1):
Chris@87 478 foundfile = 1
Chris@87 479 readfortrancode(fn1, dowithline=dowithline, istop=0)
Chris@87 480 break
Chris@87 481 if not foundfile:
Chris@87 482 outmess('readfortrancode: could not find include file %s in %s. Ignoring.\n'%(repr(fn), os.pathsep.join(include_dirs)))
Chris@87 483 else:
Chris@87 484 dowithline(finalline)
Chris@87 485 filepositiontext=''
Chris@87 486 fin.close()
Chris@87 487 if istop: dowithline('', 1)
Chris@87 488 else:
Chris@87 489 gotnextfile, filepositiontext, currentfilename, sourcecodeform, strictf77,\
Chris@87 490 beginpattern, quiet, verbose, dolowercase=saveglobals
Chris@87 491
Chris@87 492 ########### Crack line
Chris@87 493 beforethisafter=r'\s*(?P<before>%s(?=\s*(\b(%s)\b)))'+ \
Chris@87 494 r'\s*(?P<this>(\b(%s)\b))'+ \
Chris@87 495 r'\s*(?P<after>%s)\s*\Z'
Chris@87 496 ##
Chris@87 497 fortrantypes='character|logical|integer|real|complex|double\s*(precision\s*(complex|)|complex)|type(?=\s*\([\w\s,=(*)]*\))|byte'
Chris@87 498 typespattern=re.compile(beforethisafter%('', fortrantypes, fortrantypes, '.*'), re.I), 'type'
Chris@87 499 typespattern4implicit=re.compile(beforethisafter%('', fortrantypes+'|static|automatic|undefined', fortrantypes+'|static|automatic|undefined', '.*'), re.I)
Chris@87 500 #
Chris@87 501 functionpattern=re.compile(beforethisafter%('([a-z]+[\w\s(=*+-/)]*?|)', 'function', 'function', '.*'), re.I), 'begin'
Chris@87 502 subroutinepattern=re.compile(beforethisafter%('[a-z\s]*?', 'subroutine', 'subroutine', '.*'), re.I), 'begin'
Chris@87 503 #modulepattern=re.compile(beforethisafter%('[a-z\s]*?','module','module','.*'),re.I),'begin'
Chris@87 504 #
Chris@87 505 groupbegins77=r'program|block\s*data'
Chris@87 506 beginpattern77=re.compile(beforethisafter%('', groupbegins77, groupbegins77, '.*'), re.I), 'begin'
Chris@87 507 groupbegins90=groupbegins77+r'|module(?!\s*procedure)|python\s*module|interface|type(?!\s*\()'
Chris@87 508 beginpattern90=re.compile(beforethisafter%('', groupbegins90, groupbegins90, '.*'), re.I), 'begin'
Chris@87 509 groupends=r'end|endprogram|endblockdata|endmodule|endpythonmodule|endinterface'
Chris@87 510 endpattern=re.compile(beforethisafter%('', groupends, groupends, '[\w\s]*'), re.I), 'end'
Chris@87 511 #endifs='end\s*(if|do|where|select|while|forall)'
Chris@87 512 endifs='(end\s*(if|do|where|select|while|forall))|(module\s*procedure)'
Chris@87 513 endifpattern=re.compile(beforethisafter%('[\w]*?', endifs, endifs, '[\w\s]*'), re.I), 'endif'
Chris@87 514 #
Chris@87 515 implicitpattern=re.compile(beforethisafter%('', 'implicit', 'implicit', '.*'), re.I), 'implicit'
Chris@87 516 dimensionpattern=re.compile(beforethisafter%('', 'dimension|virtual', 'dimension|virtual', '.*'), re.I), 'dimension'
Chris@87 517 externalpattern=re.compile(beforethisafter%('', 'external', 'external', '.*'), re.I), 'external'
Chris@87 518 optionalpattern=re.compile(beforethisafter%('', 'optional', 'optional', '.*'), re.I), 'optional'
Chris@87 519 requiredpattern=re.compile(beforethisafter%('', 'required', 'required', '.*'), re.I), 'required'
Chris@87 520 publicpattern=re.compile(beforethisafter%('', 'public', 'public', '.*'), re.I), 'public'
Chris@87 521 privatepattern=re.compile(beforethisafter%('', 'private', 'private', '.*'), re.I), 'private'
Chris@87 522 intrisicpattern=re.compile(beforethisafter%('', 'intrisic', 'intrisic', '.*'), re.I), 'intrisic'
Chris@87 523 intentpattern=re.compile(beforethisafter%('', 'intent|depend|note|check', 'intent|depend|note|check', '\s*\(.*?\).*'), re.I), 'intent'
Chris@87 524 parameterpattern=re.compile(beforethisafter%('', 'parameter', 'parameter', '\s*\(.*'), re.I), 'parameter'
Chris@87 525 datapattern=re.compile(beforethisafter%('', 'data', 'data', '.*'), re.I), 'data'
Chris@87 526 callpattern=re.compile(beforethisafter%('', 'call', 'call', '.*'), re.I), 'call'
Chris@87 527 entrypattern=re.compile(beforethisafter%('', 'entry', 'entry', '.*'), re.I), 'entry'
Chris@87 528 callfunpattern=re.compile(beforethisafter%('', 'callfun', 'callfun', '.*'), re.I), 'callfun'
Chris@87 529 commonpattern=re.compile(beforethisafter%('', 'common', 'common', '.*'), re.I), 'common'
Chris@87 530 usepattern=re.compile(beforethisafter%('', 'use', 'use', '.*'), re.I), 'use'
Chris@87 531 containspattern=re.compile(beforethisafter%('', 'contains', 'contains', ''), re.I), 'contains'
Chris@87 532 formatpattern=re.compile(beforethisafter%('', 'format', 'format', '.*'), re.I), 'format'
Chris@87 533 ## Non-fortran and f2py-specific statements
Chris@87 534 f2pyenhancementspattern=re.compile(beforethisafter%('', 'threadsafe|fortranname|callstatement|callprotoargument|usercode|pymethoddef', 'threadsafe|fortranname|callstatement|callprotoargument|usercode|pymethoddef', '.*'), re.I|re.S), 'f2pyenhancements'
Chris@87 535 multilinepattern = re.compile(r"\s*(?P<before>''')(?P<this>.*?)(?P<after>''')\s*\Z", re.S), 'multiline'
Chris@87 536 ##
Chris@87 537
Chris@87 538 def _simplifyargs(argsline):
Chris@87 539 a = []
Chris@87 540 for n in markoutercomma(argsline).split('@,@'):
Chris@87 541 for r in '(),':
Chris@87 542 n = n.replace(r, '_')
Chris@87 543 a.append(n)
Chris@87 544 return ','.join(a)
Chris@87 545
Chris@87 546 crackline_re_1 = re.compile(r'\s*(?P<result>\b[a-z]+[\w]*\b)\s*[=].*', re.I)
Chris@87 547 def crackline(line,reset=0):
Chris@87 548 """
Chris@87 549 reset=-1 --- initialize
Chris@87 550 reset=0 --- crack the line
Chris@87 551 reset=1 --- final check if mismatch of blocks occured
Chris@87 552
Chris@87 553 Cracked data is saved in grouplist[0].
Chris@87 554 """
Chris@87 555 global beginpattern, groupcounter, groupname, groupcache, grouplist, gotnextfile,\
Chris@87 556 filepositiontext, currentfilename, neededmodule, expectbegin, skipblocksuntil,\
Chris@87 557 skipemptyends, previous_context
Chris@87 558 if ';' in line and not (f2pyenhancementspattern[0].match(line) or
Chris@87 559 multilinepattern[0].match(line)):
Chris@87 560 for l in line.split(';'):
Chris@87 561 assert reset==0, repr(reset) # XXX: non-zero reset values need testing
Chris@87 562 crackline(l, reset)
Chris@87 563 return
Chris@87 564 if reset<0:
Chris@87 565 groupcounter=0
Chris@87 566 groupname={groupcounter:''}
Chris@87 567 groupcache={groupcounter:{}}
Chris@87 568 grouplist={groupcounter:[]}
Chris@87 569 groupcache[groupcounter]['body']=[]
Chris@87 570 groupcache[groupcounter]['vars']={}
Chris@87 571 groupcache[groupcounter]['block']=''
Chris@87 572 groupcache[groupcounter]['name']=''
Chris@87 573 neededmodule=-1
Chris@87 574 skipblocksuntil=-1
Chris@87 575 return
Chris@87 576 if reset>0:
Chris@87 577 fl=0
Chris@87 578 if f77modulename and neededmodule==groupcounter: fl=2
Chris@87 579 while groupcounter>fl:
Chris@87 580 outmess('crackline: groupcounter=%s groupname=%s\n'%(repr(groupcounter), repr(groupname)))
Chris@87 581 outmess('crackline: Mismatch of blocks encountered. Trying to fix it by assuming "end" statement.\n')
Chris@87 582 grouplist[groupcounter-1].append(groupcache[groupcounter])
Chris@87 583 grouplist[groupcounter-1][-1]['body']=grouplist[groupcounter]
Chris@87 584 del grouplist[groupcounter]
Chris@87 585 groupcounter=groupcounter-1
Chris@87 586 if f77modulename and neededmodule==groupcounter:
Chris@87 587 grouplist[groupcounter-1].append(groupcache[groupcounter])
Chris@87 588 grouplist[groupcounter-1][-1]['body']=grouplist[groupcounter]
Chris@87 589 del grouplist[groupcounter]
Chris@87 590 groupcounter=groupcounter-1 # end interface
Chris@87 591 grouplist[groupcounter-1].append(groupcache[groupcounter])
Chris@87 592 grouplist[groupcounter-1][-1]['body']=grouplist[groupcounter]
Chris@87 593 del grouplist[groupcounter]
Chris@87 594 groupcounter=groupcounter-1 # end module
Chris@87 595 neededmodule=-1
Chris@87 596 return
Chris@87 597 if line=='': return
Chris@87 598 flag=0
Chris@87 599 for pat in [dimensionpattern, externalpattern, intentpattern, optionalpattern,
Chris@87 600 requiredpattern,
Chris@87 601 parameterpattern, datapattern, publicpattern, privatepattern,
Chris@87 602 intrisicpattern,
Chris@87 603 endifpattern, endpattern,
Chris@87 604 formatpattern,
Chris@87 605 beginpattern, functionpattern, subroutinepattern,
Chris@87 606 implicitpattern, typespattern, commonpattern,
Chris@87 607 callpattern, usepattern, containspattern,
Chris@87 608 entrypattern,
Chris@87 609 f2pyenhancementspattern,
Chris@87 610 multilinepattern
Chris@87 611 ]:
Chris@87 612 m = pat[0].match(line)
Chris@87 613 if m:
Chris@87 614 break
Chris@87 615 flag=flag+1
Chris@87 616 if not m:
Chris@87 617 re_1 = crackline_re_1
Chris@87 618 if 0<=skipblocksuntil<=groupcounter:return
Chris@87 619 if 'externals' in groupcache[groupcounter]:
Chris@87 620 for name in groupcache[groupcounter]['externals']:
Chris@87 621 if name in invbadnames:
Chris@87 622 name=invbadnames[name]
Chris@87 623 if 'interfaced' in groupcache[groupcounter] and name in groupcache[groupcounter]['interfaced']:
Chris@87 624 continue
Chris@87 625 m1=re.match(r'(?P<before>[^"]*)\b%s\b\s*@\(@(?P<args>[^@]*)@\)@.*\Z'%name, markouterparen(line), re.I)
Chris@87 626 if m1:
Chris@87 627 m2 = re_1.match(m1.group('before'))
Chris@87 628 a = _simplifyargs(m1.group('args'))
Chris@87 629 if m2:
Chris@87 630 line='callfun %s(%s) result (%s)'%(name, a, m2.group('result'))
Chris@87 631 else: line='callfun %s(%s)'%(name, a)
Chris@87 632 m = callfunpattern[0].match(line)
Chris@87 633 if not m:
Chris@87 634 outmess('crackline: could not resolve function call for line=%s.\n'%repr(line))
Chris@87 635 return
Chris@87 636 analyzeline(m, 'callfun', line)
Chris@87 637 return
Chris@87 638 if verbose>1 or (verbose==1 and currentfilename.lower().endswith('.pyf')):
Chris@87 639 previous_context = None
Chris@87 640 outmess('crackline:%d: No pattern for line\n'%(groupcounter))
Chris@87 641 return
Chris@87 642 elif pat[1]=='end':
Chris@87 643 if 0<=skipblocksuntil<groupcounter:
Chris@87 644 groupcounter=groupcounter-1
Chris@87 645 if skipblocksuntil<=groupcounter: return
Chris@87 646 if groupcounter<=0:
Chris@87 647 raise Exception('crackline: groupcounter(=%s) is nonpositive. '
Chris@87 648 'Check the blocks.' \
Chris@87 649 % (groupcounter))
Chris@87 650 m1 = beginpattern[0].match((line))
Chris@87 651 if (m1) and (not m1.group('this')==groupname[groupcounter]):
Chris@87 652 raise Exception('crackline: End group %s does not match with '
Chris@87 653 'previous Begin group %s\n\t%s' % \
Chris@87 654 (repr(m1.group('this')), repr(groupname[groupcounter]),
Chris@87 655 filepositiontext)
Chris@87 656 )
Chris@87 657 if skipblocksuntil==groupcounter:
Chris@87 658 skipblocksuntil=-1
Chris@87 659 grouplist[groupcounter-1].append(groupcache[groupcounter])
Chris@87 660 grouplist[groupcounter-1][-1]['body']=grouplist[groupcounter]
Chris@87 661 del grouplist[groupcounter]
Chris@87 662 groupcounter=groupcounter-1
Chris@87 663 if not skipemptyends:
Chris@87 664 expectbegin=1
Chris@87 665 elif pat[1] == 'begin':
Chris@87 666 if 0<=skipblocksuntil<=groupcounter:
Chris@87 667 groupcounter=groupcounter+1
Chris@87 668 return
Chris@87 669 gotnextfile=0
Chris@87 670 analyzeline(m, pat[1], line)
Chris@87 671 expectbegin=0
Chris@87 672 elif pat[1]=='endif':
Chris@87 673 pass
Chris@87 674 elif pat[1]=='contains':
Chris@87 675 if ignorecontains: return
Chris@87 676 if 0<=skipblocksuntil<=groupcounter: return
Chris@87 677 skipblocksuntil=groupcounter
Chris@87 678 else:
Chris@87 679 if 0<=skipblocksuntil<=groupcounter:return
Chris@87 680 analyzeline(m, pat[1], line)
Chris@87 681
Chris@87 682 def markouterparen(line):
Chris@87 683 l='';f=0
Chris@87 684 for c in line:
Chris@87 685 if c=='(':
Chris@87 686 f=f+1
Chris@87 687 if f==1: l=l+'@(@'; continue
Chris@87 688 elif c==')':
Chris@87 689 f=f-1
Chris@87 690 if f==0: l=l+'@)@'; continue
Chris@87 691 l=l+c
Chris@87 692 return l
Chris@87 693 def markoutercomma(line,comma=','):
Chris@87 694 l='';f=0
Chris@87 695 cc=''
Chris@87 696 for c in line:
Chris@87 697 if (not cc or cc==')') and c=='(':
Chris@87 698 f=f+1
Chris@87 699 cc = ')'
Chris@87 700 elif not cc and c=='\'' and (not l or l[-1]!='\\'):
Chris@87 701 f=f+1
Chris@87 702 cc = '\''
Chris@87 703 elif c==cc:
Chris@87 704 f=f-1
Chris@87 705 if f==0:
Chris@87 706 cc=''
Chris@87 707 elif c==comma and f==0:
Chris@87 708 l=l+'@'+comma+'@'
Chris@87 709 continue
Chris@87 710 l=l+c
Chris@87 711 assert not f, repr((f, line, l, cc))
Chris@87 712 return l
Chris@87 713 def unmarkouterparen(line):
Chris@87 714 r = line.replace('@(@', '(').replace('@)@', ')')
Chris@87 715 return r
Chris@87 716 def appenddecl(decl,decl2,force=1):
Chris@87 717 if not decl: decl={}
Chris@87 718 if not decl2: return decl
Chris@87 719 if decl is decl2: return decl
Chris@87 720 for k in list(decl2.keys()):
Chris@87 721 if k=='typespec':
Chris@87 722 if force or k not in decl:
Chris@87 723 decl[k]=decl2[k]
Chris@87 724 elif k=='attrspec':
Chris@87 725 for l in decl2[k]:
Chris@87 726 decl=setattrspec(decl, l, force)
Chris@87 727 elif k=='kindselector':
Chris@87 728 decl=setkindselector(decl, decl2[k], force)
Chris@87 729 elif k=='charselector':
Chris@87 730 decl=setcharselector(decl, decl2[k], force)
Chris@87 731 elif k in ['=', 'typename']:
Chris@87 732 if force or k not in decl:
Chris@87 733 decl[k]=decl2[k]
Chris@87 734 elif k=='note':
Chris@87 735 pass
Chris@87 736 elif k in ['intent', 'check', 'dimension', 'optional', 'required']:
Chris@87 737 errmess('appenddecl: "%s" not implemented.\n'%k)
Chris@87 738 else:
Chris@87 739 raise Exception('appenddecl: Unknown variable definition key:' + \
Chris@87 740 str(k))
Chris@87 741 return decl
Chris@87 742
Chris@87 743 selectpattern=re.compile(r'\s*(?P<this>(@\(@.*?@\)@|[*][\d*]+|[*]\s*@\(@.*?@\)@|))(?P<after>.*)\Z', re.I)
Chris@87 744 nameargspattern=re.compile(r'\s*(?P<name>\b[\w$]+\b)\s*(@\(@\s*(?P<args>[\w\s,]*)\s*@\)@|)\s*((result(\s*@\(@\s*(?P<result>\b[\w$]+\b)\s*@\)@|))|(bind\s*@\(@\s*(?P<bind>.*)\s*@\)@))*\s*\Z', re.I)
Chris@87 745 callnameargspattern=re.compile(r'\s*(?P<name>\b[\w$]+\b)\s*@\(@\s*(?P<args>.*)\s*@\)@\s*\Z', re.I)
Chris@87 746 real16pattern = re.compile(r'([-+]?(?:\d+(?:\.\d*)?|\d*\.\d+))[dD]((?:[-+]?\d+)?)')
Chris@87 747 real8pattern = re.compile(r'([-+]?((?:\d+(?:\.\d*)?|\d*\.\d+))[eE]((?:[-+]?\d+)?)|(\d+\.\d*))')
Chris@87 748
Chris@87 749 _intentcallbackpattern = re.compile(r'intent\s*\(.*?\bcallback\b', re.I)
Chris@87 750 def _is_intent_callback(vdecl):
Chris@87 751 for a in vdecl.get('attrspec', []):
Chris@87 752 if _intentcallbackpattern.match(a):
Chris@87 753 return 1
Chris@87 754 return 0
Chris@87 755
Chris@87 756 def _resolvenameargspattern(line):
Chris@87 757 line = markouterparen(line)
Chris@87 758 m1=nameargspattern.match(line)
Chris@87 759 if m1:
Chris@87 760 return m1.group('name'), m1.group('args'), m1.group('result'), m1.group('bind')
Chris@87 761 m1=callnameargspattern.match(line)
Chris@87 762 if m1:
Chris@87 763 return m1.group('name'), m1.group('args'), None, None
Chris@87 764 return None, [], None, None
Chris@87 765
Chris@87 766 def analyzeline(m, case, line):
Chris@87 767 global groupcounter, groupname, groupcache, grouplist, filepositiontext,\
Chris@87 768 currentfilename, f77modulename, neededinterface, neededmodule, expectbegin,\
Chris@87 769 gotnextfile, previous_context
Chris@87 770 block=m.group('this')
Chris@87 771 if case != 'multiline':
Chris@87 772 previous_context = None
Chris@87 773 if expectbegin and case not in ['begin', 'call', 'callfun', 'type'] \
Chris@87 774 and not skipemptyends and groupcounter<1:
Chris@87 775 newname=os.path.basename(currentfilename).split('.')[0]
Chris@87 776 outmess('analyzeline: no group yet. Creating program group with name "%s".\n'%newname)
Chris@87 777 gotnextfile=0
Chris@87 778 groupcounter=groupcounter+1
Chris@87 779 groupname[groupcounter]='program'
Chris@87 780 groupcache[groupcounter]={}
Chris@87 781 grouplist[groupcounter]=[]
Chris@87 782 groupcache[groupcounter]['body']=[]
Chris@87 783 groupcache[groupcounter]['vars']={}
Chris@87 784 groupcache[groupcounter]['block']='program'
Chris@87 785 groupcache[groupcounter]['name']=newname
Chris@87 786 groupcache[groupcounter]['from']='fromsky'
Chris@87 787 expectbegin=0
Chris@87 788 if case in ['begin', 'call', 'callfun']:
Chris@87 789 # Crack line => block,name,args,result
Chris@87 790 block = block.lower()
Chris@87 791 if re.match(r'block\s*data', block, re.I): block='block data'
Chris@87 792 if re.match(r'python\s*module', block, re.I): block='python module'
Chris@87 793 name, args, result, bind = _resolvenameargspattern(m.group('after'))
Chris@87 794 if name is None:
Chris@87 795 if block=='block data':
Chris@87 796 name = '_BLOCK_DATA_'
Chris@87 797 else:
Chris@87 798 name = ''
Chris@87 799 if block not in ['interface', 'block data']:
Chris@87 800 outmess('analyzeline: No name/args pattern found for line.\n')
Chris@87 801
Chris@87 802 previous_context = (block, name, groupcounter)
Chris@87 803 if args: args=rmbadname([x.strip() for x in markoutercomma(args).split('@,@')])
Chris@87 804 else: args=[]
Chris@87 805 if '' in args:
Chris@87 806 while '' in args:
Chris@87 807 args.remove('')
Chris@87 808 outmess('analyzeline: argument list is malformed (missing argument).\n')
Chris@87 809
Chris@87 810 # end of crack line => block,name,args,result
Chris@87 811 needmodule=0
Chris@87 812 needinterface=0
Chris@87 813
Chris@87 814 if case in ['call', 'callfun']:
Chris@87 815 needinterface=1
Chris@87 816 if 'args' not in groupcache[groupcounter]:
Chris@87 817 return
Chris@87 818 if name not in groupcache[groupcounter]['args']:
Chris@87 819 return
Chris@87 820 for it in grouplist[groupcounter]:
Chris@87 821 if it['name']==name:
Chris@87 822 return
Chris@87 823 if name in groupcache[groupcounter]['interfaced']:
Chris@87 824 return
Chris@87 825 block={'call':'subroutine','callfun':'function'}[case]
Chris@87 826 if f77modulename and neededmodule==-1 and groupcounter<=1:
Chris@87 827 neededmodule=groupcounter+2
Chris@87 828 needmodule=1
Chris@87 829 if block != 'interface':
Chris@87 830 needinterface=1
Chris@87 831 # Create new block(s)
Chris@87 832 groupcounter=groupcounter+1
Chris@87 833 groupcache[groupcounter]={}
Chris@87 834 grouplist[groupcounter]=[]
Chris@87 835 if needmodule:
Chris@87 836 if verbose>1:
Chris@87 837 outmess('analyzeline: Creating module block %s\n'%repr(f77modulename), 0)
Chris@87 838 groupname[groupcounter]='module'
Chris@87 839 groupcache[groupcounter]['block']='python module'
Chris@87 840 groupcache[groupcounter]['name']=f77modulename
Chris@87 841 groupcache[groupcounter]['from']=''
Chris@87 842 groupcache[groupcounter]['body']=[]
Chris@87 843 groupcache[groupcounter]['externals']=[]
Chris@87 844 groupcache[groupcounter]['interfaced']=[]
Chris@87 845 groupcache[groupcounter]['vars']={}
Chris@87 846 groupcounter=groupcounter+1
Chris@87 847 groupcache[groupcounter]={}
Chris@87 848 grouplist[groupcounter]=[]
Chris@87 849 if needinterface:
Chris@87 850 if verbose>1:
Chris@87 851 outmess('analyzeline: Creating additional interface block (groupcounter=%s).\n' % (groupcounter), 0)
Chris@87 852 groupname[groupcounter]='interface'
Chris@87 853 groupcache[groupcounter]['block']='interface'
Chris@87 854 groupcache[groupcounter]['name']='unknown_interface'
Chris@87 855 groupcache[groupcounter]['from']='%s:%s'%(groupcache[groupcounter-1]['from'], groupcache[groupcounter-1]['name'])
Chris@87 856 groupcache[groupcounter]['body']=[]
Chris@87 857 groupcache[groupcounter]['externals']=[]
Chris@87 858 groupcache[groupcounter]['interfaced']=[]
Chris@87 859 groupcache[groupcounter]['vars']={}
Chris@87 860 groupcounter=groupcounter+1
Chris@87 861 groupcache[groupcounter]={}
Chris@87 862 grouplist[groupcounter]=[]
Chris@87 863 groupname[groupcounter]=block
Chris@87 864 groupcache[groupcounter]['block']=block
Chris@87 865 if not name: name='unknown_'+block
Chris@87 866 groupcache[groupcounter]['prefix']=m.group('before')
Chris@87 867 groupcache[groupcounter]['name']=rmbadname1(name)
Chris@87 868 groupcache[groupcounter]['result']=result
Chris@87 869 if groupcounter==1:
Chris@87 870 groupcache[groupcounter]['from']=currentfilename
Chris@87 871 else:
Chris@87 872 if f77modulename and groupcounter==3:
Chris@87 873 groupcache[groupcounter]['from']='%s:%s'%(groupcache[groupcounter-1]['from'], currentfilename)
Chris@87 874 else:
Chris@87 875 groupcache[groupcounter]['from']='%s:%s'%(groupcache[groupcounter-1]['from'], groupcache[groupcounter-1]['name'])
Chris@87 876 for k in list(groupcache[groupcounter].keys()):
Chris@87 877 if not groupcache[groupcounter][k]:
Chris@87 878 del groupcache[groupcounter][k]
Chris@87 879
Chris@87 880 groupcache[groupcounter]['args']=args
Chris@87 881 groupcache[groupcounter]['body']=[]
Chris@87 882 groupcache[groupcounter]['externals']=[]
Chris@87 883 groupcache[groupcounter]['interfaced']=[]
Chris@87 884 groupcache[groupcounter]['vars']={}
Chris@87 885 groupcache[groupcounter]['entry']={}
Chris@87 886 # end of creation
Chris@87 887 if block=='type':
Chris@87 888 groupcache[groupcounter]['varnames'] = []
Chris@87 889
Chris@87 890 if case in ['call', 'callfun']: # set parents variables
Chris@87 891 if name not in groupcache[groupcounter-2]['externals']:
Chris@87 892 groupcache[groupcounter-2]['externals'].append(name)
Chris@87 893 groupcache[groupcounter]['vars']=copy.deepcopy(groupcache[groupcounter-2]['vars'])
Chris@87 894 #try: del groupcache[groupcounter]['vars'][groupcache[groupcounter-2]['name']]
Chris@87 895 #except: pass
Chris@87 896 try: del groupcache[groupcounter]['vars'][name][groupcache[groupcounter]['vars'][name]['attrspec'].index('external')]
Chris@87 897 except: pass
Chris@87 898 if block in ['function', 'subroutine']: # set global attributes
Chris@87 899 try: groupcache[groupcounter]['vars'][name]=appenddecl(groupcache[groupcounter]['vars'][name], groupcache[groupcounter-2]['vars'][''])
Chris@87 900 except: pass
Chris@87 901 if case=='callfun': # return type
Chris@87 902 if result and result in groupcache[groupcounter]['vars']:
Chris@87 903 if not name==result:
Chris@87 904 groupcache[groupcounter]['vars'][name]=appenddecl(groupcache[groupcounter]['vars'][name], groupcache[groupcounter]['vars'][result])
Chris@87 905 #if groupcounter>1: # name is interfaced
Chris@87 906 try: groupcache[groupcounter-2]['interfaced'].append(name)
Chris@87 907 except: pass
Chris@87 908 if block=='function':
Chris@87 909 t=typespattern[0].match(m.group('before')+' '+name)
Chris@87 910 if t:
Chris@87 911 typespec, selector, attr, edecl=cracktypespec0(t.group('this'), t.group('after'))
Chris@87 912 updatevars(typespec, selector, attr, edecl)
Chris@87 913
Chris@87 914 if case in ['call', 'callfun']:
Chris@87 915 grouplist[groupcounter-1].append(groupcache[groupcounter])
Chris@87 916 grouplist[groupcounter-1][-1]['body']=grouplist[groupcounter]
Chris@87 917 del grouplist[groupcounter]
Chris@87 918 groupcounter=groupcounter-1 # end routine
Chris@87 919 grouplist[groupcounter-1].append(groupcache[groupcounter])
Chris@87 920 grouplist[groupcounter-1][-1]['body']=grouplist[groupcounter]
Chris@87 921 del grouplist[groupcounter]
Chris@87 922 groupcounter=groupcounter-1 # end interface
Chris@87 923
Chris@87 924 elif case=='entry':
Chris@87 925 name, args, result, bind=_resolvenameargspattern(m.group('after'))
Chris@87 926 if name is not None:
Chris@87 927 if args:
Chris@87 928 args=rmbadname([x.strip() for x in markoutercomma(args).split('@,@')])
Chris@87 929 else: args=[]
Chris@87 930 assert result is None, repr(result)
Chris@87 931 groupcache[groupcounter]['entry'][name] = args
Chris@87 932 previous_context = ('entry', name, groupcounter)
Chris@87 933 elif case=='type':
Chris@87 934 typespec, selector, attr, edecl=cracktypespec0(block, m.group('after'))
Chris@87 935 last_name = updatevars(typespec, selector, attr, edecl)
Chris@87 936 if last_name is not None:
Chris@87 937 previous_context = ('variable', last_name, groupcounter)
Chris@87 938 elif case in ['dimension', 'intent', 'optional', 'required', 'external', 'public', 'private', 'intrisic']:
Chris@87 939 edecl=groupcache[groupcounter]['vars']
Chris@87 940 ll=m.group('after').strip()
Chris@87 941 i=ll.find('::')
Chris@87 942 if i<0 and case=='intent':
Chris@87 943 i=markouterparen(ll).find('@)@')-2
Chris@87 944 ll=ll[:i+1]+'::'+ll[i+1:]
Chris@87 945 i=ll.find('::')
Chris@87 946 if ll[i:]=='::' and 'args' in groupcache[groupcounter]:
Chris@87 947 outmess('All arguments will have attribute %s%s\n'%(m.group('this'), ll[:i]))
Chris@87 948 ll = ll + ','.join(groupcache[groupcounter]['args'])
Chris@87 949 if i<0:i=0;pl=''
Chris@87 950 else: pl=ll[:i].strip();ll=ll[i+2:]
Chris@87 951 ch = markoutercomma(pl).split('@,@')
Chris@87 952 if len(ch)>1:
Chris@87 953 pl = ch[0]
Chris@87 954 outmess('analyzeline: cannot handle multiple attributes without type specification. Ignoring %r.\n' % (','.join(ch[1:])))
Chris@87 955 last_name = None
Chris@87 956
Chris@87 957 for e in [x.strip() for x in markoutercomma(ll).split('@,@')]:
Chris@87 958 m1=namepattern.match(e)
Chris@87 959 if not m1:
Chris@87 960 if case in ['public', 'private']: k=''
Chris@87 961 else:
Chris@87 962 print(m.groupdict())
Chris@87 963 outmess('analyzeline: no name pattern found in %s statement for %s. Skipping.\n'%(case, repr(e)))
Chris@87 964 continue
Chris@87 965 else:
Chris@87 966 k=rmbadname1(m1.group('name'))
Chris@87 967 if k not in edecl:
Chris@87 968 edecl[k]={}
Chris@87 969 if case=='dimension':
Chris@87 970 ap=case+m1.group('after')
Chris@87 971 if case=='intent':
Chris@87 972 ap=m.group('this')+pl
Chris@87 973 if _intentcallbackpattern.match(ap):
Chris@87 974 if k not in groupcache[groupcounter]['args']:
Chris@87 975 if groupcounter>1:
Chris@87 976 if '__user__' not in groupcache[groupcounter-2]['name']:
Chris@87 977 outmess('analyzeline: missing __user__ module (could be nothing)\n')
Chris@87 978 if k!=groupcache[groupcounter]['name']: # fixes ticket 1693
Chris@87 979 outmess('analyzeline: appending intent(callback) %s'\
Chris@87 980 ' to %s arguments\n' % (k, groupcache[groupcounter]['name']))
Chris@87 981 groupcache[groupcounter]['args'].append(k)
Chris@87 982 else:
Chris@87 983 errmess('analyzeline: intent(callback) %s is ignored' % (k))
Chris@87 984 else:
Chris@87 985 errmess('analyzeline: intent(callback) %s is already'\
Chris@87 986 ' in argument list' % (k))
Chris@87 987 if case in ['optional', 'required', 'public', 'external', 'private', 'intrisic']:
Chris@87 988 ap=case
Chris@87 989 if 'attrspec' in edecl[k]:
Chris@87 990 edecl[k]['attrspec'].append(ap)
Chris@87 991 else:
Chris@87 992 edecl[k]['attrspec']=[ap]
Chris@87 993 if case=='external':
Chris@87 994 if groupcache[groupcounter]['block']=='program':
Chris@87 995 outmess('analyzeline: ignoring program arguments\n')
Chris@87 996 continue
Chris@87 997 if k not in groupcache[groupcounter]['args']:
Chris@87 998 #outmess('analyzeline: ignoring external %s (not in arguments list)\n'%(`k`))
Chris@87 999 continue
Chris@87 1000 if 'externals' not in groupcache[groupcounter]:
Chris@87 1001 groupcache[groupcounter]['externals']=[]
Chris@87 1002 groupcache[groupcounter]['externals'].append(k)
Chris@87 1003 last_name = k
Chris@87 1004 groupcache[groupcounter]['vars']=edecl
Chris@87 1005 if last_name is not None:
Chris@87 1006 previous_context = ('variable', last_name, groupcounter)
Chris@87 1007 elif case=='parameter':
Chris@87 1008 edecl=groupcache[groupcounter]['vars']
Chris@87 1009 ll=m.group('after').strip()[1:-1]
Chris@87 1010 last_name = None
Chris@87 1011 for e in markoutercomma(ll).split('@,@'):
Chris@87 1012 try:
Chris@87 1013 k, initexpr=[x.strip() for x in e.split('=')]
Chris@87 1014 except:
Chris@87 1015 outmess('analyzeline: could not extract name,expr in parameter statement "%s" of "%s"\n'%(e, ll));continue
Chris@87 1016 params = get_parameters(edecl)
Chris@87 1017 k=rmbadname1(k)
Chris@87 1018 if k not in edecl:
Chris@87 1019 edecl[k]={}
Chris@87 1020 if '=' in edecl[k] and (not edecl[k]['=']==initexpr):
Chris@87 1021 outmess('analyzeline: Overwriting the value of parameter "%s" ("%s") with "%s".\n'%(k, edecl[k]['='], initexpr))
Chris@87 1022 t = determineexprtype(initexpr, params)
Chris@87 1023 if t:
Chris@87 1024 if t.get('typespec')=='real':
Chris@87 1025 tt = list(initexpr)
Chris@87 1026 for m in real16pattern.finditer(initexpr):
Chris@87 1027 tt[m.start():m.end()] = list(\
Chris@87 1028 initexpr[m.start():m.end()].lower().replace('d', 'e'))
Chris@87 1029 initexpr = ''.join(tt)
Chris@87 1030 elif t.get('typespec')=='complex':
Chris@87 1031 initexpr = initexpr[1:].lower().replace('d', 'e').\
Chris@87 1032 replace(',', '+1j*(')
Chris@87 1033 try:
Chris@87 1034 v = eval(initexpr, {}, params)
Chris@87 1035 except (SyntaxError, NameError, TypeError) as msg:
Chris@87 1036 errmess('analyzeline: Failed to evaluate %r. Ignoring: %s\n'\
Chris@87 1037 % (initexpr, msg))
Chris@87 1038 continue
Chris@87 1039 edecl[k]['='] = repr(v)
Chris@87 1040 if 'attrspec' in edecl[k]:
Chris@87 1041 edecl[k]['attrspec'].append('parameter')
Chris@87 1042 else: edecl[k]['attrspec']=['parameter']
Chris@87 1043 last_name = k
Chris@87 1044 groupcache[groupcounter]['vars']=edecl
Chris@87 1045 if last_name is not None:
Chris@87 1046 previous_context = ('variable', last_name, groupcounter)
Chris@87 1047 elif case=='implicit':
Chris@87 1048 if m.group('after').strip().lower()=='none':
Chris@87 1049 groupcache[groupcounter]['implicit']=None
Chris@87 1050 elif m.group('after'):
Chris@87 1051 if 'implicit' in groupcache[groupcounter]:
Chris@87 1052 impl=groupcache[groupcounter]['implicit']
Chris@87 1053 else: impl={}
Chris@87 1054 if impl is None:
Chris@87 1055 outmess('analyzeline: Overwriting earlier "implicit none" statement.\n')
Chris@87 1056 impl={}
Chris@87 1057 for e in markoutercomma(m.group('after')).split('@,@'):
Chris@87 1058 decl={}
Chris@87 1059 m1=re.match(r'\s*(?P<this>.*?)\s*(\(\s*(?P<after>[a-z-, ]+)\s*\)\s*|)\Z', e, re.I)
Chris@87 1060 if not m1:
Chris@87 1061 outmess('analyzeline: could not extract info of implicit statement part "%s"\n'%(e));continue
Chris@87 1062 m2=typespattern4implicit.match(m1.group('this'))
Chris@87 1063 if not m2:
Chris@87 1064 outmess('analyzeline: could not extract types pattern of implicit statement part "%s"\n'%(e));continue
Chris@87 1065 typespec, selector, attr, edecl=cracktypespec0(m2.group('this'), m2.group('after'))
Chris@87 1066 kindselect, charselect, typename=cracktypespec(typespec, selector)
Chris@87 1067 decl['typespec']=typespec
Chris@87 1068 decl['kindselector']=kindselect
Chris@87 1069 decl['charselector']=charselect
Chris@87 1070 decl['typename']=typename
Chris@87 1071 for k in list(decl.keys()):
Chris@87 1072 if not decl[k]: del decl[k]
Chris@87 1073 for r in markoutercomma(m1.group('after')).split('@,@'):
Chris@87 1074 if '-' in r:
Chris@87 1075 try: begc, endc=[x.strip() for x in r.split('-')]
Chris@87 1076 except:
Chris@87 1077 outmess('analyzeline: expected "<char>-<char>" instead of "%s" in range list of implicit statement\n'%r);continue
Chris@87 1078 else: begc=endc=r.strip()
Chris@87 1079 if not len(begc)==len(endc)==1:
Chris@87 1080 outmess('analyzeline: expected "<char>-<char>" instead of "%s" in range list of implicit statement (2)\n'%r);continue
Chris@87 1081 for o in range(ord(begc), ord(endc)+1):
Chris@87 1082 impl[chr(o)]=decl
Chris@87 1083 groupcache[groupcounter]['implicit']=impl
Chris@87 1084 elif case=='data':
Chris@87 1085 ll=[]
Chris@87 1086 dl='';il='';f=0;fc=1;inp=0
Chris@87 1087 for c in m.group('after'):
Chris@87 1088 if not inp:
Chris@87 1089 if c=="'": fc=not fc
Chris@87 1090 if c=='/' and fc: f=f+1;continue
Chris@87 1091 if c=='(': inp = inp + 1
Chris@87 1092 elif c==')': inp = inp - 1
Chris@87 1093 if f==0: dl=dl+c
Chris@87 1094 elif f==1: il=il+c
Chris@87 1095 elif f==2:
Chris@87 1096 dl = dl.strip()
Chris@87 1097 if dl.startswith(','):
Chris@87 1098 dl = dl[1:].strip()
Chris@87 1099 ll.append([dl, il])
Chris@87 1100 dl=c;il='';f=0
Chris@87 1101 if f==2:
Chris@87 1102 dl = dl.strip()
Chris@87 1103 if dl.startswith(','):
Chris@87 1104 dl = dl[1:].strip()
Chris@87 1105 ll.append([dl, il])
Chris@87 1106 vars={}
Chris@87 1107 if 'vars' in groupcache[groupcounter]:
Chris@87 1108 vars=groupcache[groupcounter]['vars']
Chris@87 1109 last_name = None
Chris@87 1110 for l in ll:
Chris@87 1111 l=[x.strip() for x in l]
Chris@87 1112 if l[0][0]==',':l[0]=l[0][1:]
Chris@87 1113 if l[0][0]=='(':
Chris@87 1114 outmess('analyzeline: implied-DO list "%s" is not supported. Skipping.\n'%l[0])
Chris@87 1115 continue
Chris@87 1116 #if '(' in l[0]:
Chris@87 1117 # #outmess('analyzeline: ignoring this data statement.\n')
Chris@87 1118 # continue
Chris@87 1119 i=0;j=0;llen=len(l[1])
Chris@87 1120 for v in rmbadname([x.strip() for x in markoutercomma(l[0]).split('@,@')]):
Chris@87 1121 if v[0]=='(':
Chris@87 1122 outmess('analyzeline: implied-DO list "%s" is not supported. Skipping.\n'%v)
Chris@87 1123 # XXX: subsequent init expressions may get wrong values.
Chris@87 1124 # Ignoring since data statements are irrelevant for wrapping.
Chris@87 1125 continue
Chris@87 1126 fc=0
Chris@87 1127 while (i<llen) and (fc or not l[1][i]==','):
Chris@87 1128 if l[1][i]=="'": fc=not fc
Chris@87 1129 i=i+1
Chris@87 1130 i=i+1
Chris@87 1131 #v,l[1][j:i-1]=name,initvalue
Chris@87 1132 if v not in vars:
Chris@87 1133 vars[v]={}
Chris@87 1134 if '=' in vars[v] and not vars[v]['=']==l[1][j:i-1]:
Chris@87 1135 outmess('analyzeline: changing init expression of "%s" ("%s") to "%s"\n'%(v, vars[v]['='], l[1][j:i-1]))
Chris@87 1136 vars[v]['=']=l[1][j:i-1]
Chris@87 1137 j=i
Chris@87 1138 last_name = v
Chris@87 1139 groupcache[groupcounter]['vars']=vars
Chris@87 1140 if last_name is not None:
Chris@87 1141 previous_context = ('variable', last_name, groupcounter)
Chris@87 1142 elif case=='common':
Chris@87 1143 line=m.group('after').strip()
Chris@87 1144 if not line[0]=='/':line='//'+line
Chris@87 1145 cl=[]
Chris@87 1146 f=0;bn='';ol=''
Chris@87 1147 for c in line:
Chris@87 1148 if c=='/':f=f+1;continue
Chris@87 1149 if f>=3:
Chris@87 1150 bn = bn.strip()
Chris@87 1151 if not bn: bn='_BLNK_'
Chris@87 1152 cl.append([bn, ol])
Chris@87 1153 f=f-2;bn='';ol=''
Chris@87 1154 if f%2: bn=bn+c
Chris@87 1155 else: ol=ol+c
Chris@87 1156 bn = bn.strip()
Chris@87 1157 if not bn: bn='_BLNK_'
Chris@87 1158 cl.append([bn, ol])
Chris@87 1159 commonkey={}
Chris@87 1160 if 'common' in groupcache[groupcounter]:
Chris@87 1161 commonkey=groupcache[groupcounter]['common']
Chris@87 1162 for c in cl:
Chris@87 1163 if c[0] in commonkey:
Chris@87 1164 outmess('analyzeline: previously defined common block encountered. Skipping.\n')
Chris@87 1165 continue
Chris@87 1166 commonkey[c[0]]=[]
Chris@87 1167 for i in [x.strip() for x in markoutercomma(c[1]).split('@,@')]:
Chris@87 1168 if i: commonkey[c[0]].append(i)
Chris@87 1169 groupcache[groupcounter]['common']=commonkey
Chris@87 1170 previous_context = ('common', bn, groupcounter)
Chris@87 1171 elif case=='use':
Chris@87 1172 m1=re.match(r'\A\s*(?P<name>\b[\w]+\b)\s*((,(\s*\bonly\b\s*:|(?P<notonly>))\s*(?P<list>.*))|)\s*\Z', m.group('after'), re.I)
Chris@87 1173 if m1:
Chris@87 1174 mm=m1.groupdict()
Chris@87 1175 if 'use' not in groupcache[groupcounter]:
Chris@87 1176 groupcache[groupcounter]['use']={}
Chris@87 1177 name=m1.group('name')
Chris@87 1178 groupcache[groupcounter]['use'][name]={}
Chris@87 1179 isonly=0
Chris@87 1180 if 'list' in mm and mm['list'] is not None:
Chris@87 1181 if 'notonly' in mm and mm['notonly'] is None:
Chris@87 1182 isonly=1
Chris@87 1183 groupcache[groupcounter]['use'][name]['only']=isonly
Chris@87 1184 ll=[x.strip() for x in mm['list'].split(',')]
Chris@87 1185 rl={}
Chris@87 1186 for l in ll:
Chris@87 1187 if '=' in l:
Chris@87 1188 m2=re.match(r'\A\s*(?P<local>\b[\w]+\b)\s*=\s*>\s*(?P<use>\b[\w]+\b)\s*\Z', l, re.I)
Chris@87 1189 if m2: rl[m2.group('local').strip()]=m2.group('use').strip()
Chris@87 1190 else:
Chris@87 1191 outmess('analyzeline: Not local=>use pattern found in %s\n'%repr(l))
Chris@87 1192 else:
Chris@87 1193 rl[l]=l
Chris@87 1194 groupcache[groupcounter]['use'][name]['map']=rl
Chris@87 1195 else:
Chris@87 1196 pass
Chris@87 1197 else:
Chris@87 1198 print(m.groupdict())
Chris@87 1199 outmess('analyzeline: Could not crack the use statement.\n')
Chris@87 1200 elif case in ['f2pyenhancements']:
Chris@87 1201 if 'f2pyenhancements' not in groupcache[groupcounter]:
Chris@87 1202 groupcache[groupcounter]['f2pyenhancements'] = {}
Chris@87 1203 d = groupcache[groupcounter]['f2pyenhancements']
Chris@87 1204 if m.group('this')=='usercode' and 'usercode' in d:
Chris@87 1205 if isinstance(d['usercode'], str):
Chris@87 1206 d['usercode'] = [d['usercode']]
Chris@87 1207 d['usercode'].append(m.group('after'))
Chris@87 1208 else:
Chris@87 1209 d[m.group('this')] = m.group('after')
Chris@87 1210 elif case=='multiline':
Chris@87 1211 if previous_context is None:
Chris@87 1212 if verbose:
Chris@87 1213 outmess('analyzeline: No context for multiline block.\n')
Chris@87 1214 return
Chris@87 1215 gc = groupcounter
Chris@87 1216 #gc = previous_context[2]
Chris@87 1217 appendmultiline(groupcache[gc],
Chris@87 1218 previous_context[:2],
Chris@87 1219 m.group('this'))
Chris@87 1220 else:
Chris@87 1221 if verbose>1:
Chris@87 1222 print(m.groupdict())
Chris@87 1223 outmess('analyzeline: No code implemented for line.\n')
Chris@87 1224
Chris@87 1225 def appendmultiline(group, context_name, ml):
Chris@87 1226 if 'f2pymultilines' not in group:
Chris@87 1227 group['f2pymultilines'] = {}
Chris@87 1228 d = group['f2pymultilines']
Chris@87 1229 if context_name not in d:
Chris@87 1230 d[context_name] = []
Chris@87 1231 d[context_name].append(ml)
Chris@87 1232 return
Chris@87 1233
Chris@87 1234 def cracktypespec0(typespec, ll):
Chris@87 1235 selector=None
Chris@87 1236 attr=None
Chris@87 1237 if re.match(r'double\s*complex', typespec, re.I): typespec='double complex'
Chris@87 1238 elif re.match(r'double\s*precision', typespec, re.I): typespec='double precision'
Chris@87 1239 else: typespec=typespec.strip().lower()
Chris@87 1240 m1=selectpattern.match(markouterparen(ll))
Chris@87 1241 if not m1:
Chris@87 1242 outmess('cracktypespec0: no kind/char_selector pattern found for line.\n')
Chris@87 1243 return
Chris@87 1244 d=m1.groupdict()
Chris@87 1245 for k in list(d.keys()): d[k]=unmarkouterparen(d[k])
Chris@87 1246 if typespec in ['complex', 'integer', 'logical', 'real', 'character', 'type']:
Chris@87 1247 selector=d['this']
Chris@87 1248 ll=d['after']
Chris@87 1249 i=ll.find('::')
Chris@87 1250 if i>=0:
Chris@87 1251 attr=ll[:i].strip()
Chris@87 1252 ll=ll[i+2:]
Chris@87 1253 return typespec, selector, attr, ll
Chris@87 1254 #####
Chris@87 1255 namepattern=re.compile(r'\s*(?P<name>\b[\w]+\b)\s*(?P<after>.*)\s*\Z', re.I)
Chris@87 1256 kindselector=re.compile(r'\s*(\(\s*(kind\s*=)?\s*(?P<kind>.*)\s*\)|[*]\s*(?P<kind2>.*?))\s*\Z', re.I)
Chris@87 1257 charselector=re.compile(r'\s*(\((?P<lenkind>.*)\)|[*]\s*(?P<charlen>.*))\s*\Z', re.I)
Chris@87 1258 lenkindpattern=re.compile(r'\s*(kind\s*=\s*(?P<kind>.*?)\s*(@,@\s*len\s*=\s*(?P<len>.*)|)|(len\s*=\s*|)(?P<len2>.*?)\s*(@,@\s*(kind\s*=\s*|)(?P<kind2>.*)|))\s*\Z', re.I)
Chris@87 1259 lenarraypattern=re.compile(r'\s*(@\(@\s*(?!/)\s*(?P<array>.*?)\s*@\)@\s*[*]\s*(?P<len>.*?)|([*]\s*(?P<len2>.*?)|)\s*(@\(@\s*(?!/)\s*(?P<array2>.*?)\s*@\)@|))\s*(=\s*(?P<init>.*?)|(@\(@|)/\s*(?P<init2>.*?)\s*/(@\)@|)|)\s*\Z', re.I)
Chris@87 1260 def removespaces(expr):
Chris@87 1261 expr=expr.strip()
Chris@87 1262 if len(expr)<=1: return expr
Chris@87 1263 expr2=expr[0]
Chris@87 1264 for i in range(1, len(expr)-1):
Chris@87 1265 if expr[i]==' ' and \
Chris@87 1266 ((expr[i+1] in "()[]{}=+-/* ") or (expr[i-1] in "()[]{}=+-/* ")): continue
Chris@87 1267 expr2=expr2+expr[i]
Chris@87 1268 expr2=expr2+expr[-1]
Chris@87 1269 return expr2
Chris@87 1270 def markinnerspaces(line):
Chris@87 1271 l='';f=0
Chris@87 1272 cc='\''
Chris@87 1273 cc1='"'
Chris@87 1274 cb=''
Chris@87 1275 for c in line:
Chris@87 1276 if cb=='\\' and c in ['\\', '\'', '"']:
Chris@87 1277 l=l+c
Chris@87 1278 cb=c
Chris@87 1279 continue
Chris@87 1280 if f==0 and c in ['\'', '"']: cc=c; cc1={'\'':'"','"':'\''}[c]
Chris@87 1281 if c==cc:f=f+1
Chris@87 1282 elif c==cc:f=f-1
Chris@87 1283 elif c==' ' and f==1: l=l+'@_@'; continue
Chris@87 1284 l=l+c;cb=c
Chris@87 1285 return l
Chris@87 1286 def updatevars(typespec, selector, attrspec, entitydecl):
Chris@87 1287 global groupcache, groupcounter
Chris@87 1288 last_name = None
Chris@87 1289 kindselect, charselect, typename=cracktypespec(typespec, selector)
Chris@87 1290 if attrspec:
Chris@87 1291 attrspec=[x.strip() for x in markoutercomma(attrspec).split('@,@')]
Chris@87 1292 l = []
Chris@87 1293 c = re.compile(r'(?P<start>[a-zA-Z]+)')
Chris@87 1294 for a in attrspec:
Chris@87 1295 if not a:
Chris@87 1296 continue
Chris@87 1297 m = c.match(a)
Chris@87 1298 if m:
Chris@87 1299 s = m.group('start').lower()
Chris@87 1300 a = s + a[len(s):]
Chris@87 1301 l.append(a)
Chris@87 1302 attrspec = l
Chris@87 1303 el=[x.strip() for x in markoutercomma(entitydecl).split('@,@')]
Chris@87 1304 el1=[]
Chris@87 1305 for e in el:
Chris@87 1306 for e1 in [x.strip() for x in markoutercomma(removespaces(markinnerspaces(e)), comma=' ').split('@ @')]:
Chris@87 1307 if e1: el1.append(e1.replace('@_@', ' '))
Chris@87 1308 for e in el1:
Chris@87 1309 m=namepattern.match(e)
Chris@87 1310 if not m:
Chris@87 1311 outmess('updatevars: no name pattern found for entity=%s. Skipping.\n'%(repr(e)))
Chris@87 1312 continue
Chris@87 1313 ename=rmbadname1(m.group('name'))
Chris@87 1314 edecl={}
Chris@87 1315 if ename in groupcache[groupcounter]['vars']:
Chris@87 1316 edecl=groupcache[groupcounter]['vars'][ename].copy()
Chris@87 1317 not_has_typespec = 'typespec' not in edecl
Chris@87 1318 if not_has_typespec:
Chris@87 1319 edecl['typespec']=typespec
Chris@87 1320 elif typespec and (not typespec==edecl['typespec']):
Chris@87 1321 outmess('updatevars: attempt to change the type of "%s" ("%s") to "%s". Ignoring.\n' % (ename, edecl['typespec'], typespec))
Chris@87 1322 if 'kindselector' not in edecl:
Chris@87 1323 edecl['kindselector']=copy.copy(kindselect)
Chris@87 1324 elif kindselect:
Chris@87 1325 for k in list(kindselect.keys()):
Chris@87 1326 if k in edecl['kindselector'] and (not kindselect[k]==edecl['kindselector'][k]):
Chris@87 1327 outmess('updatevars: attempt to change the kindselector "%s" of "%s" ("%s") to "%s". Ignoring.\n' % (k, ename, edecl['kindselector'][k], kindselect[k]))
Chris@87 1328 else: edecl['kindselector'][k]=copy.copy(kindselect[k])
Chris@87 1329 if 'charselector' not in edecl and charselect:
Chris@87 1330 if not_has_typespec:
Chris@87 1331 edecl['charselector']=charselect
Chris@87 1332 else:
Chris@87 1333 errmess('updatevars:%s: attempt to change empty charselector to %r. Ignoring.\n' \
Chris@87 1334 %(ename, charselect))
Chris@87 1335 elif charselect:
Chris@87 1336 for k in list(charselect.keys()):
Chris@87 1337 if k in edecl['charselector'] and (not charselect[k]==edecl['charselector'][k]):
Chris@87 1338 outmess('updatevars: attempt to change the charselector "%s" of "%s" ("%s") to "%s". Ignoring.\n' % (k, ename, edecl['charselector'][k], charselect[k]))
Chris@87 1339 else: edecl['charselector'][k]=copy.copy(charselect[k])
Chris@87 1340 if 'typename' not in edecl:
Chris@87 1341 edecl['typename']=typename
Chris@87 1342 elif typename and (not edecl['typename']==typename):
Chris@87 1343 outmess('updatevars: attempt to change the typename of "%s" ("%s") to "%s". Ignoring.\n' % (ename, edecl['typename'], typename))
Chris@87 1344 if 'attrspec' not in edecl:
Chris@87 1345 edecl['attrspec']=copy.copy(attrspec)
Chris@87 1346 elif attrspec:
Chris@87 1347 for a in attrspec:
Chris@87 1348 if a not in edecl['attrspec']:
Chris@87 1349 edecl['attrspec'].append(a)
Chris@87 1350 else:
Chris@87 1351 edecl['typespec']=copy.copy(typespec)
Chris@87 1352 edecl['kindselector']=copy.copy(kindselect)
Chris@87 1353 edecl['charselector']=copy.copy(charselect)
Chris@87 1354 edecl['typename']=typename
Chris@87 1355 edecl['attrspec']=copy.copy(attrspec)
Chris@87 1356 if m.group('after'):
Chris@87 1357 m1=lenarraypattern.match(markouterparen(m.group('after')))
Chris@87 1358 if m1:
Chris@87 1359 d1=m1.groupdict()
Chris@87 1360 for lk in ['len', 'array', 'init']:
Chris@87 1361 if d1[lk+'2'] is not None: d1[lk]=d1[lk+'2']; del d1[lk+'2']
Chris@87 1362 for k in list(d1.keys()):
Chris@87 1363 if d1[k] is not None: d1[k]=unmarkouterparen(d1[k])
Chris@87 1364 else: del d1[k]
Chris@87 1365 if 'len' in d1 and 'array' in d1:
Chris@87 1366 if d1['len']=='':
Chris@87 1367 d1['len']=d1['array']
Chris@87 1368 del d1['array']
Chris@87 1369 else:
Chris@87 1370 d1['array']=d1['array']+','+d1['len']
Chris@87 1371 del d1['len']
Chris@87 1372 errmess('updatevars: "%s %s" is mapped to "%s %s(%s)"\n'%(typespec, e, typespec, ename, d1['array']))
Chris@87 1373 if 'array' in d1:
Chris@87 1374 dm = 'dimension(%s)'%d1['array']
Chris@87 1375 if 'attrspec' not in edecl or (not edecl['attrspec']):
Chris@87 1376 edecl['attrspec']=[dm]
Chris@87 1377 else:
Chris@87 1378 edecl['attrspec'].append(dm)
Chris@87 1379 for dm1 in edecl['attrspec']:
Chris@87 1380 if dm1[:9]=='dimension' and dm1!=dm:
Chris@87 1381 del edecl['attrspec'][-1]
Chris@87 1382 errmess('updatevars:%s: attempt to change %r to %r. Ignoring.\n' \
Chris@87 1383 % (ename, dm1, dm))
Chris@87 1384 break
Chris@87 1385
Chris@87 1386 if 'len' in d1:
Chris@87 1387 if typespec in ['complex', 'integer', 'logical', 'real']:
Chris@87 1388 if ('kindselector' not in edecl) or (not edecl['kindselector']):
Chris@87 1389 edecl['kindselector']={}
Chris@87 1390 edecl['kindselector']['*']=d1['len']
Chris@87 1391 elif typespec == 'character':
Chris@87 1392 if ('charselector' not in edecl) or (not edecl['charselector']):
Chris@87 1393 edecl['charselector']={}
Chris@87 1394 if 'len' in edecl['charselector']:
Chris@87 1395 del edecl['charselector']['len']
Chris@87 1396 edecl['charselector']['*']=d1['len']
Chris@87 1397 if 'init' in d1:
Chris@87 1398 if '=' in edecl and (not edecl['=']==d1['init']):
Chris@87 1399 outmess('updatevars: attempt to change the init expression of "%s" ("%s") to "%s". Ignoring.\n' % (ename, edecl['='], d1['init']))
Chris@87 1400 else:
Chris@87 1401 edecl['=']=d1['init']
Chris@87 1402 else:
Chris@87 1403 outmess('updatevars: could not crack entity declaration "%s". Ignoring.\n'%(ename+m.group('after')))
Chris@87 1404 for k in list(edecl.keys()):
Chris@87 1405 if not edecl[k]:
Chris@87 1406 del edecl[k]
Chris@87 1407 groupcache[groupcounter]['vars'][ename]=edecl
Chris@87 1408 if 'varnames' in groupcache[groupcounter]:
Chris@87 1409 groupcache[groupcounter]['varnames'].append(ename)
Chris@87 1410 last_name = ename
Chris@87 1411 return last_name
Chris@87 1412
Chris@87 1413 def cracktypespec(typespec, selector):
Chris@87 1414 kindselect=None
Chris@87 1415 charselect=None
Chris@87 1416 typename=None
Chris@87 1417 if selector:
Chris@87 1418 if typespec in ['complex', 'integer', 'logical', 'real']:
Chris@87 1419 kindselect=kindselector.match(selector)
Chris@87 1420 if not kindselect:
Chris@87 1421 outmess('cracktypespec: no kindselector pattern found for %s\n'%(repr(selector)))
Chris@87 1422 return
Chris@87 1423 kindselect=kindselect.groupdict()
Chris@87 1424 kindselect['*']=kindselect['kind2']
Chris@87 1425 del kindselect['kind2']
Chris@87 1426 for k in list(kindselect.keys()):
Chris@87 1427 if not kindselect[k]: del kindselect[k]
Chris@87 1428 for k, i in list(kindselect.items()):
Chris@87 1429 kindselect[k] = rmbadname1(i)
Chris@87 1430 elif typespec=='character':
Chris@87 1431 charselect=charselector.match(selector)
Chris@87 1432 if not charselect:
Chris@87 1433 outmess('cracktypespec: no charselector pattern found for %s\n'%(repr(selector)))
Chris@87 1434 return
Chris@87 1435 charselect=charselect.groupdict()
Chris@87 1436 charselect['*']=charselect['charlen']
Chris@87 1437 del charselect['charlen']
Chris@87 1438 if charselect['lenkind']:
Chris@87 1439 lenkind=lenkindpattern.match(markoutercomma(charselect['lenkind']))
Chris@87 1440 lenkind=lenkind.groupdict()
Chris@87 1441 for lk in ['len', 'kind']:
Chris@87 1442 if lenkind[lk+'2']:
Chris@87 1443 lenkind[lk]=lenkind[lk+'2']
Chris@87 1444 charselect[lk]=lenkind[lk]
Chris@87 1445 del lenkind[lk+'2']
Chris@87 1446 del charselect['lenkind']
Chris@87 1447 for k in list(charselect.keys()):
Chris@87 1448 if not charselect[k]: del charselect[k]
Chris@87 1449 for k, i in list(charselect.items()):
Chris@87 1450 charselect[k] = rmbadname1(i)
Chris@87 1451 elif typespec=='type':
Chris@87 1452 typename=re.match(r'\s*\(\s*(?P<name>\w+)\s*\)', selector, re.I)
Chris@87 1453 if typename: typename=typename.group('name')
Chris@87 1454 else: outmess('cracktypespec: no typename found in %s\n'%(repr(typespec+selector)))
Chris@87 1455 else:
Chris@87 1456 outmess('cracktypespec: no selector used for %s\n'%(repr(selector)))
Chris@87 1457 return kindselect, charselect, typename
Chris@87 1458 ######
Chris@87 1459 def setattrspec(decl,attr,force=0):
Chris@87 1460 if not decl:
Chris@87 1461 decl={}
Chris@87 1462 if not attr:
Chris@87 1463 return decl
Chris@87 1464 if 'attrspec' not in decl:
Chris@87 1465 decl['attrspec']=[attr]
Chris@87 1466 return decl
Chris@87 1467 if force: decl['attrspec'].append(attr)
Chris@87 1468 if attr in decl['attrspec']: return decl
Chris@87 1469 if attr=='static' and 'automatic' not in decl['attrspec']:
Chris@87 1470 decl['attrspec'].append(attr)
Chris@87 1471 elif attr=='automatic' and 'static' not in decl['attrspec']:
Chris@87 1472 decl['attrspec'].append(attr)
Chris@87 1473 elif attr=='public' and 'private' not in decl['attrspec']:
Chris@87 1474 decl['attrspec'].append(attr)
Chris@87 1475 elif attr=='private' and 'public' not in decl['attrspec']:
Chris@87 1476 decl['attrspec'].append(attr)
Chris@87 1477 else:
Chris@87 1478 decl['attrspec'].append(attr)
Chris@87 1479 return decl
Chris@87 1480
Chris@87 1481 def setkindselector(decl,sel,force=0):
Chris@87 1482 if not decl:
Chris@87 1483 decl={}
Chris@87 1484 if not sel:
Chris@87 1485 return decl
Chris@87 1486 if 'kindselector' not in decl:
Chris@87 1487 decl['kindselector']=sel
Chris@87 1488 return decl
Chris@87 1489 for k in list(sel.keys()):
Chris@87 1490 if force or k not in decl['kindselector']:
Chris@87 1491 decl['kindselector'][k]=sel[k]
Chris@87 1492 return decl
Chris@87 1493
Chris@87 1494 def setcharselector(decl,sel,force=0):
Chris@87 1495 if not decl:
Chris@87 1496 decl={}
Chris@87 1497 if not sel:
Chris@87 1498 return decl
Chris@87 1499 if 'charselector' not in decl:
Chris@87 1500 decl['charselector']=sel
Chris@87 1501 return decl
Chris@87 1502 for k in list(sel.keys()):
Chris@87 1503 if force or k not in decl['charselector']:
Chris@87 1504 decl['charselector'][k]=sel[k]
Chris@87 1505 return decl
Chris@87 1506
Chris@87 1507 def getblockname(block,unknown='unknown'):
Chris@87 1508 if 'name' in block:
Chris@87 1509 return block['name']
Chris@87 1510 return unknown
Chris@87 1511
Chris@87 1512 ###### post processing
Chris@87 1513
Chris@87 1514 def setmesstext(block):
Chris@87 1515 global filepositiontext
Chris@87 1516 try:
Chris@87 1517 filepositiontext='In: %s:%s\n'%(block['from'], block['name'])
Chris@87 1518 except:
Chris@87 1519 pass
Chris@87 1520
Chris@87 1521 def get_usedict(block):
Chris@87 1522 usedict = {}
Chris@87 1523 if 'parent_block' in block:
Chris@87 1524 usedict = get_usedict(block['parent_block'])
Chris@87 1525 if 'use' in block:
Chris@87 1526 usedict.update(block['use'])
Chris@87 1527 return usedict
Chris@87 1528
Chris@87 1529 def get_useparameters(block, param_map=None):
Chris@87 1530 global f90modulevars
Chris@87 1531 if param_map is None:
Chris@87 1532 param_map = {}
Chris@87 1533 usedict = get_usedict(block)
Chris@87 1534 if not usedict:
Chris@87 1535 return param_map
Chris@87 1536 for usename, mapping in list(usedict.items()):
Chris@87 1537 usename = usename.lower()
Chris@87 1538 if usename not in f90modulevars:
Chris@87 1539 outmess('get_useparameters: no module %s info used by %s\n' % (usename, block.get('name')))
Chris@87 1540 continue
Chris@87 1541 mvars = f90modulevars[usename]
Chris@87 1542 params = get_parameters(mvars)
Chris@87 1543 if not params:
Chris@87 1544 continue
Chris@87 1545 # XXX: apply mapping
Chris@87 1546 if mapping:
Chris@87 1547 errmess('get_useparameters: mapping for %s not impl.' % (mapping))
Chris@87 1548 for k, v in list(params.items()):
Chris@87 1549 if k in param_map:
Chris@87 1550 outmess('get_useparameters: overriding parameter %s with'\
Chris@87 1551 ' value from module %s' % (repr(k), repr(usename)))
Chris@87 1552 param_map[k] = v
Chris@87 1553
Chris@87 1554 return param_map
Chris@87 1555
Chris@87 1556 def postcrack2(block,tab='',param_map=None):
Chris@87 1557 global f90modulevars
Chris@87 1558 if not f90modulevars:
Chris@87 1559 return block
Chris@87 1560 if isinstance(block, list):
Chris@87 1561 ret = []
Chris@87 1562 for g in block:
Chris@87 1563 g = postcrack2(g, tab=tab+'\t', param_map=param_map)
Chris@87 1564 ret.append(g)
Chris@87 1565 return ret
Chris@87 1566 setmesstext(block)
Chris@87 1567 outmess('%sBlock: %s\n'%(tab, block['name']), 0)
Chris@87 1568
Chris@87 1569 if param_map is None:
Chris@87 1570 param_map = get_useparameters(block)
Chris@87 1571
Chris@87 1572 if param_map is not None and 'vars' in block:
Chris@87 1573 vars = block['vars']
Chris@87 1574 for n in list(vars.keys()):
Chris@87 1575 var = vars[n]
Chris@87 1576 if 'kindselector' in var:
Chris@87 1577 kind = var['kindselector']
Chris@87 1578 if 'kind' in kind:
Chris@87 1579 val = kind['kind']
Chris@87 1580 if val in param_map:
Chris@87 1581 kind['kind'] = param_map[val]
Chris@87 1582 new_body = []
Chris@87 1583 for b in block['body']:
Chris@87 1584 b = postcrack2(b, tab=tab+'\t', param_map=param_map)
Chris@87 1585 new_body.append(b)
Chris@87 1586 block['body'] = new_body
Chris@87 1587
Chris@87 1588 return block
Chris@87 1589
Chris@87 1590 def postcrack(block,args=None,tab=''):
Chris@87 1591 """
Chris@87 1592 TODO:
Chris@87 1593 function return values
Chris@87 1594 determine expression types if in argument list
Chris@87 1595 """
Chris@87 1596 global usermodules, onlyfunctions
Chris@87 1597 if isinstance(block, list):
Chris@87 1598 gret=[]
Chris@87 1599 uret=[]
Chris@87 1600 for g in block:
Chris@87 1601 setmesstext(g)
Chris@87 1602 g=postcrack(g, tab=tab+'\t')
Chris@87 1603 if 'name' in g and '__user__' in g['name']: # sort user routines to appear first
Chris@87 1604 uret.append(g)
Chris@87 1605 else:
Chris@87 1606 gret.append(g)
Chris@87 1607 return uret+gret
Chris@87 1608 setmesstext(block)
Chris@87 1609 if not isinstance(block, dict) and 'block' not in block:
Chris@87 1610 raise Exception('postcrack: Expected block dictionary instead of ' + \
Chris@87 1611 str(block))
Chris@87 1612 if 'name' in block and not block['name']=='unknown_interface':
Chris@87 1613 outmess('%sBlock: %s\n'%(tab, block['name']), 0)
Chris@87 1614 blocktype=block['block']
Chris@87 1615 block=analyzeargs(block)
Chris@87 1616 block=analyzecommon(block)
Chris@87 1617 block['vars']=analyzevars(block)
Chris@87 1618 block['sortvars']=sortvarnames(block['vars'])
Chris@87 1619 if 'args' in block and block['args']:
Chris@87 1620 args=block['args']
Chris@87 1621 block['body']=analyzebody(block, args, tab=tab)
Chris@87 1622
Chris@87 1623 userisdefined=[]
Chris@87 1624 ## fromuser = []
Chris@87 1625 if 'use' in block:
Chris@87 1626 useblock=block['use']
Chris@87 1627 for k in list(useblock.keys()):
Chris@87 1628 if '__user__' in k:
Chris@87 1629 userisdefined.append(k)
Chris@87 1630 ## if 'map' in useblock[k]:
Chris@87 1631 ## for n in useblock[k]['map'].itervalues():
Chris@87 1632 ## if n not in fromuser: fromuser.append(n)
Chris@87 1633 else: useblock={}
Chris@87 1634 name=''
Chris@87 1635 if 'name' in block:
Chris@87 1636 name=block['name']
Chris@87 1637 if 'externals' in block and block['externals']:# and not userisdefined: # Build a __user__ module
Chris@87 1638 interfaced=[]
Chris@87 1639 if 'interfaced' in block:
Chris@87 1640 interfaced=block['interfaced']
Chris@87 1641 mvars=copy.copy(block['vars'])
Chris@87 1642 if name:
Chris@87 1643 mname=name+'__user__routines'
Chris@87 1644 else:
Chris@87 1645 mname='unknown__user__routines'
Chris@87 1646 if mname in userisdefined:
Chris@87 1647 i=1
Chris@87 1648 while '%s_%i'%(mname, i) in userisdefined: i=i+1
Chris@87 1649 mname='%s_%i'%(mname, i)
Chris@87 1650 interface={'block':'interface','body':[],'vars':{},'name':name+'_user_interface'}
Chris@87 1651 for e in block['externals']:
Chris@87 1652 ## if e in fromuser:
Chris@87 1653 ## outmess(' Skipping %s that is defined explicitly in another use statement\n'%(`e`))
Chris@87 1654 ## continue
Chris@87 1655 if e in interfaced:
Chris@87 1656 edef=[]
Chris@87 1657 j=-1
Chris@87 1658 for b in block['body']:
Chris@87 1659 j=j+1
Chris@87 1660 if b['block']=='interface':
Chris@87 1661 i=-1
Chris@87 1662 for bb in b['body']:
Chris@87 1663 i=i+1
Chris@87 1664 if 'name' in bb and bb['name']==e:
Chris@87 1665 edef=copy.copy(bb)
Chris@87 1666 del b['body'][i]
Chris@87 1667 break
Chris@87 1668 if edef:
Chris@87 1669 if not b['body']: del block['body'][j]
Chris@87 1670 del interfaced[interfaced.index(e)]
Chris@87 1671 break
Chris@87 1672 interface['body'].append(edef)
Chris@87 1673 else:
Chris@87 1674 if e in mvars and not isexternal(mvars[e]):
Chris@87 1675 interface['vars'][e]=mvars[e]
Chris@87 1676 if interface['vars'] or interface['body']:
Chris@87 1677 block['interfaced']=interfaced
Chris@87 1678 mblock={'block':'python module','body':[interface],'vars':{},'name':mname,'interfaced':block['externals']}
Chris@87 1679 useblock[mname]={}
Chris@87 1680 usermodules.append(mblock)
Chris@87 1681 if useblock:
Chris@87 1682 block['use']=useblock
Chris@87 1683 return block
Chris@87 1684
Chris@87 1685 def sortvarnames(vars):
Chris@87 1686 indep = []
Chris@87 1687 dep = []
Chris@87 1688 for v in list(vars.keys()):
Chris@87 1689 if 'depend' in vars[v] and vars[v]['depend']:
Chris@87 1690 dep.append(v)
Chris@87 1691 #print '%s depends on %s'%(v,vars[v]['depend'])
Chris@87 1692 else: indep.append(v)
Chris@87 1693 n = len(dep)
Chris@87 1694 i = 0
Chris@87 1695 while dep: #XXX: How to catch dependence cycles correctly?
Chris@87 1696 v = dep[0]
Chris@87 1697 fl = 0
Chris@87 1698 for w in dep[1:]:
Chris@87 1699 if w in vars[v]['depend']:
Chris@87 1700 fl = 1
Chris@87 1701 break
Chris@87 1702 if fl:
Chris@87 1703 dep = dep[1:]+[v]
Chris@87 1704 i = i + 1
Chris@87 1705 if i>n:
Chris@87 1706 errmess('sortvarnames: failed to compute dependencies because'
Chris@87 1707 ' of cyclic dependencies between '
Chris@87 1708 +', '.join(dep)+'\n')
Chris@87 1709 indep = indep + dep
Chris@87 1710 break
Chris@87 1711 else:
Chris@87 1712 indep.append(v)
Chris@87 1713 dep = dep[1:]
Chris@87 1714 n = len(dep)
Chris@87 1715 i = 0
Chris@87 1716 #print indep
Chris@87 1717 return indep
Chris@87 1718
Chris@87 1719 def analyzecommon(block):
Chris@87 1720 if not hascommon(block): return block
Chris@87 1721 commonvars=[]
Chris@87 1722 for k in list(block['common'].keys()):
Chris@87 1723 comvars=[]
Chris@87 1724 for e in block['common'][k]:
Chris@87 1725 m=re.match(r'\A\s*\b(?P<name>.*?)\b\s*(\((?P<dims>.*?)\)|)\s*\Z', e, re.I)
Chris@87 1726 if m:
Chris@87 1727 dims=[]
Chris@87 1728 if m.group('dims'):
Chris@87 1729 dims=[x.strip() for x in markoutercomma(m.group('dims')).split('@,@')]
Chris@87 1730 n=m.group('name').strip()
Chris@87 1731 if n in block['vars']:
Chris@87 1732 if 'attrspec' in block['vars'][n]:
Chris@87 1733 block['vars'][n]['attrspec'].append('dimension(%s)'%(','.join(dims)))
Chris@87 1734 else:
Chris@87 1735 block['vars'][n]['attrspec']=['dimension(%s)'%(','.join(dims))]
Chris@87 1736 else:
Chris@87 1737 if dims:
Chris@87 1738 block['vars'][n]={'attrspec':['dimension(%s)'%(','.join(dims))]}
Chris@87 1739 else: block['vars'][n]={}
Chris@87 1740 if n not in commonvars: commonvars.append(n)
Chris@87 1741 else:
Chris@87 1742 n=e
Chris@87 1743 errmess('analyzecommon: failed to extract "<name>[(<dims>)]" from "%s" in common /%s/.\n'%(e, k))
Chris@87 1744 comvars.append(n)
Chris@87 1745 block['common'][k]=comvars
Chris@87 1746 if 'commonvars' not in block:
Chris@87 1747 block['commonvars']=commonvars
Chris@87 1748 else:
Chris@87 1749 block['commonvars']=block['commonvars']+commonvars
Chris@87 1750 return block
Chris@87 1751
Chris@87 1752 def analyzebody(block,args,tab=''):
Chris@87 1753 global usermodules, skipfuncs, onlyfuncs, f90modulevars
Chris@87 1754 setmesstext(block)
Chris@87 1755 body=[]
Chris@87 1756 for b in block['body']:
Chris@87 1757 b['parent_block'] = block
Chris@87 1758 if b['block'] in ['function', 'subroutine']:
Chris@87 1759 if args is not None and b['name'] not in args:
Chris@87 1760 continue
Chris@87 1761 else:
Chris@87 1762 as_=b['args']
Chris@87 1763 if b['name'] in skipfuncs:
Chris@87 1764 continue
Chris@87 1765 if onlyfuncs and b['name'] not in onlyfuncs:
Chris@87 1766 continue
Chris@87 1767 b['saved_interface'] = crack2fortrangen(b, '\n'+' '*6, as_interface=True)
Chris@87 1768
Chris@87 1769 else: as_=args
Chris@87 1770 b=postcrack(b, as_, tab=tab+'\t')
Chris@87 1771 if b['block']=='interface' and not b['body']:
Chris@87 1772 if 'f2pyenhancements' not in b:
Chris@87 1773 continue
Chris@87 1774 if b['block'].replace(' ', '')=='pythonmodule':
Chris@87 1775 usermodules.append(b)
Chris@87 1776 else:
Chris@87 1777 if b['block']=='module':
Chris@87 1778 f90modulevars[b['name']] = b['vars']
Chris@87 1779 body.append(b)
Chris@87 1780 return body
Chris@87 1781
Chris@87 1782 def buildimplicitrules(block):
Chris@87 1783 setmesstext(block)
Chris@87 1784 implicitrules=defaultimplicitrules
Chris@87 1785 attrrules={}
Chris@87 1786 if 'implicit' in block:
Chris@87 1787 if block['implicit'] is None:
Chris@87 1788 implicitrules=None
Chris@87 1789 if verbose>1:
Chris@87 1790 outmess('buildimplicitrules: no implicit rules for routine %s.\n'%repr(block['name']))
Chris@87 1791 else:
Chris@87 1792 for k in list(block['implicit'].keys()):
Chris@87 1793 if block['implicit'][k].get('typespec') not in ['static', 'automatic']:
Chris@87 1794 implicitrules[k]=block['implicit'][k]
Chris@87 1795 else:
Chris@87 1796 attrrules[k]=block['implicit'][k]['typespec']
Chris@87 1797 return implicitrules, attrrules
Chris@87 1798
Chris@87 1799 def myeval(e,g=None,l=None):
Chris@87 1800 r = eval(e, g, l)
Chris@87 1801 if type(r) in [type(0), type(0.0)]:
Chris@87 1802 return r
Chris@87 1803 raise ValueError('r=%r' % (r))
Chris@87 1804
Chris@87 1805 getlincoef_re_1 = re.compile(r'\A\b\w+\b\Z', re.I)
Chris@87 1806 def getlincoef(e, xset): # e = a*x+b ; x in xset
Chris@87 1807 try:
Chris@87 1808 c = int(myeval(e, {}, {}))
Chris@87 1809 return 0, c, None
Chris@87 1810 except: pass
Chris@87 1811 if getlincoef_re_1.match(e):
Chris@87 1812 return 1, 0, e
Chris@87 1813 len_e = len(e)
Chris@87 1814 for x in xset:
Chris@87 1815 if len(x)>len_e: continue
Chris@87 1816 if re.search(r'\w\s*\([^)]*\b'+x+r'\b', e):
Chris@87 1817 # skip function calls having x as an argument, e.g max(1, x)
Chris@87 1818 continue
Chris@87 1819 re_1 = re.compile(r'(?P<before>.*?)\b'+x+r'\b(?P<after>.*)', re.I)
Chris@87 1820 m = re_1.match(e)
Chris@87 1821 if m:
Chris@87 1822 try:
Chris@87 1823 m1 = re_1.match(e)
Chris@87 1824 while m1:
Chris@87 1825 ee = '%s(%s)%s'%(m1.group('before'), 0, m1.group('after'))
Chris@87 1826 m1 = re_1.match(ee)
Chris@87 1827 b = myeval(ee, {}, {})
Chris@87 1828 m1 = re_1.match(e)
Chris@87 1829 while m1:
Chris@87 1830 ee = '%s(%s)%s'%(m1.group('before'), 1, m1.group('after'))
Chris@87 1831 m1 = re_1.match(ee)
Chris@87 1832 a = myeval(ee, {}, {}) - b
Chris@87 1833 m1 = re_1.match(e)
Chris@87 1834 while m1:
Chris@87 1835 ee = '%s(%s)%s'%(m1.group('before'), 0.5, m1.group('after'))
Chris@87 1836 m1 = re_1.match(ee)
Chris@87 1837 c = myeval(ee, {}, {})
Chris@87 1838 # computing another point to be sure that expression is linear
Chris@87 1839 m1 = re_1.match(e)
Chris@87 1840 while m1:
Chris@87 1841 ee = '%s(%s)%s'%(m1.group('before'), 1.5, m1.group('after'))
Chris@87 1842 m1 = re_1.match(ee)
Chris@87 1843 c2 = myeval(ee, {}, {})
Chris@87 1844 if (a*0.5+b==c and a*1.5+b==c2):
Chris@87 1845 return a, b, x
Chris@87 1846 except: pass
Chris@87 1847 break
Chris@87 1848 return None, None, None
Chris@87 1849
Chris@87 1850 _varname_match = re.compile(r'\A[a-z]\w*\Z').match
Chris@87 1851 def getarrlen(dl,args,star='*'):
Chris@87 1852 edl = []
Chris@87 1853 try: edl.append(myeval(dl[0], {}, {}))
Chris@87 1854 except: edl.append(dl[0])
Chris@87 1855 try: edl.append(myeval(dl[1], {}, {}))
Chris@87 1856 except: edl.append(dl[1])
Chris@87 1857 if isinstance(edl[0], int):
Chris@87 1858 p1 = 1-edl[0]
Chris@87 1859 if p1==0: d = str(dl[1])
Chris@87 1860 elif p1<0: d = '%s-%s'%(dl[1], -p1)
Chris@87 1861 else: d = '%s+%s'%(dl[1], p1)
Chris@87 1862 elif isinstance(edl[1], int):
Chris@87 1863 p1 = 1+edl[1]
Chris@87 1864 if p1==0: d='-(%s)' % (dl[0])
Chris@87 1865 else: d='%s-(%s)' % (p1, dl[0])
Chris@87 1866 else: d = '%s-(%s)+1'%(dl[1], dl[0])
Chris@87 1867 try: return repr(myeval(d, {}, {})), None, None
Chris@87 1868 except: pass
Chris@87 1869 d1, d2=getlincoef(dl[0], args), getlincoef(dl[1], args)
Chris@87 1870 if None not in [d1[0], d2[0]]:
Chris@87 1871 if (d1[0], d2[0])==(0, 0):
Chris@87 1872 return repr(d2[1]-d1[1]+1), None, None
Chris@87 1873 b = d2[1] - d1[1] + 1
Chris@87 1874 d1 = (d1[0], 0, d1[2])
Chris@87 1875 d2 = (d2[0], b, d2[2])
Chris@87 1876 if d1[0]==0 and d2[2] in args:
Chris@87 1877 if b<0: return '%s * %s - %s'%(d2[0], d2[2], -b), d2[2], '+%s)/(%s)'%(-b, d2[0])
Chris@87 1878 elif b: return '%s * %s + %s'%(d2[0], d2[2], b), d2[2], '-%s)/(%s)'%(b, d2[0])
Chris@87 1879 else: return '%s * %s'%(d2[0], d2[2]), d2[2], ')/(%s)'%(d2[0])
Chris@87 1880 if d2[0]==0 and d1[2] in args:
Chris@87 1881
Chris@87 1882 if b<0: return '%s * %s - %s'%(-d1[0], d1[2], -b), d1[2], '+%s)/(%s)'%(-b, -d1[0])
Chris@87 1883 elif b: return '%s * %s + %s'%(-d1[0], d1[2], b), d1[2], '-%s)/(%s)'%(b, -d1[0])
Chris@87 1884 else: return '%s * %s'%(-d1[0], d1[2]), d1[2], ')/(%s)'%(-d1[0])
Chris@87 1885 if d1[2]==d2[2] and d1[2] in args:
Chris@87 1886 a = d2[0] - d1[0]
Chris@87 1887 if not a: return repr(b), None, None
Chris@87 1888 if b<0: return '%s * %s - %s'%(a, d1[2], -b), d2[2], '+%s)/(%s)'%(-b, a)
Chris@87 1889 elif b: return '%s * %s + %s'%(a, d1[2], b), d2[2], '-%s)/(%s)'%(b, a)
Chris@87 1890 else: return '%s * %s'%(a, d1[2]), d2[2], ')/(%s)'%(a)
Chris@87 1891 if d1[0]==d2[0]==1:
Chris@87 1892 c = str(d1[2])
Chris@87 1893 if c not in args:
Chris@87 1894 if _varname_match(c):
Chris@87 1895 outmess('\tgetarrlen:variable "%s" undefined\n' % (c))
Chris@87 1896 c = '(%s)'%c
Chris@87 1897 if b==0: d='%s-%s' % (d2[2], c)
Chris@87 1898 elif b<0: d='%s-%s-%s' % (d2[2], c, -b)
Chris@87 1899 else: d='%s-%s+%s' % (d2[2], c, b)
Chris@87 1900 elif d1[0]==0:
Chris@87 1901 c2 = str(d2[2])
Chris@87 1902 if c2 not in args:
Chris@87 1903 if _varname_match(c2):
Chris@87 1904 outmess('\tgetarrlen:variable "%s" undefined\n' % (c2))
Chris@87 1905 c2 = '(%s)'%c2
Chris@87 1906 if d2[0]==1: pass
Chris@87 1907 elif d2[0]==-1: c2='-%s' %c2
Chris@87 1908 else: c2='%s*%s'%(d2[0], c2)
Chris@87 1909
Chris@87 1910 if b==0: d=c2
Chris@87 1911 elif b<0: d='%s-%s' % (c2, -b)
Chris@87 1912 else: d='%s+%s' % (c2, b)
Chris@87 1913 elif d2[0]==0:
Chris@87 1914 c1 = str(d1[2])
Chris@87 1915 if c1 not in args:
Chris@87 1916 if _varname_match(c1):
Chris@87 1917 outmess('\tgetarrlen:variable "%s" undefined\n' % (c1))
Chris@87 1918 c1 = '(%s)'%c1
Chris@87 1919 if d1[0]==1: c1='-%s'%c1
Chris@87 1920 elif d1[0]==-1: c1='+%s'%c1
Chris@87 1921 elif d1[0]<0: c1='+%s*%s'%(-d1[0], c1)
Chris@87 1922 else: c1 = '-%s*%s' % (d1[0], c1)
Chris@87 1923
Chris@87 1924 if b==0: d=c1
Chris@87 1925 elif b<0: d='%s-%s' % (c1, -b)
Chris@87 1926 else: d='%s+%s' % (c1, b)
Chris@87 1927 else:
Chris@87 1928 c1 = str(d1[2])
Chris@87 1929 if c1 not in args:
Chris@87 1930 if _varname_match(c1):
Chris@87 1931 outmess('\tgetarrlen:variable "%s" undefined\n' % (c1))
Chris@87 1932 c1 = '(%s)'%c1
Chris@87 1933 if d1[0]==1: c1='-%s'%c1
Chris@87 1934 elif d1[0]==-1: c1='+%s'%c1
Chris@87 1935 elif d1[0]<0: c1='+%s*%s'%(-d1[0], c1)
Chris@87 1936 else: c1 = '-%s*%s' % (d1[0], c1)
Chris@87 1937
Chris@87 1938 c2 = str(d2[2])
Chris@87 1939 if c2 not in args:
Chris@87 1940 if _varname_match(c2):
Chris@87 1941 outmess('\tgetarrlen:variable "%s" undefined\n' % (c2))
Chris@87 1942 c2 = '(%s)'%c2
Chris@87 1943 if d2[0]==1: pass
Chris@87 1944 elif d2[0]==-1: c2='-%s' %c2
Chris@87 1945 else: c2='%s*%s'%(d2[0], c2)
Chris@87 1946
Chris@87 1947 if b==0: d='%s%s' % (c2, c1)
Chris@87 1948 elif b<0: d='%s%s-%s' % (c2, c1, -b)
Chris@87 1949 else: d='%s%s+%s' % (c2, c1, b)
Chris@87 1950 return d, None, None
Chris@87 1951
Chris@87 1952 word_pattern = re.compile(r'\b[a-z][\w$]*\b', re.I)
Chris@87 1953
Chris@87 1954 def _get_depend_dict(name, vars, deps):
Chris@87 1955 if name in vars:
Chris@87 1956 words = vars[name].get('depend', [])
Chris@87 1957
Chris@87 1958 if '=' in vars[name] and not isstring(vars[name]):
Chris@87 1959 for word in word_pattern.findall(vars[name]['=']):
Chris@87 1960 if word not in words and word in vars:
Chris@87 1961 words.append(word)
Chris@87 1962 for word in words[:]:
Chris@87 1963 for w in deps.get(word, []) \
Chris@87 1964 or _get_depend_dict(word, vars, deps):
Chris@87 1965 if w not in words:
Chris@87 1966 words.append(w)
Chris@87 1967 else:
Chris@87 1968 outmess('_get_depend_dict: no dependence info for %s\n' % (repr(name)))
Chris@87 1969 words = []
Chris@87 1970 deps[name] = words
Chris@87 1971 return words
Chris@87 1972
Chris@87 1973 def _calc_depend_dict(vars):
Chris@87 1974 names = list(vars.keys())
Chris@87 1975 depend_dict = {}
Chris@87 1976 for n in names:
Chris@87 1977 _get_depend_dict(n, vars, depend_dict)
Chris@87 1978 return depend_dict
Chris@87 1979
Chris@87 1980 def get_sorted_names(vars):
Chris@87 1981 """
Chris@87 1982 """
Chris@87 1983 depend_dict = _calc_depend_dict(vars)
Chris@87 1984 names = []
Chris@87 1985 for name in list(depend_dict.keys()):
Chris@87 1986 if not depend_dict[name]:
Chris@87 1987 names.append(name)
Chris@87 1988 del depend_dict[name]
Chris@87 1989 while depend_dict:
Chris@87 1990 for name, lst in list(depend_dict.items()):
Chris@87 1991 new_lst = [n for n in lst if n in depend_dict]
Chris@87 1992 if not new_lst:
Chris@87 1993 names.append(name)
Chris@87 1994 del depend_dict[name]
Chris@87 1995 else:
Chris@87 1996 depend_dict[name] = new_lst
Chris@87 1997 return [name for name in names if name in vars]
Chris@87 1998
Chris@87 1999 def _kind_func(string):
Chris@87 2000 #XXX: return something sensible.
Chris@87 2001 if string[0] in "'\"":
Chris@87 2002 string = string[1:-1]
Chris@87 2003 if real16pattern.match(string):
Chris@87 2004 return 8
Chris@87 2005 elif real8pattern.match(string):
Chris@87 2006 return 4
Chris@87 2007 return 'kind('+string+')'
Chris@87 2008
Chris@87 2009 def _selected_int_kind_func(r):
Chris@87 2010 #XXX: This should be processor dependent
Chris@87 2011 m = 10**r
Chris@87 2012 if m<=2**8: return 1
Chris@87 2013 if m<=2**16: return 2
Chris@87 2014 if m<=2**32: return 4
Chris@87 2015 if m<=2**63: return 8
Chris@87 2016 if m<=2**128: return 16
Chris@87 2017 return -1
Chris@87 2018
Chris@87 2019 def _selected_real_kind_func(p, r=0, radix=0):
Chris@87 2020 #XXX: This should be processor dependent
Chris@87 2021 # This is only good for 0 <= p <= 20
Chris@87 2022 if p < 7: return 4
Chris@87 2023 if p < 16: return 8
Chris@87 2024 if platform.machine().lower().startswith('power'):
Chris@87 2025 if p <= 20:
Chris@87 2026 return 16
Chris@87 2027 else:
Chris@87 2028 if p < 19:
Chris@87 2029 return 10
Chris@87 2030 elif p <= 20:
Chris@87 2031 return 16
Chris@87 2032 return -1
Chris@87 2033
Chris@87 2034 def get_parameters(vars, global_params={}):
Chris@87 2035 params = copy.copy(global_params)
Chris@87 2036 g_params = copy.copy(global_params)
Chris@87 2037 for name, func in [('kind', _kind_func),
Chris@87 2038 ('selected_int_kind', _selected_int_kind_func),
Chris@87 2039 ('selected_real_kind', _selected_real_kind_func),
Chris@87 2040 ]:
Chris@87 2041 if name not in g_params:
Chris@87 2042 g_params[name] = func
Chris@87 2043 param_names = []
Chris@87 2044 for n in get_sorted_names(vars):
Chris@87 2045 if 'attrspec' in vars[n] and 'parameter' in vars[n]['attrspec']:
Chris@87 2046 param_names.append(n)
Chris@87 2047 kind_re = re.compile(r'\bkind\s*\(\s*(?P<value>.*)\s*\)', re.I)
Chris@87 2048 selected_int_kind_re = re.compile(r'\bselected_int_kind\s*\(\s*(?P<value>.*)\s*\)', re.I)
Chris@87 2049 selected_kind_re = re.compile(r'\bselected_(int|real)_kind\s*\(\s*(?P<value>.*)\s*\)', re.I)
Chris@87 2050 for n in param_names:
Chris@87 2051 if '=' in vars[n]:
Chris@87 2052 v = vars[n]['=']
Chris@87 2053 if islogical(vars[n]):
Chris@87 2054 v = v.lower()
Chris@87 2055 for repl in [
Chris@87 2056 ('.false.', 'False'),
Chris@87 2057 ('.true.', 'True'),
Chris@87 2058 #TODO: test .eq., .neq., etc replacements.
Chris@87 2059 ]:
Chris@87 2060 v = v.replace(*repl)
Chris@87 2061 v = kind_re.sub(r'kind("\1")', v)
Chris@87 2062 v = selected_int_kind_re.sub(r'selected_int_kind(\1)', v)
Chris@87 2063 if isinteger(vars[n]) and not selected_kind_re.match(v):
Chris@87 2064 v = v.split('_')[0]
Chris@87 2065 if isdouble(vars[n]):
Chris@87 2066 tt = list(v)
Chris@87 2067 for m in real16pattern.finditer(v):
Chris@87 2068 tt[m.start():m.end()] = list(\
Chris@87 2069 v[m.start():m.end()].lower().replace('d', 'e'))
Chris@87 2070 v = ''.join(tt)
Chris@87 2071 if iscomplex(vars[n]):
Chris@87 2072 if v[0]=='(' and v[-1]==')':
Chris@87 2073 l = markoutercomma(v[1:-1]).split('@,@')
Chris@87 2074 try:
Chris@87 2075 params[n] = eval(v, g_params, params)
Chris@87 2076 except Exception as msg:
Chris@87 2077 params[n] = v
Chris@87 2078 #print params
Chris@87 2079 outmess('get_parameters: got "%s" on %s\n' % (msg, repr(v)))
Chris@87 2080 if isstring(vars[n]) and isinstance(params[n], int):
Chris@87 2081 params[n] = chr(params[n])
Chris@87 2082 nl = n.lower()
Chris@87 2083 if nl!=n:
Chris@87 2084 params[nl] = params[n]
Chris@87 2085 else:
Chris@87 2086 print(vars[n])
Chris@87 2087 outmess('get_parameters:parameter %s does not have value?!\n'%(repr(n)))
Chris@87 2088 return params
Chris@87 2089
Chris@87 2090 def _eval_length(length, params):
Chris@87 2091 if length in ['(:)', '(*)', '*']:
Chris@87 2092 return '(*)'
Chris@87 2093 return _eval_scalar(length, params)
Chris@87 2094
Chris@87 2095 _is_kind_number = re.compile(r'\d+_').match
Chris@87 2096
Chris@87 2097 def _eval_scalar(value, params):
Chris@87 2098 if _is_kind_number(value):
Chris@87 2099 value = value.split('_')[0]
Chris@87 2100 try:
Chris@87 2101 value = str(eval(value, {}, params))
Chris@87 2102 except (NameError, SyntaxError):
Chris@87 2103 return value
Chris@87 2104 except Exception as msg:
Chris@87 2105 errmess('"%s" in evaluating %r '\
Chris@87 2106 '(available names: %s)\n' \
Chris@87 2107 % (msg, value, list(params.keys())))
Chris@87 2108 return value
Chris@87 2109
Chris@87 2110 def analyzevars(block):
Chris@87 2111 global f90modulevars
Chris@87 2112 setmesstext(block)
Chris@87 2113 implicitrules, attrrules=buildimplicitrules(block)
Chris@87 2114 vars=copy.copy(block['vars'])
Chris@87 2115 if block['block']=='function' and block['name'] not in vars:
Chris@87 2116 vars[block['name']]={}
Chris@87 2117 if '' in block['vars']:
Chris@87 2118 del vars['']
Chris@87 2119 if 'attrspec' in block['vars']['']:
Chris@87 2120 gen=block['vars']['']['attrspec']
Chris@87 2121 for n in list(vars.keys()):
Chris@87 2122 for k in ['public', 'private']:
Chris@87 2123 if k in gen:
Chris@87 2124 vars[n]=setattrspec(vars[n], k)
Chris@87 2125 svars=[]
Chris@87 2126 args = block['args']
Chris@87 2127 for a in args:
Chris@87 2128 try:
Chris@87 2129 vars[a]
Chris@87 2130 svars.append(a)
Chris@87 2131 except KeyError:
Chris@87 2132 pass
Chris@87 2133 for n in list(vars.keys()):
Chris@87 2134 if n not in args: svars.append(n)
Chris@87 2135
Chris@87 2136 params = get_parameters(vars, get_useparameters(block))
Chris@87 2137
Chris@87 2138 dep_matches = {}
Chris@87 2139 name_match = re.compile(r'\w[\w\d_$]*').match
Chris@87 2140 for v in list(vars.keys()):
Chris@87 2141 m = name_match(v)
Chris@87 2142 if m:
Chris@87 2143 n = v[m.start():m.end()]
Chris@87 2144 try:
Chris@87 2145 dep_matches[n]
Chris@87 2146 except KeyError:
Chris@87 2147 dep_matches[n] = re.compile(r'.*\b%s\b'%(v), re.I).match
Chris@87 2148 for n in svars:
Chris@87 2149 if n[0] in list(attrrules.keys()):
Chris@87 2150 vars[n]=setattrspec(vars[n], attrrules[n[0]])
Chris@87 2151 if 'typespec' not in vars[n]:
Chris@87 2152 if not('attrspec' in vars[n] and 'external' in vars[n]['attrspec']):
Chris@87 2153 if implicitrules:
Chris@87 2154 ln0 = n[0].lower()
Chris@87 2155 for k in list(implicitrules[ln0].keys()):
Chris@87 2156 if k=='typespec' and implicitrules[ln0][k]=='undefined':
Chris@87 2157 continue
Chris@87 2158 if k not in vars[n]:
Chris@87 2159 vars[n][k]=implicitrules[ln0][k]
Chris@87 2160 elif k=='attrspec':
Chris@87 2161 for l in implicitrules[ln0][k]:
Chris@87 2162 vars[n]=setattrspec(vars[n], l)
Chris@87 2163 elif n in block['args']:
Chris@87 2164 outmess('analyzevars: typespec of variable %s is not defined in routine %s.\n'%(repr(n), block['name']))
Chris@87 2165
Chris@87 2166 if 'charselector' in vars[n]:
Chris@87 2167 if 'len' in vars[n]['charselector']:
Chris@87 2168 l = vars[n]['charselector']['len']
Chris@87 2169 try:
Chris@87 2170 l = str(eval(l, {}, params))
Chris@87 2171 except:
Chris@87 2172 pass
Chris@87 2173 vars[n]['charselector']['len'] = l
Chris@87 2174
Chris@87 2175 if 'kindselector' in vars[n]:
Chris@87 2176 if 'kind' in vars[n]['kindselector']:
Chris@87 2177 l = vars[n]['kindselector']['kind']
Chris@87 2178 try:
Chris@87 2179 l = str(eval(l, {}, params))
Chris@87 2180 except:
Chris@87 2181 pass
Chris@87 2182 vars[n]['kindselector']['kind'] = l
Chris@87 2183
Chris@87 2184 savelindims = {}
Chris@87 2185 if 'attrspec' in vars[n]:
Chris@87 2186 attr=vars[n]['attrspec']
Chris@87 2187 attr.reverse()
Chris@87 2188 vars[n]['attrspec']=[]
Chris@87 2189 dim, intent, depend, check, note=None, None, None, None, None
Chris@87 2190 for a in attr:
Chris@87 2191 if a[:9]=='dimension': dim=(a[9:].strip())[1:-1]
Chris@87 2192 elif a[:6]=='intent': intent=(a[6:].strip())[1:-1]
Chris@87 2193 elif a[:6]=='depend': depend=(a[6:].strip())[1:-1]
Chris@87 2194 elif a[:5]=='check': check=(a[5:].strip())[1:-1]
Chris@87 2195 elif a[:4]=='note': note=(a[4:].strip())[1:-1]
Chris@87 2196 else: vars[n]=setattrspec(vars[n], a)
Chris@87 2197 if intent:
Chris@87 2198 if 'intent' not in vars[n]:
Chris@87 2199 vars[n]['intent']=[]
Chris@87 2200 for c in [x.strip() for x in markoutercomma(intent).split('@,@')]:
Chris@87 2201 # Remove spaces so that 'in out' becomes 'inout'
Chris@87 2202 tmp = c.replace(' ', '')
Chris@87 2203 if tmp not in vars[n]['intent']:
Chris@87 2204 vars[n]['intent'].append(tmp)
Chris@87 2205 intent=None
Chris@87 2206 if note:
Chris@87 2207 note=note.replace('\\n\\n', '\n\n')
Chris@87 2208 note=note.replace('\\n ', '\n')
Chris@87 2209 if 'note' not in vars[n]:
Chris@87 2210 vars[n]['note']=[note]
Chris@87 2211 else:
Chris@87 2212 vars[n]['note'].append(note)
Chris@87 2213 note=None
Chris@87 2214 if depend is not None:
Chris@87 2215 if 'depend' not in vars[n]:
Chris@87 2216 vars[n]['depend']=[]
Chris@87 2217 for c in rmbadname([x.strip() for x in markoutercomma(depend).split('@,@')]):
Chris@87 2218 if c not in vars[n]['depend']:
Chris@87 2219 vars[n]['depend'].append(c)
Chris@87 2220 depend=None
Chris@87 2221 if check is not None:
Chris@87 2222 if 'check' not in vars[n]:
Chris@87 2223 vars[n]['check']=[]
Chris@87 2224 for c in [x.strip() for x in markoutercomma(check).split('@,@')]:
Chris@87 2225 if c not in vars[n]['check']:
Chris@87 2226 vars[n]['check'].append(c)
Chris@87 2227 check=None
Chris@87 2228 if dim and 'dimension' not in vars[n]:
Chris@87 2229 vars[n]['dimension']=[]
Chris@87 2230 for d in rmbadname([x.strip() for x in markoutercomma(dim).split('@,@')]):
Chris@87 2231 star = '*'
Chris@87 2232 if d==':':
Chris@87 2233 star=':'
Chris@87 2234 if d in params:
Chris@87 2235 d = str(params[d])
Chris@87 2236 for p in list(params.keys()):
Chris@87 2237 m = re.match(r'(?P<before>.*?)\b'+p+r'\b(?P<after>.*)', d, re.I)
Chris@87 2238 if m:
Chris@87 2239 #outmess('analyzevars:replacing parameter %s in %s (dimension of %s) with %s\n'%(`p`,`d`,`n`,`params[p]`))
Chris@87 2240 d = m.group('before')+str(params[p])+m.group('after')
Chris@87 2241 if d==star:
Chris@87 2242 dl = [star]
Chris@87 2243 else:
Chris@87 2244 dl=markoutercomma(d, ':').split('@:@')
Chris@87 2245 if len(dl)==2 and '*' in dl: # e.g. dimension(5:*)
Chris@87 2246 dl = ['*']
Chris@87 2247 d = '*'
Chris@87 2248 if len(dl)==1 and not dl[0]==star: dl = ['1', dl[0]]
Chris@87 2249 if len(dl)==2:
Chris@87 2250 d, v, di = getarrlen(dl, list(block['vars'].keys()))
Chris@87 2251 if d[:4] == '1 * ': d = d[4:]
Chris@87 2252 if di and di[-4:] == '/(1)': di = di[:-4]
Chris@87 2253 if v: savelindims[d] = v, di
Chris@87 2254 vars[n]['dimension'].append(d)
Chris@87 2255 if 'dimension' in vars[n]:
Chris@87 2256 if isintent_c(vars[n]):
Chris@87 2257 shape_macro = 'shape'
Chris@87 2258 else:
Chris@87 2259 shape_macro = 'shape'#'fshape'
Chris@87 2260 if isstringarray(vars[n]):
Chris@87 2261 if 'charselector' in vars[n]:
Chris@87 2262 d = vars[n]['charselector']
Chris@87 2263 if '*' in d:
Chris@87 2264 d = d['*']
Chris@87 2265 errmess('analyzevars: character array "character*%s %s(%s)" is considered as "character %s(%s)"; "intent(c)" is forced.\n'\
Chris@87 2266 %(d, n,
Chris@87 2267 ','.join(vars[n]['dimension']),
Chris@87 2268 n, ','.join(vars[n]['dimension']+[d])))
Chris@87 2269 vars[n]['dimension'].append(d)
Chris@87 2270 del vars[n]['charselector']
Chris@87 2271 if 'intent' not in vars[n]:
Chris@87 2272 vars[n]['intent'] = []
Chris@87 2273 if 'c' not in vars[n]['intent']:
Chris@87 2274 vars[n]['intent'].append('c')
Chris@87 2275 else:
Chris@87 2276 errmess("analyzevars: charselector=%r unhandled." % (d))
Chris@87 2277 if 'check' not in vars[n] and 'args' in block and n in block['args']:
Chris@87 2278 flag = 'depend' not in vars[n]
Chris@87 2279 if flag:
Chris@87 2280 vars[n]['depend']=[]
Chris@87 2281 vars[n]['check']=[]
Chris@87 2282 if 'dimension' in vars[n]:
Chris@87 2283 #/----< no check
Chris@87 2284 #vars[n]['check'].append('rank(%s)==%s'%(n,len(vars[n]['dimension'])))
Chris@87 2285 i=-1; ni=len(vars[n]['dimension'])
Chris@87 2286 for d in vars[n]['dimension']:
Chris@87 2287 ddeps=[] # dependecies of 'd'
Chris@87 2288 ad=''
Chris@87 2289 pd=''
Chris@87 2290 #origd = d
Chris@87 2291 if d not in vars:
Chris@87 2292 if d in savelindims:
Chris@87 2293 pd, ad='(', savelindims[d][1]
Chris@87 2294 d = savelindims[d][0]
Chris@87 2295 else:
Chris@87 2296 for r in block['args']:
Chris@87 2297 #for r in block['vars'].iterkeys():
Chris@87 2298 if r not in vars:
Chris@87 2299 continue
Chris@87 2300 if re.match(r'.*?\b'+r+r'\b', d, re.I):
Chris@87 2301 ddeps.append(r)
Chris@87 2302 if d in vars:
Chris@87 2303 if 'attrspec' in vars[d]:
Chris@87 2304 for aa in vars[d]['attrspec']:
Chris@87 2305 if aa[:6]=='depend':
Chris@87 2306 ddeps += aa[6:].strip()[1:-1].split(',')
Chris@87 2307 if 'depend' in vars[d]:
Chris@87 2308 ddeps=ddeps+vars[d]['depend']
Chris@87 2309 i=i+1
Chris@87 2310 if d in vars and ('depend' not in vars[d]) \
Chris@87 2311 and ('=' not in vars[d]) and (d not in vars[n]['depend']) \
Chris@87 2312 and l_or(isintent_in, isintent_inout, isintent_inplace)(vars[n]):
Chris@87 2313 vars[d]['depend']=[n]
Chris@87 2314 if ni>1:
Chris@87 2315 vars[d]['=']='%s%s(%s,%s)%s'% (pd, shape_macro, n, i, ad)
Chris@87 2316 else:
Chris@87 2317 vars[d]['=']='%slen(%s)%s'% (pd, n, ad)
Chris@87 2318 # /---< no check
Chris@87 2319 if 1 and 'check' not in vars[d]:
Chris@87 2320 if ni>1:
Chris@87 2321 vars[d]['check']=['%s%s(%s,%i)%s==%s'\
Chris@87 2322 %(pd, shape_macro, n, i, ad, d)]
Chris@87 2323 else:
Chris@87 2324 vars[d]['check']=['%slen(%s)%s>=%s'%(pd, n, ad, d)]
Chris@87 2325 if 'attrspec' not in vars[d]:
Chris@87 2326 vars[d]['attrspec']=['optional']
Chris@87 2327 if ('optional' not in vars[d]['attrspec']) and\
Chris@87 2328 ('required' not in vars[d]['attrspec']):
Chris@87 2329 vars[d]['attrspec'].append('optional')
Chris@87 2330 elif d not in ['*', ':']:
Chris@87 2331 #/----< no check
Chris@87 2332 #if ni>1: vars[n]['check'].append('shape(%s,%i)==%s'%(n,i,d))
Chris@87 2333 #else: vars[n]['check'].append('len(%s)>=%s'%(n,d))
Chris@87 2334 if flag:
Chris@87 2335 if d in vars:
Chris@87 2336 if n not in ddeps:
Chris@87 2337 vars[n]['depend'].append(d)
Chris@87 2338 else:
Chris@87 2339 vars[n]['depend'] = vars[n]['depend'] + ddeps
Chris@87 2340 elif isstring(vars[n]):
Chris@87 2341 length='1'
Chris@87 2342 if 'charselector' in vars[n]:
Chris@87 2343 if '*' in vars[n]['charselector']:
Chris@87 2344 length = _eval_length(vars[n]['charselector']['*'],
Chris@87 2345 params)
Chris@87 2346 vars[n]['charselector']['*']=length
Chris@87 2347 elif 'len' in vars[n]['charselector']:
Chris@87 2348 length = _eval_length(vars[n]['charselector']['len'],
Chris@87 2349 params)
Chris@87 2350 del vars[n]['charselector']['len']
Chris@87 2351 vars[n]['charselector']['*']=length
Chris@87 2352
Chris@87 2353 if not vars[n]['check']:
Chris@87 2354 del vars[n]['check']
Chris@87 2355 if flag and not vars[n]['depend']:
Chris@87 2356 del vars[n]['depend']
Chris@87 2357 if '=' in vars[n]:
Chris@87 2358 if 'attrspec' not in vars[n]:
Chris@87 2359 vars[n]['attrspec']=[]
Chris@87 2360 if ('optional' not in vars[n]['attrspec']) and \
Chris@87 2361 ('required' not in vars[n]['attrspec']):
Chris@87 2362 vars[n]['attrspec'].append('optional')
Chris@87 2363 if 'depend' not in vars[n]:
Chris@87 2364 vars[n]['depend']=[]
Chris@87 2365 for v, m in list(dep_matches.items()):
Chris@87 2366 if m(vars[n]['=']): vars[n]['depend'].append(v)
Chris@87 2367 if not vars[n]['depend']: del vars[n]['depend']
Chris@87 2368 if isscalar(vars[n]):
Chris@87 2369 vars[n]['='] = _eval_scalar(vars[n]['='], params)
Chris@87 2370
Chris@87 2371 for n in list(vars.keys()):
Chris@87 2372 if n==block['name']: # n is block name
Chris@87 2373 if 'note' in vars[n]:
Chris@87 2374 block['note']=vars[n]['note']
Chris@87 2375 if block['block']=='function':
Chris@87 2376 if 'result' in block and block['result'] in vars:
Chris@87 2377 vars[n]=appenddecl(vars[n], vars[block['result']])
Chris@87 2378 if 'prefix' in block:
Chris@87 2379 pr=block['prefix']; ispure=0; isrec=1
Chris@87 2380 pr1=pr.replace('pure', '')
Chris@87 2381 ispure=(not pr==pr1)
Chris@87 2382 pr=pr1.replace('recursive', '')
Chris@87 2383 isrec=(not pr==pr1)
Chris@87 2384 m=typespattern[0].match(pr)
Chris@87 2385 if m:
Chris@87 2386 typespec, selector, attr, edecl=cracktypespec0(m.group('this'), m.group('after'))
Chris@87 2387 kindselect, charselect, typename=cracktypespec(typespec, selector)
Chris@87 2388 vars[n]['typespec']=typespec
Chris@87 2389 if kindselect:
Chris@87 2390 if 'kind' in kindselect:
Chris@87 2391 try:
Chris@87 2392 kindselect['kind'] = eval(kindselect['kind'], {}, params)
Chris@87 2393 except:
Chris@87 2394 pass
Chris@87 2395 vars[n]['kindselector']=kindselect
Chris@87 2396 if charselect: vars[n]['charselector']=charselect
Chris@87 2397 if typename: vars[n]['typename']=typename
Chris@87 2398 if ispure: vars[n]=setattrspec(vars[n], 'pure')
Chris@87 2399 if isrec: vars[n]=setattrspec(vars[n], 'recursive')
Chris@87 2400 else:
Chris@87 2401 outmess('analyzevars: prefix (%s) were not used\n'%repr(block['prefix']))
Chris@87 2402 if not block['block'] in ['module', 'pythonmodule', 'python module', 'block data']:
Chris@87 2403 if 'commonvars' in block:
Chris@87 2404 neededvars=copy.copy(block['args']+block['commonvars'])
Chris@87 2405 else:
Chris@87 2406 neededvars=copy.copy(block['args'])
Chris@87 2407 for n in list(vars.keys()):
Chris@87 2408 if l_or(isintent_callback, isintent_aux)(vars[n]):
Chris@87 2409 neededvars.append(n)
Chris@87 2410 if 'entry' in block:
Chris@87 2411 neededvars.extend(list(block['entry'].keys()))
Chris@87 2412 for k in list(block['entry'].keys()):
Chris@87 2413 for n in block['entry'][k]:
Chris@87 2414 if n not in neededvars:
Chris@87 2415 neededvars.append(n)
Chris@87 2416 if block['block']=='function':
Chris@87 2417 if 'result' in block:
Chris@87 2418 neededvars.append(block['result'])
Chris@87 2419 else:
Chris@87 2420 neededvars.append(block['name'])
Chris@87 2421 if block['block'] in ['subroutine', 'function']:
Chris@87 2422 name = block['name']
Chris@87 2423 if name in vars and 'intent' in vars[name]:
Chris@87 2424 block['intent'] = vars[name]['intent']
Chris@87 2425 if block['block'] == 'type':
Chris@87 2426 neededvars.extend(list(vars.keys()))
Chris@87 2427 for n in list(vars.keys()):
Chris@87 2428 if n not in neededvars:
Chris@87 2429 del vars[n]
Chris@87 2430 return vars
Chris@87 2431
Chris@87 2432 analyzeargs_re_1 = re.compile(r'\A[a-z]+[\w$]*\Z', re.I)
Chris@87 2433 def expr2name(a, block, args=[]):
Chris@87 2434 orig_a = a
Chris@87 2435 a_is_expr = not analyzeargs_re_1.match(a)
Chris@87 2436 if a_is_expr: # `a` is an expression
Chris@87 2437 implicitrules, attrrules=buildimplicitrules(block)
Chris@87 2438 at=determineexprtype(a, block['vars'], implicitrules)
Chris@87 2439 na='e_'
Chris@87 2440 for c in a:
Chris@87 2441 c = c.lower()
Chris@87 2442 if c not in string.ascii_lowercase+string.digits: c='_'
Chris@87 2443 na=na+c
Chris@87 2444 if na[-1]=='_': na=na+'e'
Chris@87 2445 else: na=na+'_e'
Chris@87 2446 a=na
Chris@87 2447 while a in block['vars'] or a in block['args']:
Chris@87 2448 a=a+'r'
Chris@87 2449 if a in args:
Chris@87 2450 k = 1
Chris@87 2451 while a + str(k) in args:
Chris@87 2452 k = k + 1
Chris@87 2453 a = a + str(k)
Chris@87 2454 if a_is_expr:
Chris@87 2455 block['vars'][a]=at
Chris@87 2456 else:
Chris@87 2457 if a not in block['vars']:
Chris@87 2458 if orig_a in block['vars']:
Chris@87 2459 block['vars'][a] = block['vars'][orig_a]
Chris@87 2460 else:
Chris@87 2461 block['vars'][a]={}
Chris@87 2462 if 'externals' in block and orig_a in block['externals']+block['interfaced']:
Chris@87 2463 block['vars'][a]=setattrspec(block['vars'][a], 'external')
Chris@87 2464 return a
Chris@87 2465
Chris@87 2466 def analyzeargs(block):
Chris@87 2467 setmesstext(block)
Chris@87 2468 implicitrules, attrrules=buildimplicitrules(block)
Chris@87 2469 if 'args' not in block:
Chris@87 2470 block['args']=[]
Chris@87 2471 args=[]
Chris@87 2472 for a in block['args']:
Chris@87 2473 a = expr2name(a, block, args)
Chris@87 2474 args.append(a)
Chris@87 2475 block['args']=args
Chris@87 2476 if 'entry' in block:
Chris@87 2477 for k, args1 in list(block['entry'].items()):
Chris@87 2478 for a in args1:
Chris@87 2479 if a not in block['vars']:
Chris@87 2480 block['vars'][a]={}
Chris@87 2481
Chris@87 2482 for b in block['body']:
Chris@87 2483 if b['name'] in args:
Chris@87 2484 if 'externals' not in block:
Chris@87 2485 block['externals']=[]
Chris@87 2486 if b['name'] not in block['externals']:
Chris@87 2487 block['externals'].append(b['name'])
Chris@87 2488 if 'result' in block and block['result'] not in block['vars']:
Chris@87 2489 block['vars'][block['result']]={}
Chris@87 2490 return block
Chris@87 2491
Chris@87 2492 determineexprtype_re_1 = re.compile(r'\A\(.+?[,].+?\)\Z', re.I)
Chris@87 2493 determineexprtype_re_2 = re.compile(r'\A[+-]?\d+(_(P<name>[\w]+)|)\Z', re.I)
Chris@87 2494 determineexprtype_re_3 = re.compile(r'\A[+-]?[\d.]+[\d+-de.]*(_(P<name>[\w]+)|)\Z', re.I)
Chris@87 2495 determineexprtype_re_4 = re.compile(r'\A\(.*\)\Z', re.I)
Chris@87 2496 determineexprtype_re_5 = re.compile(r'\A(?P<name>\w+)\s*\(.*?\)\s*\Z', re.I)
Chris@87 2497 def _ensure_exprdict(r):
Chris@87 2498 if isinstance(r, int):
Chris@87 2499 return {'typespec':'integer'}
Chris@87 2500 if isinstance(r, float):
Chris@87 2501 return {'typespec':'real'}
Chris@87 2502 if isinstance(r, complex):
Chris@87 2503 return {'typespec':'complex'}
Chris@87 2504 if isinstance(r, dict):
Chris@87 2505 return r
Chris@87 2506 raise AssertionError(repr(r))
Chris@87 2507
Chris@87 2508 def determineexprtype(expr,vars,rules={}):
Chris@87 2509 if expr in vars:
Chris@87 2510 return _ensure_exprdict(vars[expr])
Chris@87 2511 expr=expr.strip()
Chris@87 2512 if determineexprtype_re_1.match(expr):
Chris@87 2513 return {'typespec':'complex'}
Chris@87 2514 m=determineexprtype_re_2.match(expr)
Chris@87 2515 if m:
Chris@87 2516 if 'name' in m.groupdict() and m.group('name'):
Chris@87 2517 outmess('determineexprtype: selected kind types not supported (%s)\n'%repr(expr))
Chris@87 2518 return {'typespec':'integer'}
Chris@87 2519 m = determineexprtype_re_3.match(expr)
Chris@87 2520 if m:
Chris@87 2521 if 'name' in m.groupdict() and m.group('name'):
Chris@87 2522 outmess('determineexprtype: selected kind types not supported (%s)\n'%repr(expr))
Chris@87 2523 return {'typespec':'real'}
Chris@87 2524 for op in ['+', '-', '*', '/']:
Chris@87 2525 for e in [x.strip() for x in markoutercomma(expr, comma=op).split('@'+op+'@')]:
Chris@87 2526 if e in vars:
Chris@87 2527 return _ensure_exprdict(vars[e])
Chris@87 2528 t={}
Chris@87 2529 if determineexprtype_re_4.match(expr): # in parenthesis
Chris@87 2530 t=determineexprtype(expr[1:-1], vars, rules)
Chris@87 2531 else:
Chris@87 2532 m = determineexprtype_re_5.match(expr)
Chris@87 2533 if m:
Chris@87 2534 rn=m.group('name')
Chris@87 2535 t=determineexprtype(m.group('name'), vars, rules)
Chris@87 2536 if t and 'attrspec' in t:
Chris@87 2537 del t['attrspec']
Chris@87 2538 if not t:
Chris@87 2539 if rn[0] in rules:
Chris@87 2540 return _ensure_exprdict(rules[rn[0]])
Chris@87 2541 if expr[0] in '\'"':
Chris@87 2542 return {'typespec':'character','charselector':{'*':'*'}}
Chris@87 2543 if not t:
Chris@87 2544 outmess('determineexprtype: could not determine expressions (%s) type.\n'%(repr(expr)))
Chris@87 2545 return t
Chris@87 2546
Chris@87 2547 ######
Chris@87 2548 def crack2fortrangen(block,tab='\n', as_interface=False):
Chris@87 2549 global skipfuncs, onlyfuncs
Chris@87 2550 setmesstext(block)
Chris@87 2551 ret=''
Chris@87 2552 if isinstance(block, list):
Chris@87 2553 for g in block:
Chris@87 2554 if g and g['block'] in ['function', 'subroutine']:
Chris@87 2555 if g['name'] in skipfuncs:
Chris@87 2556 continue
Chris@87 2557 if onlyfuncs and g['name'] not in onlyfuncs:
Chris@87 2558 continue
Chris@87 2559 ret=ret+crack2fortrangen(g, tab, as_interface=as_interface)
Chris@87 2560 return ret
Chris@87 2561 prefix=''
Chris@87 2562 name=''
Chris@87 2563 args=''
Chris@87 2564 blocktype=block['block']
Chris@87 2565 if blocktype=='program': return ''
Chris@87 2566 argsl = []
Chris@87 2567 if 'name' in block:
Chris@87 2568 name=block['name']
Chris@87 2569 if 'args' in block:
Chris@87 2570 vars = block['vars']
Chris@87 2571 for a in block['args']:
Chris@87 2572 a = expr2name(a, block, argsl)
Chris@87 2573 if not isintent_callback(vars[a]):
Chris@87 2574 argsl.append(a)
Chris@87 2575 if block['block']=='function' or argsl:
Chris@87 2576 args='(%s)'%','.join(argsl)
Chris@87 2577 f2pyenhancements = ''
Chris@87 2578 if 'f2pyenhancements' in block:
Chris@87 2579 for k in list(block['f2pyenhancements'].keys()):
Chris@87 2580 f2pyenhancements = '%s%s%s %s'%(f2pyenhancements, tab+tabchar, k, block['f2pyenhancements'][k])
Chris@87 2581 intent_lst = block.get('intent', [])[:]
Chris@87 2582 if blocktype=='function' and 'callback' in intent_lst:
Chris@87 2583 intent_lst.remove('callback')
Chris@87 2584 if intent_lst:
Chris@87 2585 f2pyenhancements = '%s%sintent(%s) %s'%\
Chris@87 2586 (f2pyenhancements, tab+tabchar,
Chris@87 2587 ','.join(intent_lst), name)
Chris@87 2588 use=''
Chris@87 2589 if 'use' in block:
Chris@87 2590 use=use2fortran(block['use'], tab+tabchar)
Chris@87 2591 common=''
Chris@87 2592 if 'common' in block:
Chris@87 2593 common=common2fortran(block['common'], tab+tabchar)
Chris@87 2594 if name=='unknown_interface': name=''
Chris@87 2595 result=''
Chris@87 2596 if 'result' in block:
Chris@87 2597 result=' result (%s)'%block['result']
Chris@87 2598 if block['result'] not in argsl:
Chris@87 2599 argsl.append(block['result'])
Chris@87 2600 #if 'prefix' in block:
Chris@87 2601 # prefix=block['prefix']+' '
Chris@87 2602 body=crack2fortrangen(block['body'], tab+tabchar)
Chris@87 2603 vars=vars2fortran(block, block['vars'], argsl, tab+tabchar, as_interface=as_interface)
Chris@87 2604 mess=''
Chris@87 2605 if 'from' in block and not as_interface:
Chris@87 2606 mess='! in %s'%block['from']
Chris@87 2607 if 'entry' in block:
Chris@87 2608 entry_stmts = ''
Chris@87 2609 for k, i in list(block['entry'].items()):
Chris@87 2610 entry_stmts = '%s%sentry %s(%s)' \
Chris@87 2611 % (entry_stmts, tab+tabchar, k, ','.join(i))
Chris@87 2612 body = body + entry_stmts
Chris@87 2613 if blocktype=='block data' and name=='_BLOCK_DATA_':
Chris@87 2614 name = ''
Chris@87 2615 ret='%s%s%s %s%s%s %s%s%s%s%s%s%send %s %s'%(tab, prefix, blocktype, name, args, result, mess, f2pyenhancements, use, vars, common, body, tab, blocktype, name)
Chris@87 2616 return ret
Chris@87 2617
Chris@87 2618 def common2fortran(common,tab=''):
Chris@87 2619 ret=''
Chris@87 2620 for k in list(common.keys()):
Chris@87 2621 if k=='_BLNK_':
Chris@87 2622 ret='%s%scommon %s'%(ret, tab, ','.join(common[k]))
Chris@87 2623 else:
Chris@87 2624 ret='%s%scommon /%s/ %s'%(ret, tab, k, ','.join(common[k]))
Chris@87 2625 return ret
Chris@87 2626
Chris@87 2627 def use2fortran(use,tab=''):
Chris@87 2628 ret=''
Chris@87 2629 for m in list(use.keys()):
Chris@87 2630 ret='%s%suse %s,'%(ret, tab, m)
Chris@87 2631 if use[m]=={}:
Chris@87 2632 if ret and ret[-1]==',': ret=ret[:-1]
Chris@87 2633 continue
Chris@87 2634 if 'only' in use[m] and use[m]['only']:
Chris@87 2635 ret='%s only:'%(ret)
Chris@87 2636 if 'map' in use[m] and use[m]['map']:
Chris@87 2637 c=' '
Chris@87 2638 for k in list(use[m]['map'].keys()):
Chris@87 2639 if k==use[m]['map'][k]:
Chris@87 2640 ret='%s%s%s'%(ret, c, k); c=','
Chris@87 2641 else:
Chris@87 2642 ret='%s%s%s=>%s'%(ret, c, k, use[m]['map'][k]); c=','
Chris@87 2643 if ret and ret[-1]==',': ret=ret[:-1]
Chris@87 2644 return ret
Chris@87 2645
Chris@87 2646 def true_intent_list(var):
Chris@87 2647 lst = var['intent']
Chris@87 2648 ret = []
Chris@87 2649 for intent in lst:
Chris@87 2650 try:
Chris@87 2651 c = eval('isintent_%s(var)' % intent)
Chris@87 2652 except NameError:
Chris@87 2653 c = 0
Chris@87 2654 if c:
Chris@87 2655 ret.append(intent)
Chris@87 2656 return ret
Chris@87 2657
Chris@87 2658 def vars2fortran(block,vars,args,tab='', as_interface=False):
Chris@87 2659 """
Chris@87 2660 TODO:
Chris@87 2661 public sub
Chris@87 2662 ...
Chris@87 2663 """
Chris@87 2664 setmesstext(block)
Chris@87 2665 ret=''
Chris@87 2666 nout=[]
Chris@87 2667 for a in args:
Chris@87 2668 if a in block['vars']:
Chris@87 2669 nout.append(a)
Chris@87 2670 if 'commonvars' in block:
Chris@87 2671 for a in block['commonvars']:
Chris@87 2672 if a in vars:
Chris@87 2673 if a not in nout:
Chris@87 2674 nout.append(a)
Chris@87 2675 else:
Chris@87 2676 errmess('vars2fortran: Confused?!: "%s" is not defined in vars.\n'%a)
Chris@87 2677 if 'varnames' in block:
Chris@87 2678 nout.extend(block['varnames'])
Chris@87 2679 if not as_interface:
Chris@87 2680 for a in list(vars.keys()):
Chris@87 2681 if a not in nout:
Chris@87 2682 nout.append(a)
Chris@87 2683 for a in nout:
Chris@87 2684 if 'depend' in vars[a]:
Chris@87 2685 for d in vars[a]['depend']:
Chris@87 2686 if d in vars and 'depend' in vars[d] and a in vars[d]['depend']:
Chris@87 2687 errmess('vars2fortran: Warning: cross-dependence between variables "%s" and "%s"\n'%(a, d))
Chris@87 2688 if 'externals' in block and a in block['externals']:
Chris@87 2689 if isintent_callback(vars[a]):
Chris@87 2690 ret='%s%sintent(callback) %s'%(ret, tab, a)
Chris@87 2691 ret='%s%sexternal %s'%(ret, tab, a)
Chris@87 2692 if isoptional(vars[a]):
Chris@87 2693 ret='%s%soptional %s'%(ret, tab, a)
Chris@87 2694 if a in vars and 'typespec' not in vars[a]:
Chris@87 2695 continue
Chris@87 2696 cont=1
Chris@87 2697 for b in block['body']:
Chris@87 2698 if a==b['name'] and b['block']=='function':
Chris@87 2699 cont=0;break
Chris@87 2700 if cont:
Chris@87 2701 continue
Chris@87 2702 if a not in vars:
Chris@87 2703 show(vars)
Chris@87 2704 outmess('vars2fortran: No definition for argument "%s".\n'%a)
Chris@87 2705 continue
Chris@87 2706 if a==block['name'] and not block['block']=='function':
Chris@87 2707 continue
Chris@87 2708 if 'typespec' not in vars[a]:
Chris@87 2709 if 'attrspec' in vars[a] and 'external' in vars[a]['attrspec']:
Chris@87 2710 if a in args:
Chris@87 2711 ret='%s%sexternal %s'%(ret, tab, a)
Chris@87 2712 continue
Chris@87 2713 show(vars[a])
Chris@87 2714 outmess('vars2fortran: No typespec for argument "%s".\n'%a)
Chris@87 2715 continue
Chris@87 2716 vardef=vars[a]['typespec']
Chris@87 2717 if vardef=='type' and 'typename' in vars[a]:
Chris@87 2718 vardef='%s(%s)'%(vardef, vars[a]['typename'])
Chris@87 2719 selector={}
Chris@87 2720 if 'kindselector' in vars[a]:
Chris@87 2721 selector=vars[a]['kindselector']
Chris@87 2722 elif 'charselector' in vars[a]:
Chris@87 2723 selector=vars[a]['charselector']
Chris@87 2724 if '*' in selector:
Chris@87 2725 if selector['*'] in ['*', ':']:
Chris@87 2726 vardef='%s*(%s)'%(vardef, selector['*'])
Chris@87 2727 else:
Chris@87 2728 vardef='%s*%s'%(vardef, selector['*'])
Chris@87 2729 else:
Chris@87 2730 if 'len' in selector:
Chris@87 2731 vardef='%s(len=%s'%(vardef, selector['len'])
Chris@87 2732 if 'kind' in selector:
Chris@87 2733 vardef='%s,kind=%s)'%(vardef, selector['kind'])
Chris@87 2734 else:
Chris@87 2735 vardef='%s)'%(vardef)
Chris@87 2736 elif 'kind' in selector:
Chris@87 2737 vardef='%s(kind=%s)'%(vardef, selector['kind'])
Chris@87 2738 c=' '
Chris@87 2739 if 'attrspec' in vars[a]:
Chris@87 2740 attr=[]
Chris@87 2741 for l in vars[a]['attrspec']:
Chris@87 2742 if l not in ['external']:
Chris@87 2743 attr.append(l)
Chris@87 2744 if attr:
Chris@87 2745 vardef='%s, %s'%(vardef, ','.join(attr))
Chris@87 2746 c=','
Chris@87 2747 if 'dimension' in vars[a]:
Chris@87 2748 # if not isintent_c(vars[a]):
Chris@87 2749 # vars[a]['dimension'].reverse()
Chris@87 2750 vardef='%s%sdimension(%s)'%(vardef, c, ','.join(vars[a]['dimension']))
Chris@87 2751 c=','
Chris@87 2752 if 'intent' in vars[a]:
Chris@87 2753 lst = true_intent_list(vars[a])
Chris@87 2754 if lst:
Chris@87 2755 vardef='%s%sintent(%s)'%(vardef, c, ','.join(lst))
Chris@87 2756 c=','
Chris@87 2757 if 'check' in vars[a]:
Chris@87 2758 vardef='%s%scheck(%s)'%(vardef, c, ','.join(vars[a]['check']))
Chris@87 2759 c=','
Chris@87 2760 if 'depend' in vars[a]:
Chris@87 2761 vardef='%s%sdepend(%s)'%(vardef, c, ','.join(vars[a]['depend']))
Chris@87 2762 c=','
Chris@87 2763 if '=' in vars[a]:
Chris@87 2764 v = vars[a]['=']
Chris@87 2765 if vars[a]['typespec'] in ['complex', 'double complex']:
Chris@87 2766 try:
Chris@87 2767 v = eval(v)
Chris@87 2768 v = '(%s,%s)' % (v.real, v.imag)
Chris@87 2769 except:
Chris@87 2770 pass
Chris@87 2771 vardef='%s :: %s=%s'%(vardef, a, v)
Chris@87 2772 else:
Chris@87 2773 vardef='%s :: %s'%(vardef, a)
Chris@87 2774 ret='%s%s%s'%(ret, tab, vardef)
Chris@87 2775 return ret
Chris@87 2776 ######
Chris@87 2777
Chris@87 2778 def crackfortran(files):
Chris@87 2779 global usermodules
Chris@87 2780 outmess('Reading fortran codes...\n', 0)
Chris@87 2781 readfortrancode(files, crackline)
Chris@87 2782 outmess('Post-processing...\n', 0)
Chris@87 2783 usermodules=[]
Chris@87 2784 postlist=postcrack(grouplist[0])
Chris@87 2785 outmess('Post-processing (stage 2)...\n', 0)
Chris@87 2786 postlist=postcrack2(postlist)
Chris@87 2787 return usermodules+postlist
Chris@87 2788
Chris@87 2789 def crack2fortran(block):
Chris@87 2790 global f2py_version
Chris@87 2791 pyf=crack2fortrangen(block)+'\n'
Chris@87 2792 header="""! -*- f90 -*-
Chris@87 2793 ! Note: the context of this file is case sensitive.
Chris@87 2794 """
Chris@87 2795 footer="""
Chris@87 2796 ! This file was auto-generated with f2py (version:%s).
Chris@87 2797 ! See http://cens.ioc.ee/projects/f2py2e/
Chris@87 2798 """%(f2py_version)
Chris@87 2799 return header+pyf+footer
Chris@87 2800
Chris@87 2801 if __name__ == "__main__":
Chris@87 2802 files=[]
Chris@87 2803 funcs=[]
Chris@87 2804 f=1;f2=0;f3=0
Chris@87 2805 showblocklist=0
Chris@87 2806 for l in sys.argv[1:]:
Chris@87 2807 if l=='': pass
Chris@87 2808 elif l[0]==':':
Chris@87 2809 f=0
Chris@87 2810 elif l=='-quiet':
Chris@87 2811 quiet=1
Chris@87 2812 verbose=0
Chris@87 2813 elif l=='-verbose':
Chris@87 2814 verbose=2
Chris@87 2815 quiet=0
Chris@87 2816 elif l=='-fix':
Chris@87 2817 if strictf77:
Chris@87 2818 outmess('Use option -f90 before -fix if Fortran 90 code is in fix form.\n', 0)
Chris@87 2819 skipemptyends=1
Chris@87 2820 sourcecodeform='fix'
Chris@87 2821 elif l=='-skipemptyends':
Chris@87 2822 skipemptyends=1
Chris@87 2823 elif l=='--ignore-contains':
Chris@87 2824 ignorecontains=1
Chris@87 2825 elif l=='-f77':
Chris@87 2826 strictf77=1
Chris@87 2827 sourcecodeform='fix'
Chris@87 2828 elif l=='-f90':
Chris@87 2829 strictf77=0
Chris@87 2830 sourcecodeform='free'
Chris@87 2831 skipemptyends=1
Chris@87 2832 elif l=='-h':
Chris@87 2833 f2=1
Chris@87 2834 elif l=='-show':
Chris@87 2835 showblocklist=1
Chris@87 2836 elif l=='-m':
Chris@87 2837 f3=1
Chris@87 2838 elif l[0]=='-':
Chris@87 2839 errmess('Unknown option %s\n'%repr(l))
Chris@87 2840 elif f2:
Chris@87 2841 f2=0
Chris@87 2842 pyffilename=l
Chris@87 2843 elif f3:
Chris@87 2844 f3=0
Chris@87 2845 f77modulename=l
Chris@87 2846 elif f:
Chris@87 2847 try:
Chris@87 2848 open(l).close()
Chris@87 2849 files.append(l)
Chris@87 2850 except IOError as detail:
Chris@87 2851 errmess('IOError: %s\n'%str(detail))
Chris@87 2852 else:
Chris@87 2853 funcs.append(l)
Chris@87 2854 if not strictf77 and f77modulename and not skipemptyends:
Chris@87 2855 outmess("""\
Chris@87 2856 Warning: You have specifyied module name for non Fortran 77 code
Chris@87 2857 that should not need one (expect if you are scanning F90 code
Chris@87 2858 for non module blocks but then you should use flag -skipemptyends
Chris@87 2859 and also be sure that the files do not contain programs without program statement).
Chris@87 2860 """, 0)
Chris@87 2861
Chris@87 2862 postlist=crackfortran(files, funcs)
Chris@87 2863 if pyffilename:
Chris@87 2864 outmess('Writing fortran code to file %s\n'%repr(pyffilename), 0)
Chris@87 2865 pyf=crack2fortran(postlist)
Chris@87 2866 f=open(pyffilename, 'w')
Chris@87 2867 f.write(pyf)
Chris@87 2868 f.close()
Chris@87 2869 if showblocklist:
Chris@87 2870 show(postlist)