PageRenderTime 34ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/numpy/f2py/crackfortran.py

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