PageRenderTime 66ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/third_party/numpy/files/numpy/f2py/crackfortran.py

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