PageRenderTime 70ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/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

Large files files are truncated, but you can click here to view the full file

  1. #!/usr/bin/env python
  2. """
  3. crackfortran --- read fortran (77,90) code and extract declaration information.
  4. Usage is explained in the comment block below.
  5. Copyright 1999-2004 Pearu Peterson all rights reserved,
  6. Pearu Peterson <pearu@ioc.ee>
  7. Permission to use, modify, and distribute this software is given under the
  8. terms of the NumPy License.
  9. NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
  10. $Date: 2005/09/27 07:13:49 $
  11. Pearu Peterson
  12. """
  13. __version__ = "$Revision: 1.177 $"[10:-1]
  14. import 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]

Large files files are truncated, but you can click here to view the full file