comparison DEPENDENCIES/mingw32/Python27/Lib/site-packages/numpy/f2py/crackfortran.py @ 87:2a2c65a20a8b

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