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

Add Python libs and headers
author Chris Cannam
date Wed, 25 Feb 2015 14:05:22 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DEPENDENCIES/mingw32/Python27/Lib/site-packages/numpy/f2py/crackfortran.py	Wed Feb 25 14:05:22 2015 +0000
@@ -0,0 +1,2870 @@
+#!/usr/bin/env python
+"""
+crackfortran --- read fortran (77,90) code and extract declaration information.
+
+Copyright 1999-2004 Pearu Peterson all rights reserved,
+Pearu Peterson <pearu@ioc.ee>
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED.  USE AT YOUR OWN RISK.
+$Date: 2005/09/27 07:13:49 $
+Pearu Peterson
+
+
+Usage of crackfortran:
+======================
+Command line keys: -quiet,-verbose,-fix,-f77,-f90,-show,-h <pyffilename>
+                   -m <module name for f77 routines>,--ignore-contains
+Functions: crackfortran, crack2fortran
+The following Fortran statements/constructions are supported
+(or will be if needed):
+   block data,byte,call,character,common,complex,contains,data,
+   dimension,double complex,double precision,end,external,function,
+   implicit,integer,intent,interface,intrinsic,
+   logical,module,optional,parameter,private,public,
+   program,real,(sequence?),subroutine,type,use,virtual,
+   include,pythonmodule
+Note: 'virtual' is mapped to 'dimension'.
+Note: 'implicit integer (z) static (z)' is 'implicit static (z)' (this is minor bug).
+Note: code after 'contains' will be ignored until its scope ends.
+Note: 'common' statement is extended: dimensions are moved to variable definitions
+Note: f2py directive: <commentchar>f2py<line> is read as <line>
+Note: pythonmodule is introduced to represent Python module
+
+Usage:
+  `postlist=crackfortran(files,funcs)`
+  `postlist` contains declaration information read from the list of files `files`.
+  `crack2fortran(postlist)` returns a fortran code to be saved to pyf-file
+
+  `postlist` has the following structure:
+ *** it is a list of dictionaries containing `blocks':
+     B = {'block','body','vars','parent_block'[,'name','prefix','args','result',
+          'implicit','externals','interfaced','common','sortvars',
+          'commonvars','note']}
+     B['block'] = 'interface' | 'function' | 'subroutine' | 'module' |
+                  'program' | 'block data' | 'type' | 'pythonmodule'
+     B['body'] --- list containing `subblocks' with the same structure as `blocks'
+     B['parent_block'] --- dictionary of a parent block:
+                             C['body'][<index>]['parent_block'] is C
+     B['vars'] --- dictionary of variable definitions
+     B['sortvars'] --- dictionary of variable definitions sorted by dependence (independent first)
+     B['name'] --- name of the block (not if B['block']=='interface')
+     B['prefix'] --- prefix string (only if B['block']=='function')
+     B['args'] --- list of argument names if B['block']== 'function' | 'subroutine'
+     B['result'] --- name of the return value (only if B['block']=='function')
+     B['implicit'] --- dictionary {'a':<variable definition>,'b':...} | None
+     B['externals'] --- list of variables being external
+     B['interfaced'] --- list of variables being external and defined
+     B['common'] --- dictionary of common blocks (list of objects)
+     B['commonvars'] --- list of variables used in common blocks (dimensions are moved to variable definitions)
+     B['from'] --- string showing the 'parents' of the current block
+     B['use'] --- dictionary of modules used in current block:
+         {<modulename>:{['only':<0|1>],['map':{<local_name1>:<use_name1>,...}]}}
+     B['note'] --- list of LaTeX comments on the block
+     B['f2pyenhancements'] --- optional dictionary
+          {'threadsafe':'','fortranname':<name>,
+           'callstatement':<C-expr>|<multi-line block>,
+           'callprotoargument':<C-expr-list>,
+           'usercode':<multi-line block>|<list of multi-line blocks>,
+           'pymethoddef:<multi-line block>'
+           }
+     B['entry'] --- dictionary {entryname:argslist,..}
+     B['varnames'] --- list of variable names given in the order of reading the
+                       Fortran code, useful for derived types.
+     B['saved_interface'] --- a string of scanned routine signature, defines explicit interface
+ *** Variable definition is a dictionary
+     D = B['vars'][<variable name>] =
+     {'typespec'[,'attrspec','kindselector','charselector','=','typename']}
+     D['typespec'] = 'byte' | 'character' | 'complex' | 'double complex' |
+                     'double precision' | 'integer' | 'logical' | 'real' | 'type'
+     D['attrspec'] --- list of attributes (e.g. 'dimension(<arrayspec>)',
+                       'external','intent(in|out|inout|hide|c|callback|cache|aligned4|aligned8|aligned16)',
+                       'optional','required', etc)
+     K = D['kindselector'] = {['*','kind']} (only if D['typespec'] =
+                         'complex' | 'integer' | 'logical' | 'real' )
+     C = D['charselector'] = {['*','len','kind']}
+                             (only if D['typespec']=='character')
+     D['='] --- initialization expression string
+     D['typename'] --- name of the type if D['typespec']=='type'
+     D['dimension'] --- list of dimension bounds
+     D['intent'] --- list of intent specifications
+     D['depend'] --- list of variable names on which current variable depends on
+     D['check'] --- list of C-expressions; if C-expr returns zero, exception is raised
+     D['note'] --- list of LaTeX comments on the variable
+ *** Meaning of kind/char selectors (few examples):
+     D['typespec>']*K['*']
+     D['typespec'](kind=K['kind'])
+     character*C['*']
+     character(len=C['len'],kind=C['kind'])
+     (see also fortran type declaration statement formats below)
+
+Fortran 90 type declaration statement format (F77 is subset of F90)
+====================================================================
+(Main source: IBM XL Fortran 5.1 Language Reference Manual)
+type declaration = <typespec> [[<attrspec>]::] <entitydecl>
+<typespec> = byte                          |
+             character[<charselector>]     |
+             complex[<kindselector>]       |
+             double complex                |
+             double precision              |
+             integer[<kindselector>]       |
+             logical[<kindselector>]       |
+             real[<kindselector>]          |
+             type(<typename>)
+<charselector> = * <charlen>               |
+             ([len=]<len>[,[kind=]<kind>]) |
+             (kind=<kind>[,len=<len>])
+<kindselector> = * <intlen>                |
+             ([kind=]<kind>)
+<attrspec> = comma separated list of attributes.
+             Only the following attributes are used in
+             building up the interface:
+                external
+                (parameter --- affects '=' key)
+                optional
+                intent
+             Other attributes are ignored.
+<intentspec> = in | out | inout
+<arrayspec> = comma separated list of dimension bounds.
+<entitydecl> = <name> [[*<charlen>][(<arrayspec>)] | [(<arrayspec>)]*<charlen>]
+                      [/<init_expr>/ | =<init_expr>] [,<entitydecl>]
+
+In addition, the following attributes are used: check,depend,note
+
+TODO:
+    * Apply 'parameter' attribute (e.g. 'integer parameter :: i=2' 'real x(i)'
+                                   -> 'real x(2)')
+    The above may be solved by creating appropriate preprocessor program, for example.
+
+"""
+from __future__ import division, absolute_import, print_function
+
+import sys
+import string
+import fileinput
+import re
+import pprint
+import os
+import copy
+import platform
+
+from . import __version__
+from .auxfuncs import *
+
+f2py_version = __version__.version
+
+# Global flags:
+strictf77=1          # Ignore `!' comments unless line[0]=='!'
+sourcecodeform='fix' # 'fix','free'
+quiet=0              # Be verbose if 0 (Obsolete: not used any more)
+verbose=1            # Be quiet if 0, extra verbose if > 1.
+tabchar=4*' '
+pyffilename=''
+f77modulename=''
+skipemptyends=0      # for old F77 programs without 'program' statement
+ignorecontains=1
+dolowercase=1
+debug=[]
+
+# Global variables
+groupcounter=0
+grouplist={groupcounter:[]}
+neededmodule=-1
+expectbegin=1
+skipblocksuntil=-1
+usermodules=[]
+f90modulevars={}
+gotnextfile=1
+filepositiontext=''
+currentfilename=''
+skipfunctions=[]
+skipfuncs=[]
+onlyfuncs=[]
+include_paths=[]
+previous_context = None
+
+
+def reset_global_f2py_vars():
+    global groupcounter, grouplist, neededmodule, expectbegin, \
+        skipblocksuntil, usermodules, f90modulevars, gotnextfile, \
+        filepositiontext, currentfilename, skipfunctions, skipfuncs, \
+        onlyfuncs, include_paths, previous_context, \
+        strictf77, sourcecodeform, quiet, verbose, tabchar, pyffilename, \
+        f77modulename, skipemptyends, ignorecontains, dolowercase, debug
+
+    # flags
+    strictf77 = 1
+    sourcecodeform = 'fix'
+    quiet = 0
+    verbose = 1
+    tabchar = 4*' '
+    pyffilename = ''
+    f77modulename = ''
+    skipemptyends = 0
+    ignorecontains = 1
+    dolowercase = 1
+    debug = []
+    # variables
+    groupcounter = 0
+    grouplist = {groupcounter:[]}
+    neededmodule =-1
+    expectbegin = 1
+    skipblocksuntil = -1
+    usermodules = []
+    f90modulevars = {}
+    gotnextfile = 1
+    filepositiontext = ''
+    currentfilename = ''
+    skipfunctions = []
+    skipfuncs = []
+    onlyfuncs = []
+    include_paths = []
+    previous_context = None
+
+
+###### Some helper functions
+def show(o,f=0):pprint.pprint(o)
+errmess=sys.stderr.write
+def outmess(line,flag=1):
+    global filepositiontext
+    if not verbose: return
+    if not quiet:
+        if flag:sys.stdout.write(filepositiontext)
+        sys.stdout.write(line)
+re._MAXCACHE=50
+defaultimplicitrules={}
+for c in "abcdefghopqrstuvwxyz$_": defaultimplicitrules[c]={'typespec':'real'}
+for c in "ijklmn": defaultimplicitrules[c]={'typespec':'integer'}
+del c
+badnames={}
+invbadnames={}
+for n in ['int', 'double', 'float', 'char', 'short', 'long', 'void', 'case', 'while',
+          'return', 'signed', 'unsigned', 'if', 'for', 'typedef', 'sizeof', 'union',
+          'struct', 'static', 'register', 'new', 'break', 'do', 'goto', 'switch',
+          'continue', 'else', 'inline', 'extern', 'delete', 'const', 'auto',
+          'len', 'rank', 'shape', 'index', 'slen', 'size', '_i',
+          'max', 'min',
+          'flen', 'fshape',
+          'string', 'complex_double', 'float_double', 'stdin', 'stderr', 'stdout',
+          'type', 'default']:
+    badnames[n]=n+'_bn'
+    invbadnames[n+'_bn']=n
+
+def rmbadname1(name):
+    if name in badnames:
+        errmess('rmbadname1: Replacing "%s" with "%s".\n'%(name, badnames[name]))
+        return badnames[name]
+    return name
+
+def rmbadname(names): return [rmbadname1(_m) for _m in names]
+
+def undo_rmbadname1(name):
+    if name in invbadnames:
+        errmess('undo_rmbadname1: Replacing "%s" with "%s".\n'\
+                %(name, invbadnames[name]))
+        return invbadnames[name]
+    return name
+
+def undo_rmbadname(names): return [undo_rmbadname1(_m) for _m in names]
+
+def getextension(name):
+    i=name.rfind('.')
+    if i==-1: return ''
+    if '\\' in name[i:]: return ''
+    if '/' in name[i:]: return ''
+    return name[i+1:]
+
+is_f_file = re.compile(r'.*[.](for|ftn|f77|f)\Z', re.I).match
+_has_f_header = re.compile(r'-[*]-\s*fortran\s*-[*]-', re.I).search
+_has_f90_header = re.compile(r'-[*]-\s*f90\s*-[*]-', re.I).search
+_has_fix_header = re.compile(r'-[*]-\s*fix\s*-[*]-', re.I).search
+_free_f90_start = re.compile(r'[^c*]\s*[^\s\d\t]', re.I).match
+def is_free_format(file):
+    """Check if file is in free format Fortran."""
+    # f90 allows both fixed and free format, assuming fixed unless
+    # signs of free format are detected.
+    result = 0
+    f = open(file, 'r')
+    line = f.readline()
+    n = 15 # the number of non-comment lines to scan for hints
+    if _has_f_header(line):
+        n = 0
+    elif _has_f90_header(line):
+        n = 0
+        result = 1
+    while n>0 and line:
+        if line[0]!='!' and line.strip():
+            n -= 1
+            if (line[0]!='\t' and _free_f90_start(line[:5])) or line[-2:-1]=='&':
+                result = 1
+                break
+        line = f.readline()
+    f.close()
+    return result
+
+
+####### Read fortran (77,90) code
+def readfortrancode(ffile,dowithline=show,istop=1):
+    """
+    Read fortran codes from files and
+     1) Get rid of comments, line continuations, and empty lines; lower cases.
+     2) Call dowithline(line) on every line.
+     3) Recursively call itself when statement \"include '<filename>'\" is met.
+    """
+    global gotnextfile, filepositiontext, currentfilename, sourcecodeform, strictf77,\
+           beginpattern, quiet, verbose, dolowercase, include_paths
+    if not istop:
+        saveglobals=gotnextfile, filepositiontext, currentfilename, sourcecodeform, strictf77,\
+           beginpattern, quiet, verbose, dolowercase
+    if ffile==[]: return
+    localdolowercase = dolowercase
+    cont=0
+    finalline=''
+    ll=''
+    commentline=re.compile(r'(?P<line>([^"]*["][^"]*["][^"!]*|[^\']*\'[^\']*\'[^\'!]*|[^!\'"]*))!{1}(?P<rest>.*)')
+    includeline=re.compile(r'\s*include\s*(\'|")(?P<name>[^\'"]*)(\'|")', re.I)
+    cont1=re.compile(r'(?P<line>.*)&\s*\Z')
+    cont2=re.compile(r'(\s*&|)(?P<line>.*)')
+    mline_mark = re.compile(r".*?'''")
+    if istop: dowithline('', -1)
+    ll, l1='', ''
+    spacedigits=[' '] + [str(_m) for _m in range(10)]
+    filepositiontext=''
+    fin=fileinput.FileInput(ffile)
+    while True:
+        l=fin.readline()
+        if not l: break
+        if fin.isfirstline():
+            filepositiontext=''
+            currentfilename=fin.filename()
+            gotnextfile=1
+            l1=l
+            strictf77=0
+            sourcecodeform='fix'
+            ext = os.path.splitext(currentfilename)[1]
+            if is_f_file(currentfilename) and \
+                   not (_has_f90_header(l) or _has_fix_header(l)):
+                strictf77=1
+            elif is_free_format(currentfilename) and not _has_fix_header(l):
+                sourcecodeform='free'
+            if strictf77: beginpattern=beginpattern77
+            else: beginpattern=beginpattern90
+            outmess('\tReading file %s (format:%s%s)\n'\
+                    %(repr(currentfilename), sourcecodeform,
+                      strictf77 and ',strict' or ''))
+
+        l=l.expandtabs().replace('\xa0', ' ')
+        while not l=='':                       # Get rid of newline characters
+            if l[-1] not in "\n\r\f": break
+            l=l[:-1]
+        if not strictf77:
+            r=commentline.match(l)
+            if r:
+                l=r.group('line')+' ' # Strip comments starting with `!'
+                rl=r.group('rest')
+                if rl[:4].lower()=='f2py': # f2py directive
+                    l = l + 4*' '
+                    r=commentline.match(rl[4:])
+                    if r: l=l+r.group('line')
+                    else: l = l + rl[4:]
+        if l.strip()=='': # Skip empty line
+            cont=0
+            continue
+        if sourcecodeform=='fix':
+            if l[0] in ['*', 'c', '!', 'C', '#']:
+                if l[1:5].lower()=='f2py': # f2py directive
+                    l='     '+l[5:]
+                else: # Skip comment line
+                    cont=0
+                    continue
+            elif strictf77:
+                if len(l)>72: l=l[:72]
+            if not (l[0] in spacedigits):
+                raise Exception('readfortrancode: Found non-(space,digit) char '
+                                'in the first column.\n\tAre you sure that '
+                                'this code is in fix form?\n\tline=%s' % repr(l))
+
+            if (not cont or strictf77) and (len(l)>5 and not l[5]==' '):
+                # Continuation of a previous line
+                ll=ll+l[6:]
+                finalline=''
+                origfinalline=''
+            else:
+                if not strictf77:
+                    # F90 continuation
+                    r=cont1.match(l)
+                    if r: l=r.group('line') # Continuation follows ..
+                    if cont:
+                        ll=ll+cont2.match(l).group('line')
+                        finalline=''
+                        origfinalline=''
+                    else:
+                        l='     '+l[5:] # clean up line beginning from possible digits.
+                        if localdolowercase: finalline=ll.lower()
+                        else: finalline=ll
+                        origfinalline=ll
+                        ll=l
+                    cont=(r is not None)
+                else:
+                    l='     '+l[5:] # clean up line beginning from possible digits.
+                    if localdolowercase: finalline=ll.lower()
+                    else: finalline=ll
+                    origfinalline =ll
+                    ll=l
+
+        elif sourcecodeform=='free':
+            if not cont and ext=='.pyf' and mline_mark.match(l):
+                l = l + '\n'
+                while True:
+                    lc = fin.readline()
+                    if not lc:
+                        errmess('Unexpected end of file when reading multiline\n')
+                        break
+                    l = l + lc
+                    if mline_mark.match(lc):
+                        break
+                l = l.rstrip()
+            r=cont1.match(l)
+            if r: l=r.group('line') # Continuation follows ..
+            if cont:
+                ll=ll+cont2.match(l).group('line')
+                finalline=''
+                origfinalline=''
+            else:
+                if localdolowercase: finalline=ll.lower()
+                else: finalline=ll
+                origfinalline =ll
+                ll=l
+            cont=(r is not None)
+        else:
+            raise ValueError("Flag sourcecodeform must be either 'fix' or 'free': %s"%repr(sourcecodeform))
+        filepositiontext='Line #%d in %s:"%s"\n\t' % (fin.filelineno()-1, currentfilename, l1)
+        m=includeline.match(origfinalline)
+        if m:
+            fn=m.group('name')
+            if os.path.isfile(fn):
+                readfortrancode(fn, dowithline=dowithline, istop=0)
+            else:
+                include_dirs = [os.path.dirname(currentfilename)] + include_paths
+                foundfile = 0
+                for inc_dir in include_dirs:
+                    fn1 = os.path.join(inc_dir, fn)
+                    if os.path.isfile(fn1):
+                        foundfile = 1
+                        readfortrancode(fn1, dowithline=dowithline, istop=0)
+                        break
+                if not foundfile:
+                    outmess('readfortrancode: could not find include file %s in %s. Ignoring.\n'%(repr(fn), os.pathsep.join(include_dirs)))
+        else:
+            dowithline(finalline)
+        l1=ll
+    if localdolowercase:
+        finalline=ll.lower()
+    else: finalline=ll
+    origfinalline = ll
+    filepositiontext='Line #%d in %s:"%s"\n\t' % (fin.filelineno()-1, currentfilename, l1)
+    m=includeline.match(origfinalline)
+    if m:
+        fn=m.group('name')
+        if os.path.isfile(fn):
+            readfortrancode(fn, dowithline=dowithline, istop=0)
+        else:
+            include_dirs = [os.path.dirname(currentfilename)] + include_paths
+            foundfile = 0
+            for inc_dir in include_dirs:
+                fn1 = os.path.join(inc_dir, fn)
+                if os.path.isfile(fn1):
+                    foundfile = 1
+                    readfortrancode(fn1, dowithline=dowithline, istop=0)
+                    break
+            if not foundfile:
+                outmess('readfortrancode: could not find include file %s in %s. Ignoring.\n'%(repr(fn), os.pathsep.join(include_dirs)))
+    else:
+        dowithline(finalline)
+    filepositiontext=''
+    fin.close()
+    if istop: dowithline('', 1)
+    else:
+        gotnextfile, filepositiontext, currentfilename, sourcecodeform, strictf77,\
+           beginpattern, quiet, verbose, dolowercase=saveglobals
+
+########### Crack line
+beforethisafter=r'\s*(?P<before>%s(?=\s*(\b(%s)\b)))'+ \
+                          r'\s*(?P<this>(\b(%s)\b))'+ \
+                          r'\s*(?P<after>%s)\s*\Z'
+##
+fortrantypes='character|logical|integer|real|complex|double\s*(precision\s*(complex|)|complex)|type(?=\s*\([\w\s,=(*)]*\))|byte'
+typespattern=re.compile(beforethisafter%('', fortrantypes, fortrantypes, '.*'), re.I), 'type'
+typespattern4implicit=re.compile(beforethisafter%('', fortrantypes+'|static|automatic|undefined', fortrantypes+'|static|automatic|undefined', '.*'), re.I)
+#
+functionpattern=re.compile(beforethisafter%('([a-z]+[\w\s(=*+-/)]*?|)', 'function', 'function', '.*'), re.I), 'begin'
+subroutinepattern=re.compile(beforethisafter%('[a-z\s]*?', 'subroutine', 'subroutine', '.*'), re.I), 'begin'
+#modulepattern=re.compile(beforethisafter%('[a-z\s]*?','module','module','.*'),re.I),'begin'
+#
+groupbegins77=r'program|block\s*data'
+beginpattern77=re.compile(beforethisafter%('', groupbegins77, groupbegins77, '.*'), re.I), 'begin'
+groupbegins90=groupbegins77+r'|module(?!\s*procedure)|python\s*module|interface|type(?!\s*\()'
+beginpattern90=re.compile(beforethisafter%('', groupbegins90, groupbegins90, '.*'), re.I), 'begin'
+groupends=r'end|endprogram|endblockdata|endmodule|endpythonmodule|endinterface'
+endpattern=re.compile(beforethisafter%('', groupends, groupends, '[\w\s]*'), re.I), 'end'
+#endifs='end\s*(if|do|where|select|while|forall)'
+endifs='(end\s*(if|do|where|select|while|forall))|(module\s*procedure)'
+endifpattern=re.compile(beforethisafter%('[\w]*?', endifs, endifs, '[\w\s]*'), re.I), 'endif'
+#
+implicitpattern=re.compile(beforethisafter%('', 'implicit', 'implicit', '.*'), re.I), 'implicit'
+dimensionpattern=re.compile(beforethisafter%('', 'dimension|virtual', 'dimension|virtual', '.*'), re.I), 'dimension'
+externalpattern=re.compile(beforethisafter%('', 'external', 'external', '.*'), re.I), 'external'
+optionalpattern=re.compile(beforethisafter%('', 'optional', 'optional', '.*'), re.I), 'optional'
+requiredpattern=re.compile(beforethisafter%('', 'required', 'required', '.*'), re.I), 'required'
+publicpattern=re.compile(beforethisafter%('', 'public', 'public', '.*'), re.I), 'public'
+privatepattern=re.compile(beforethisafter%('', 'private', 'private', '.*'), re.I), 'private'
+intrisicpattern=re.compile(beforethisafter%('', 'intrisic', 'intrisic', '.*'), re.I), 'intrisic'
+intentpattern=re.compile(beforethisafter%('', 'intent|depend|note|check', 'intent|depend|note|check', '\s*\(.*?\).*'), re.I), 'intent'
+parameterpattern=re.compile(beforethisafter%('', 'parameter', 'parameter', '\s*\(.*'), re.I), 'parameter'
+datapattern=re.compile(beforethisafter%('', 'data', 'data', '.*'), re.I), 'data'
+callpattern=re.compile(beforethisafter%('', 'call', 'call', '.*'), re.I), 'call'
+entrypattern=re.compile(beforethisafter%('', 'entry', 'entry', '.*'), re.I), 'entry'
+callfunpattern=re.compile(beforethisafter%('', 'callfun', 'callfun', '.*'), re.I), 'callfun'
+commonpattern=re.compile(beforethisafter%('', 'common', 'common', '.*'), re.I), 'common'
+usepattern=re.compile(beforethisafter%('', 'use', 'use', '.*'), re.I), 'use'
+containspattern=re.compile(beforethisafter%('', 'contains', 'contains', ''), re.I), 'contains'
+formatpattern=re.compile(beforethisafter%('', 'format', 'format', '.*'), re.I), 'format'
+## Non-fortran and f2py-specific statements
+f2pyenhancementspattern=re.compile(beforethisafter%('', 'threadsafe|fortranname|callstatement|callprotoargument|usercode|pymethoddef', 'threadsafe|fortranname|callstatement|callprotoargument|usercode|pymethoddef', '.*'), re.I|re.S), 'f2pyenhancements'
+multilinepattern = re.compile(r"\s*(?P<before>''')(?P<this>.*?)(?P<after>''')\s*\Z", re.S), 'multiline'
+##
+
+def _simplifyargs(argsline):
+    a = []
+    for n in markoutercomma(argsline).split('@,@'):
+        for r in '(),':
+            n = n.replace(r, '_')
+        a.append(n)
+    return ','.join(a)
+
+crackline_re_1 = re.compile(r'\s*(?P<result>\b[a-z]+[\w]*\b)\s*[=].*', re.I)
+def crackline(line,reset=0):
+    """
+    reset=-1  --- initialize
+    reset=0   --- crack the line
+    reset=1   --- final check if mismatch of blocks occured
+
+    Cracked data is saved in grouplist[0].
+    """
+    global beginpattern, groupcounter, groupname, groupcache, grouplist, gotnextfile,\
+           filepositiontext, currentfilename, neededmodule, expectbegin, skipblocksuntil,\
+           skipemptyends, previous_context
+    if ';' in line and not (f2pyenhancementspattern[0].match(line) or
+                            multilinepattern[0].match(line)):
+        for l in line.split(';'):
+            assert reset==0, repr(reset) # XXX: non-zero reset values need testing
+            crackline(l, reset)
+        return
+    if reset<0:
+        groupcounter=0
+        groupname={groupcounter:''}
+        groupcache={groupcounter:{}}
+        grouplist={groupcounter:[]}
+        groupcache[groupcounter]['body']=[]
+        groupcache[groupcounter]['vars']={}
+        groupcache[groupcounter]['block']=''
+        groupcache[groupcounter]['name']=''
+        neededmodule=-1
+        skipblocksuntil=-1
+        return
+    if reset>0:
+        fl=0
+        if f77modulename and neededmodule==groupcounter: fl=2
+        while groupcounter>fl:
+            outmess('crackline: groupcounter=%s groupname=%s\n'%(repr(groupcounter), repr(groupname)))
+            outmess('crackline: Mismatch of blocks encountered. Trying to fix it by assuming "end" statement.\n')
+            grouplist[groupcounter-1].append(groupcache[groupcounter])
+            grouplist[groupcounter-1][-1]['body']=grouplist[groupcounter]
+            del grouplist[groupcounter]
+            groupcounter=groupcounter-1
+        if f77modulename and neededmodule==groupcounter:
+            grouplist[groupcounter-1].append(groupcache[groupcounter])
+            grouplist[groupcounter-1][-1]['body']=grouplist[groupcounter]
+            del grouplist[groupcounter]
+            groupcounter=groupcounter-1 # end interface
+            grouplist[groupcounter-1].append(groupcache[groupcounter])
+            grouplist[groupcounter-1][-1]['body']=grouplist[groupcounter]
+            del grouplist[groupcounter]
+            groupcounter=groupcounter-1 # end module
+            neededmodule=-1
+        return
+    if line=='': return
+    flag=0
+    for pat in [dimensionpattern, externalpattern, intentpattern, optionalpattern,
+                requiredpattern,
+                parameterpattern, datapattern, publicpattern, privatepattern,
+                intrisicpattern,
+                endifpattern, endpattern,
+                formatpattern,
+                beginpattern, functionpattern, subroutinepattern,
+                implicitpattern, typespattern, commonpattern,
+                callpattern, usepattern, containspattern,
+                entrypattern,
+                f2pyenhancementspattern,
+                multilinepattern
+                ]:
+        m = pat[0].match(line)
+        if m:
+            break
+        flag=flag+1
+    if not m:
+        re_1 = crackline_re_1
+        if 0<=skipblocksuntil<=groupcounter:return
+        if 'externals' in groupcache[groupcounter]:
+            for name in groupcache[groupcounter]['externals']:
+                if name in invbadnames:
+                    name=invbadnames[name]
+                if 'interfaced' in groupcache[groupcounter] and name in groupcache[groupcounter]['interfaced']:
+                    continue
+                m1=re.match(r'(?P<before>[^"]*)\b%s\b\s*@\(@(?P<args>[^@]*)@\)@.*\Z'%name, markouterparen(line), re.I)
+                if m1:
+                    m2 = re_1.match(m1.group('before'))
+                    a = _simplifyargs(m1.group('args'))
+                    if m2:
+                        line='callfun %s(%s) result (%s)'%(name, a, m2.group('result'))
+                    else: line='callfun %s(%s)'%(name, a)
+                    m = callfunpattern[0].match(line)
+                    if not m:
+                        outmess('crackline: could not resolve function call for line=%s.\n'%repr(line))
+                        return
+                    analyzeline(m, 'callfun', line)
+                    return
+        if verbose>1 or (verbose==1 and currentfilename.lower().endswith('.pyf')):
+            previous_context = None
+            outmess('crackline:%d: No pattern for line\n'%(groupcounter))
+        return
+    elif pat[1]=='end':
+        if 0<=skipblocksuntil<groupcounter:
+            groupcounter=groupcounter-1
+            if skipblocksuntil<=groupcounter: return
+        if groupcounter<=0:
+            raise Exception('crackline: groupcounter(=%s) is nonpositive. '
+                            'Check the blocks.' \
+                            % (groupcounter))
+        m1 = beginpattern[0].match((line))
+        if (m1) and (not m1.group('this')==groupname[groupcounter]):
+            raise Exception('crackline: End group %s does not match with '
+                            'previous Begin group %s\n\t%s' % \
+                            (repr(m1.group('this')), repr(groupname[groupcounter]),
+                             filepositiontext)
+                            )
+        if skipblocksuntil==groupcounter:
+            skipblocksuntil=-1
+        grouplist[groupcounter-1].append(groupcache[groupcounter])
+        grouplist[groupcounter-1][-1]['body']=grouplist[groupcounter]
+        del grouplist[groupcounter]
+        groupcounter=groupcounter-1
+        if not skipemptyends:
+            expectbegin=1
+    elif pat[1] == 'begin':
+        if 0<=skipblocksuntil<=groupcounter:
+            groupcounter=groupcounter+1
+            return
+        gotnextfile=0
+        analyzeline(m, pat[1], line)
+        expectbegin=0
+    elif pat[1]=='endif':
+        pass
+    elif pat[1]=='contains':
+        if ignorecontains: return
+        if 0<=skipblocksuntil<=groupcounter: return
+        skipblocksuntil=groupcounter
+    else:
+        if 0<=skipblocksuntil<=groupcounter:return
+        analyzeline(m, pat[1], line)
+
+def markouterparen(line):
+    l='';f=0
+    for c in line:
+        if c=='(':
+            f=f+1
+            if f==1: l=l+'@(@'; continue
+        elif c==')':
+            f=f-1
+            if f==0: l=l+'@)@'; continue
+        l=l+c
+    return l
+def markoutercomma(line,comma=','):
+    l='';f=0
+    cc=''
+    for c in line:
+        if (not cc or cc==')') and c=='(':
+            f=f+1
+            cc = ')'
+        elif not cc and c=='\'' and (not l or l[-1]!='\\'):
+            f=f+1
+            cc = '\''
+        elif c==cc:
+            f=f-1
+            if f==0:
+                cc=''
+        elif c==comma and f==0:
+            l=l+'@'+comma+'@'
+            continue
+        l=l+c
+    assert not f, repr((f, line, l, cc))
+    return l
+def unmarkouterparen(line):
+    r = line.replace('@(@', '(').replace('@)@', ')')
+    return r
+def appenddecl(decl,decl2,force=1):
+    if not decl: decl={}
+    if not decl2: return decl
+    if decl is decl2: return decl
+    for k in list(decl2.keys()):
+        if k=='typespec':
+            if force or k not in decl:
+                decl[k]=decl2[k]
+        elif k=='attrspec':
+            for l in decl2[k]:
+                decl=setattrspec(decl, l, force)
+        elif k=='kindselector':
+            decl=setkindselector(decl, decl2[k], force)
+        elif k=='charselector':
+            decl=setcharselector(decl, decl2[k], force)
+        elif k in ['=', 'typename']:
+            if force or k not in decl:
+                decl[k]=decl2[k]
+        elif k=='note':
+            pass
+        elif k in ['intent', 'check', 'dimension', 'optional', 'required']:
+            errmess('appenddecl: "%s" not implemented.\n'%k)
+        else:
+            raise Exception('appenddecl: Unknown variable definition key:' + \
+                            str(k))
+    return decl
+
+selectpattern=re.compile(r'\s*(?P<this>(@\(@.*?@\)@|[*][\d*]+|[*]\s*@\(@.*?@\)@|))(?P<after>.*)\Z', re.I)
+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)
+callnameargspattern=re.compile(r'\s*(?P<name>\b[\w$]+\b)\s*@\(@\s*(?P<args>.*)\s*@\)@\s*\Z', re.I)
+real16pattern = re.compile(r'([-+]?(?:\d+(?:\.\d*)?|\d*\.\d+))[dD]((?:[-+]?\d+)?)')
+real8pattern = re.compile(r'([-+]?((?:\d+(?:\.\d*)?|\d*\.\d+))[eE]((?:[-+]?\d+)?)|(\d+\.\d*))')
+
+_intentcallbackpattern = re.compile(r'intent\s*\(.*?\bcallback\b', re.I)
+def _is_intent_callback(vdecl):
+    for a in vdecl.get('attrspec', []):
+        if _intentcallbackpattern.match(a):
+            return 1
+    return 0
+
+def _resolvenameargspattern(line):
+    line = markouterparen(line)
+    m1=nameargspattern.match(line)
+    if m1:
+        return m1.group('name'), m1.group('args'), m1.group('result'), m1.group('bind')
+    m1=callnameargspattern.match(line)
+    if m1:
+        return m1.group('name'), m1.group('args'), None, None
+    return None, [], None, None
+
+def analyzeline(m, case, line):
+    global groupcounter, groupname, groupcache, grouplist, filepositiontext,\
+           currentfilename, f77modulename, neededinterface, neededmodule, expectbegin,\
+           gotnextfile, previous_context
+    block=m.group('this')
+    if case != 'multiline':
+        previous_context = None
+    if expectbegin and case not in ['begin', 'call', 'callfun', 'type'] \
+       and not skipemptyends and groupcounter<1:
+        newname=os.path.basename(currentfilename).split('.')[0]
+        outmess('analyzeline: no group yet. Creating program group with name "%s".\n'%newname)
+        gotnextfile=0
+        groupcounter=groupcounter+1
+        groupname[groupcounter]='program'
+        groupcache[groupcounter]={}
+        grouplist[groupcounter]=[]
+        groupcache[groupcounter]['body']=[]
+        groupcache[groupcounter]['vars']={}
+        groupcache[groupcounter]['block']='program'
+        groupcache[groupcounter]['name']=newname
+        groupcache[groupcounter]['from']='fromsky'
+        expectbegin=0
+    if case in ['begin', 'call', 'callfun']:
+        # Crack line => block,name,args,result
+        block = block.lower()
+        if re.match(r'block\s*data', block, re.I): block='block data'
+        if re.match(r'python\s*module', block, re.I): block='python module'
+        name, args, result, bind = _resolvenameargspattern(m.group('after'))
+        if name is None:
+            if block=='block data':
+                name = '_BLOCK_DATA_'
+            else:
+                name = ''
+            if block not in ['interface', 'block data']:
+                outmess('analyzeline: No name/args pattern found for line.\n')
+
+        previous_context = (block, name, groupcounter)
+        if args: args=rmbadname([x.strip() for x in markoutercomma(args).split('@,@')])
+        else: args=[]
+        if '' in args:
+            while '' in args:
+                args.remove('')
+            outmess('analyzeline: argument list is malformed (missing argument).\n')
+
+        # end of crack line => block,name,args,result
+        needmodule=0
+        needinterface=0
+
+        if case in ['call', 'callfun']:
+            needinterface=1
+            if 'args' not in groupcache[groupcounter]:
+                return
+            if name not in groupcache[groupcounter]['args']:
+                return
+            for it in grouplist[groupcounter]:
+                if it['name']==name:
+                    return
+            if name in groupcache[groupcounter]['interfaced']:
+                return
+            block={'call':'subroutine','callfun':'function'}[case]
+        if f77modulename and neededmodule==-1 and groupcounter<=1:
+            neededmodule=groupcounter+2
+            needmodule=1
+            if block != 'interface':
+                needinterface=1
+        # Create new block(s)
+        groupcounter=groupcounter+1
+        groupcache[groupcounter]={}
+        grouplist[groupcounter]=[]
+        if needmodule:
+            if verbose>1:
+                outmess('analyzeline: Creating module block %s\n'%repr(f77modulename), 0)
+            groupname[groupcounter]='module'
+            groupcache[groupcounter]['block']='python module'
+            groupcache[groupcounter]['name']=f77modulename
+            groupcache[groupcounter]['from']=''
+            groupcache[groupcounter]['body']=[]
+            groupcache[groupcounter]['externals']=[]
+            groupcache[groupcounter]['interfaced']=[]
+            groupcache[groupcounter]['vars']={}
+            groupcounter=groupcounter+1
+            groupcache[groupcounter]={}
+            grouplist[groupcounter]=[]
+        if needinterface:
+            if verbose>1:
+                outmess('analyzeline: Creating additional interface block (groupcounter=%s).\n' % (groupcounter), 0)
+            groupname[groupcounter]='interface'
+            groupcache[groupcounter]['block']='interface'
+            groupcache[groupcounter]['name']='unknown_interface'
+            groupcache[groupcounter]['from']='%s:%s'%(groupcache[groupcounter-1]['from'], groupcache[groupcounter-1]['name'])
+            groupcache[groupcounter]['body']=[]
+            groupcache[groupcounter]['externals']=[]
+            groupcache[groupcounter]['interfaced']=[]
+            groupcache[groupcounter]['vars']={}
+            groupcounter=groupcounter+1
+            groupcache[groupcounter]={}
+            grouplist[groupcounter]=[]
+        groupname[groupcounter]=block
+        groupcache[groupcounter]['block']=block
+        if not name: name='unknown_'+block
+        groupcache[groupcounter]['prefix']=m.group('before')
+        groupcache[groupcounter]['name']=rmbadname1(name)
+        groupcache[groupcounter]['result']=result
+        if groupcounter==1:
+            groupcache[groupcounter]['from']=currentfilename
+        else:
+            if f77modulename and groupcounter==3:
+                groupcache[groupcounter]['from']='%s:%s'%(groupcache[groupcounter-1]['from'], currentfilename)
+            else:
+                groupcache[groupcounter]['from']='%s:%s'%(groupcache[groupcounter-1]['from'], groupcache[groupcounter-1]['name'])
+        for k in list(groupcache[groupcounter].keys()):
+            if not groupcache[groupcounter][k]:
+                del groupcache[groupcounter][k]
+
+        groupcache[groupcounter]['args']=args
+        groupcache[groupcounter]['body']=[]
+        groupcache[groupcounter]['externals']=[]
+        groupcache[groupcounter]['interfaced']=[]
+        groupcache[groupcounter]['vars']={}
+        groupcache[groupcounter]['entry']={}
+        # end of creation
+        if block=='type':
+            groupcache[groupcounter]['varnames'] = []
+
+        if case in ['call', 'callfun']: # set parents variables
+            if name not in groupcache[groupcounter-2]['externals']:
+                groupcache[groupcounter-2]['externals'].append(name)
+            groupcache[groupcounter]['vars']=copy.deepcopy(groupcache[groupcounter-2]['vars'])
+            #try: del groupcache[groupcounter]['vars'][groupcache[groupcounter-2]['name']]
+            #except: pass
+            try: del groupcache[groupcounter]['vars'][name][groupcache[groupcounter]['vars'][name]['attrspec'].index('external')]
+            except: pass
+        if block in ['function', 'subroutine']: # set global attributes
+            try: groupcache[groupcounter]['vars'][name]=appenddecl(groupcache[groupcounter]['vars'][name], groupcache[groupcounter-2]['vars'][''])
+            except: pass
+            if case=='callfun': # return type
+                if result and result in groupcache[groupcounter]['vars']:
+                    if not name==result:
+                        groupcache[groupcounter]['vars'][name]=appenddecl(groupcache[groupcounter]['vars'][name], groupcache[groupcounter]['vars'][result])
+            #if groupcounter>1: # name is interfaced
+            try: groupcache[groupcounter-2]['interfaced'].append(name)
+            except: pass
+        if block=='function':
+            t=typespattern[0].match(m.group('before')+' '+name)
+            if t:
+                typespec, selector, attr, edecl=cracktypespec0(t.group('this'), t.group('after'))
+                updatevars(typespec, selector, attr, edecl)
+
+        if case in ['call', 'callfun']:
+            grouplist[groupcounter-1].append(groupcache[groupcounter])
+            grouplist[groupcounter-1][-1]['body']=grouplist[groupcounter]
+            del grouplist[groupcounter]
+            groupcounter=groupcounter-1 # end routine
+            grouplist[groupcounter-1].append(groupcache[groupcounter])
+            grouplist[groupcounter-1][-1]['body']=grouplist[groupcounter]
+            del grouplist[groupcounter]
+            groupcounter=groupcounter-1 # end interface
+
+    elif case=='entry':
+        name, args, result, bind=_resolvenameargspattern(m.group('after'))
+        if name is not None:
+            if args:
+                args=rmbadname([x.strip() for x in markoutercomma(args).split('@,@')])
+            else: args=[]
+            assert result is None, repr(result)
+            groupcache[groupcounter]['entry'][name] = args
+            previous_context = ('entry', name, groupcounter)
+    elif case=='type':
+        typespec, selector, attr, edecl=cracktypespec0(block, m.group('after'))
+        last_name = updatevars(typespec, selector, attr, edecl)
+        if last_name is not None:
+            previous_context = ('variable', last_name, groupcounter)
+    elif case in ['dimension', 'intent', 'optional', 'required', 'external', 'public', 'private', 'intrisic']:
+        edecl=groupcache[groupcounter]['vars']
+        ll=m.group('after').strip()
+        i=ll.find('::')
+        if i<0 and case=='intent':
+            i=markouterparen(ll).find('@)@')-2
+            ll=ll[:i+1]+'::'+ll[i+1:]
+            i=ll.find('::')
+            if ll[i:]=='::' and 'args' in groupcache[groupcounter]:
+                outmess('All arguments will have attribute %s%s\n'%(m.group('this'), ll[:i]))
+                ll = ll + ','.join(groupcache[groupcounter]['args'])
+        if i<0:i=0;pl=''
+        else: pl=ll[:i].strip();ll=ll[i+2:]
+        ch = markoutercomma(pl).split('@,@')
+        if len(ch)>1:
+            pl = ch[0]
+            outmess('analyzeline: cannot handle multiple attributes without type specification. Ignoring %r.\n' % (','.join(ch[1:])))
+        last_name = None
+
+        for e in [x.strip() for x in markoutercomma(ll).split('@,@')]:
+            m1=namepattern.match(e)
+            if not m1:
+                if case in ['public', 'private']: k=''
+                else:
+                    print(m.groupdict())
+                    outmess('analyzeline: no name pattern found in %s statement for %s. Skipping.\n'%(case, repr(e)))
+                    continue
+            else:
+                k=rmbadname1(m1.group('name'))
+            if k not in edecl:
+                edecl[k]={}
+            if case=='dimension':
+                ap=case+m1.group('after')
+            if case=='intent':
+                ap=m.group('this')+pl
+                if _intentcallbackpattern.match(ap):
+                    if k not in groupcache[groupcounter]['args']:
+                        if groupcounter>1:
+                            if '__user__' not in groupcache[groupcounter-2]['name']:
+                                outmess('analyzeline: missing __user__ module (could be nothing)\n')
+                            if k!=groupcache[groupcounter]['name']: # fixes ticket 1693
+                                outmess('analyzeline: appending intent(callback) %s'\
+                                        ' to %s arguments\n' % (k, groupcache[groupcounter]['name']))
+                                groupcache[groupcounter]['args'].append(k)
+                        else:
+                            errmess('analyzeline: intent(callback) %s is ignored' % (k))
+                    else:
+                        errmess('analyzeline: intent(callback) %s is already'\
+                                ' in argument list' % (k))
+            if case in ['optional', 'required', 'public', 'external', 'private', 'intrisic']:
+                ap=case
+            if 'attrspec' in edecl[k]:
+                edecl[k]['attrspec'].append(ap)
+            else:
+                edecl[k]['attrspec']=[ap]
+            if case=='external':
+                if groupcache[groupcounter]['block']=='program':
+                    outmess('analyzeline: ignoring program arguments\n')
+                    continue
+                if k not in groupcache[groupcounter]['args']:
+                    #outmess('analyzeline: ignoring external %s (not in arguments list)\n'%(`k`))
+                    continue
+                if 'externals' not in groupcache[groupcounter]:
+                    groupcache[groupcounter]['externals']=[]
+                groupcache[groupcounter]['externals'].append(k)
+            last_name = k
+        groupcache[groupcounter]['vars']=edecl
+        if last_name is not None:
+            previous_context = ('variable', last_name, groupcounter)
+    elif case=='parameter':
+        edecl=groupcache[groupcounter]['vars']
+        ll=m.group('after').strip()[1:-1]
+        last_name = None
+        for e in markoutercomma(ll).split('@,@'):
+            try:
+                k, initexpr=[x.strip() for x in e.split('=')]
+            except:
+                outmess('analyzeline: could not extract name,expr in parameter statement "%s" of "%s"\n'%(e, ll));continue
+            params = get_parameters(edecl)
+            k=rmbadname1(k)
+            if k not in edecl:
+                edecl[k]={}
+            if '=' in edecl[k] and (not edecl[k]['=']==initexpr):
+                outmess('analyzeline: Overwriting the value of parameter "%s" ("%s") with "%s".\n'%(k, edecl[k]['='], initexpr))
+            t = determineexprtype(initexpr, params)
+            if t:
+                if t.get('typespec')=='real':
+                    tt = list(initexpr)
+                    for m in real16pattern.finditer(initexpr):
+                        tt[m.start():m.end()] = list(\
+                            initexpr[m.start():m.end()].lower().replace('d', 'e'))
+                    initexpr = ''.join(tt)
+                elif t.get('typespec')=='complex':
+                    initexpr = initexpr[1:].lower().replace('d', 'e').\
+                               replace(',', '+1j*(')
+            try:
+                v = eval(initexpr, {}, params)
+            except (SyntaxError, NameError, TypeError) as msg:
+                errmess('analyzeline: Failed to evaluate %r. Ignoring: %s\n'\
+                        % (initexpr, msg))
+                continue
+            edecl[k]['='] = repr(v)
+            if 'attrspec' in edecl[k]:
+                edecl[k]['attrspec'].append('parameter')
+            else: edecl[k]['attrspec']=['parameter']
+            last_name = k
+        groupcache[groupcounter]['vars']=edecl
+        if last_name is not None:
+            previous_context = ('variable', last_name, groupcounter)
+    elif case=='implicit':
+        if m.group('after').strip().lower()=='none':
+            groupcache[groupcounter]['implicit']=None
+        elif m.group('after'):
+            if 'implicit' in groupcache[groupcounter]:
+                impl=groupcache[groupcounter]['implicit']
+            else: impl={}
+            if impl is None:
+                outmess('analyzeline: Overwriting earlier "implicit none" statement.\n')
+                impl={}
+            for e in markoutercomma(m.group('after')).split('@,@'):
+                decl={}
+                m1=re.match(r'\s*(?P<this>.*?)\s*(\(\s*(?P<after>[a-z-, ]+)\s*\)\s*|)\Z', e, re.I)
+                if not m1:
+                    outmess('analyzeline: could not extract info of implicit statement part "%s"\n'%(e));continue
+                m2=typespattern4implicit.match(m1.group('this'))
+                if not m2:
+                    outmess('analyzeline: could not extract types pattern of implicit statement part "%s"\n'%(e));continue
+                typespec, selector, attr, edecl=cracktypespec0(m2.group('this'), m2.group('after'))
+                kindselect, charselect, typename=cracktypespec(typespec, selector)
+                decl['typespec']=typespec
+                decl['kindselector']=kindselect
+                decl['charselector']=charselect
+                decl['typename']=typename
+                for k in list(decl.keys()):
+                    if not decl[k]: del decl[k]
+                for r in markoutercomma(m1.group('after')).split('@,@'):
+                    if '-' in r:
+                        try: begc, endc=[x.strip() for x in r.split('-')]
+                        except:
+                            outmess('analyzeline: expected "<char>-<char>" instead of "%s" in range list of implicit statement\n'%r);continue
+                    else: begc=endc=r.strip()
+                    if not len(begc)==len(endc)==1:
+                        outmess('analyzeline: expected "<char>-<char>" instead of "%s" in range list of implicit statement (2)\n'%r);continue
+                    for o in range(ord(begc), ord(endc)+1):
+                        impl[chr(o)]=decl
+            groupcache[groupcounter]['implicit']=impl
+    elif case=='data':
+        ll=[]
+        dl='';il='';f=0;fc=1;inp=0
+        for c in m.group('after'):
+            if not inp:
+                if c=="'": fc=not fc
+                if c=='/' and fc: f=f+1;continue
+            if c=='(': inp = inp + 1
+            elif c==')': inp = inp - 1
+            if f==0: dl=dl+c
+            elif f==1: il=il+c
+            elif f==2:
+                dl = dl.strip()
+                if dl.startswith(','):
+                    dl = dl[1:].strip()
+                ll.append([dl, il])
+                dl=c;il='';f=0
+        if f==2:
+            dl = dl.strip()
+            if dl.startswith(','):
+                dl = dl[1:].strip()
+            ll.append([dl, il])
+        vars={}
+        if 'vars' in groupcache[groupcounter]:
+            vars=groupcache[groupcounter]['vars']
+        last_name = None
+        for l in ll:
+            l=[x.strip() for x in l]
+            if l[0][0]==',':l[0]=l[0][1:]
+            if l[0][0]=='(':
+                outmess('analyzeline: implied-DO list "%s" is not supported. Skipping.\n'%l[0])
+                continue
+            #if '(' in l[0]:
+            #    #outmess('analyzeline: ignoring this data statement.\n')
+            #    continue
+            i=0;j=0;llen=len(l[1])
+            for v in rmbadname([x.strip() for x in markoutercomma(l[0]).split('@,@')]):
+                if v[0]=='(':
+                    outmess('analyzeline: implied-DO list "%s" is not supported. Skipping.\n'%v)
+                    # XXX: subsequent init expressions may get wrong values.
+                    #      Ignoring since data statements are irrelevant for wrapping.
+                    continue
+                fc=0
+                while (i<llen) and (fc or not l[1][i]==','):
+                    if l[1][i]=="'": fc=not fc
+                    i=i+1
+                i=i+1
+                #v,l[1][j:i-1]=name,initvalue
+                if v not in vars:
+                    vars[v]={}
+                if '=' in vars[v] and not vars[v]['=']==l[1][j:i-1]:
+                    outmess('analyzeline: changing init expression of "%s" ("%s") to "%s"\n'%(v, vars[v]['='], l[1][j:i-1]))
+                vars[v]['=']=l[1][j:i-1]
+                j=i
+                last_name = v
+        groupcache[groupcounter]['vars']=vars
+        if last_name is not None:
+            previous_context = ('variable', last_name, groupcounter)
+    elif case=='common':
+        line=m.group('after').strip()
+        if not line[0]=='/':line='//'+line
+        cl=[]
+        f=0;bn='';ol=''
+        for c in line:
+            if c=='/':f=f+1;continue
+            if f>=3:
+                bn = bn.strip()
+                if not bn: bn='_BLNK_'
+                cl.append([bn, ol])
+                f=f-2;bn='';ol=''
+            if f%2: bn=bn+c
+            else: ol=ol+c
+        bn = bn.strip()
+        if not bn: bn='_BLNK_'
+        cl.append([bn, ol])
+        commonkey={}
+        if 'common' in groupcache[groupcounter]:
+            commonkey=groupcache[groupcounter]['common']
+        for c in cl:
+            if c[0] in commonkey:
+                outmess('analyzeline: previously defined common block encountered. Skipping.\n')
+                continue
+            commonkey[c[0]]=[]
+            for i in [x.strip() for x in markoutercomma(c[1]).split('@,@')]:
+                if i: commonkey[c[0]].append(i)
+        groupcache[groupcounter]['common']=commonkey
+        previous_context = ('common', bn, groupcounter)
+    elif case=='use':
+        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)
+        if m1:
+            mm=m1.groupdict()
+            if 'use' not in groupcache[groupcounter]:
+                groupcache[groupcounter]['use']={}
+            name=m1.group('name')
+            groupcache[groupcounter]['use'][name]={}
+            isonly=0
+            if 'list' in mm and mm['list'] is not None:
+                if 'notonly' in mm and mm['notonly'] is None:
+                    isonly=1
+                groupcache[groupcounter]['use'][name]['only']=isonly
+                ll=[x.strip() for x in mm['list'].split(',')]
+                rl={}
+                for l in ll:
+                    if '=' in l:
+                        m2=re.match(r'\A\s*(?P<local>\b[\w]+\b)\s*=\s*>\s*(?P<use>\b[\w]+\b)\s*\Z', l, re.I)
+                        if m2: rl[m2.group('local').strip()]=m2.group('use').strip()
+                        else:
+                            outmess('analyzeline: Not local=>use pattern found in %s\n'%repr(l))
+                    else:
+                        rl[l]=l
+                    groupcache[groupcounter]['use'][name]['map']=rl
+            else:
+                pass
+        else:
+            print(m.groupdict())
+            outmess('analyzeline: Could not crack the use statement.\n')
+    elif case in ['f2pyenhancements']:
+        if 'f2pyenhancements' not in groupcache[groupcounter]:
+            groupcache[groupcounter]['f2pyenhancements'] = {}
+        d = groupcache[groupcounter]['f2pyenhancements']
+        if m.group('this')=='usercode' and 'usercode' in d:
+            if isinstance(d['usercode'], str):
+                d['usercode'] = [d['usercode']]
+            d['usercode'].append(m.group('after'))
+        else:
+            d[m.group('this')] = m.group('after')
+    elif case=='multiline':
+        if previous_context is None:
+            if verbose:
+                outmess('analyzeline: No context for multiline block.\n')
+            return
+        gc = groupcounter
+        #gc = previous_context[2]
+        appendmultiline(groupcache[gc],
+                        previous_context[:2],
+                        m.group('this'))
+    else:
+        if verbose>1:
+            print(m.groupdict())
+            outmess('analyzeline: No code implemented for line.\n')
+
+def appendmultiline(group, context_name, ml):
+    if 'f2pymultilines' not in group:
+        group['f2pymultilines'] = {}
+    d = group['f2pymultilines']
+    if context_name not in d:
+        d[context_name] = []
+    d[context_name].append(ml)
+    return
+
+def cracktypespec0(typespec, ll):
+    selector=None
+    attr=None
+    if re.match(r'double\s*complex', typespec, re.I): typespec='double complex'
+    elif re.match(r'double\s*precision', typespec, re.I): typespec='double precision'
+    else: typespec=typespec.strip().lower()
+    m1=selectpattern.match(markouterparen(ll))
+    if not m1:
+        outmess('cracktypespec0: no kind/char_selector pattern found for line.\n')
+        return
+    d=m1.groupdict()
+    for k in list(d.keys()): d[k]=unmarkouterparen(d[k])
+    if typespec in ['complex', 'integer', 'logical', 'real', 'character', 'type']:
+        selector=d['this']
+        ll=d['after']
+    i=ll.find('::')
+    if i>=0:
+        attr=ll[:i].strip()
+        ll=ll[i+2:]
+    return typespec, selector, attr, ll
+#####
+namepattern=re.compile(r'\s*(?P<name>\b[\w]+\b)\s*(?P<after>.*)\s*\Z', re.I)
+kindselector=re.compile(r'\s*(\(\s*(kind\s*=)?\s*(?P<kind>.*)\s*\)|[*]\s*(?P<kind2>.*?))\s*\Z', re.I)
+charselector=re.compile(r'\s*(\((?P<lenkind>.*)\)|[*]\s*(?P<charlen>.*))\s*\Z', re.I)
+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)
+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)
+def removespaces(expr):
+    expr=expr.strip()
+    if len(expr)<=1: return expr
+    expr2=expr[0]
+    for i in range(1, len(expr)-1):
+        if expr[i]==' ' and \
+           ((expr[i+1] in "()[]{}=+-/* ") or (expr[i-1] in "()[]{}=+-/* ")): continue
+        expr2=expr2+expr[i]
+    expr2=expr2+expr[-1]
+    return expr2
+def markinnerspaces(line):
+    l='';f=0
+    cc='\''
+    cc1='"'
+    cb=''
+    for c in line:
+        if cb=='\\' and c in ['\\', '\'', '"']:
+            l=l+c
+            cb=c
+            continue
+        if f==0 and c in ['\'', '"']: cc=c; cc1={'\'':'"','"':'\''}[c]
+        if c==cc:f=f+1
+        elif c==cc:f=f-1
+        elif c==' ' and f==1: l=l+'@_@'; continue
+        l=l+c;cb=c
+    return l
+def updatevars(typespec, selector, attrspec, entitydecl):
+    global groupcache, groupcounter
+    last_name = None
+    kindselect, charselect, typename=cracktypespec(typespec, selector)
+    if attrspec:
+        attrspec=[x.strip() for x in markoutercomma(attrspec).split('@,@')]
+        l = []
+        c = re.compile(r'(?P<start>[a-zA-Z]+)')
+        for a in attrspec:
+            if not a:
+                continue
+            m = c.match(a)
+            if m:
+                s = m.group('start').lower()
+                a = s + a[len(s):]
+            l.append(a)
+        attrspec = l
+    el=[x.strip() for x in markoutercomma(entitydecl).split('@,@')]
+    el1=[]
+    for e in el:
+        for e1 in [x.strip() for x in markoutercomma(removespaces(markinnerspaces(e)), comma=' ').split('@ @')]:
+            if e1: el1.append(e1.replace('@_@', ' '))
+    for e in el1:
+        m=namepattern.match(e)
+        if not m:
+            outmess('updatevars: no name pattern found for entity=%s. Skipping.\n'%(repr(e)))
+            continue
+        ename=rmbadname1(m.group('name'))
+        edecl={}
+        if ename in groupcache[groupcounter]['vars']:
+            edecl=groupcache[groupcounter]['vars'][ename].copy()
+            not_has_typespec = 'typespec' not in edecl
+            if not_has_typespec:
+                edecl['typespec']=typespec
+            elif typespec and (not typespec==edecl['typespec']):
+                outmess('updatevars: attempt to change the type of "%s" ("%s") to "%s". Ignoring.\n' % (ename, edecl['typespec'], typespec))
+            if 'kindselector' not in edecl:
+                edecl['kindselector']=copy.copy(kindselect)
+            elif kindselect:
+                for k in list(kindselect.keys()):
+                    if k in edecl['kindselector'] and (not kindselect[k]==edecl['kindselector'][k]):
+                        outmess('updatevars: attempt to change the kindselector "%s" of "%s" ("%s") to "%s". Ignoring.\n' % (k, ename, edecl['kindselector'][k], kindselect[k]))
+                    else: edecl['kindselector'][k]=copy.copy(kindselect[k])
+            if 'charselector' not in edecl and charselect:
+                if not_has_typespec:
+                    edecl['charselector']=charselect
+                else:
+                    errmess('updatevars:%s: attempt to change empty charselector to %r. Ignoring.\n' \
+                            %(ename, charselect))
+            elif charselect:
+                for k in list(charselect.keys()):
+                    if k in edecl['charselector'] and (not charselect[k]==edecl['charselector'][k]):
+                        outmess('updatevars: attempt to change the charselector "%s" of "%s" ("%s") to "%s". Ignoring.\n' % (k, ename, edecl['charselector'][k], charselect[k]))
+                    else: edecl['charselector'][k]=copy.copy(charselect[k])
+            if 'typename' not in edecl:
+                edecl['typename']=typename
+            elif typename and (not edecl['typename']==typename):
+                outmess('updatevars: attempt to change the typename of "%s" ("%s") to "%s". Ignoring.\n' % (ename, edecl['typename'], typename))
+            if 'attrspec' not in edecl:
+                edecl['attrspec']=copy.copy(attrspec)
+            elif attrspec:
+                for a in attrspec:
+                    if a not in edecl['attrspec']:
+                        edecl['attrspec'].append(a)
+        else:
+            edecl['typespec']=copy.copy(typespec)
+            edecl['kindselector']=copy.copy(kindselect)
+            edecl['charselector']=copy.copy(charselect)
+            edecl['typename']=typename
+            edecl['attrspec']=copy.copy(attrspec)
+        if m.group('after'):
+            m1=lenarraypattern.match(markouterparen(m.group('after')))
+            if m1:
+                d1=m1.groupdict()
+                for lk in ['len', 'array', 'init']:
+                    if d1[lk+'2'] is not None: d1[lk]=d1[lk+'2']; del d1[lk+'2']
+                for k in list(d1.keys()):
+                    if d1[k] is not None: d1[k]=unmarkouterparen(d1[k])
+                    else: del d1[k]
+                if 'len' in d1 and 'array' in d1:
+                    if d1['len']=='':
+                        d1['len']=d1['array']
+                        del d1['array']
+                    else:
+                        d1['array']=d1['array']+','+d1['len']
+                        del d1['len']
+                        errmess('updatevars: "%s %s" is mapped to "%s %s(%s)"\n'%(typespec, e, typespec, ename, d1['array']))
+                if 'array' in d1:
+                    dm = 'dimension(%s)'%d1['array']
+                    if 'attrspec' not in edecl or (not edecl['attrspec']):
+                        edecl['attrspec']=[dm]
+                    else:
+                        edecl['attrspec'].append(dm)
+                        for dm1 in edecl['attrspec']:
+                            if dm1[:9]=='dimension' and dm1!=dm:
+                                del edecl['attrspec'][-1]
+                                errmess('updatevars:%s: attempt to change %r to %r. Ignoring.\n' \
+                                        % (ename, dm1, dm))
+                                break
+
+                if 'len' in d1:
+                    if typespec in ['complex', 'integer', 'logical', 'real']:
+                        if ('kindselector' not in edecl) or (not edecl['kindselector']):
+                            edecl['kindselector']={}
+                        edecl['kindselector']['*']=d1['len']
+                    elif typespec == 'character':
+                        if ('charselector' not in edecl) or (not edecl['charselector']):
+                            edecl['charselector']={}
+                        if 'len' in edecl['charselector']:
+                            del edecl['charselector']['len']
+                        edecl['charselector']['*']=d1['len']
+                if 'init' in d1:
+                    if '=' in edecl and (not edecl['=']==d1['init']):
+                        outmess('updatevars: attempt to change the init expression of "%s" ("%s") to "%s". Ignoring.\n' % (ename, edecl['='], d1['init']))
+                    else:
+                        edecl['=']=d1['init']
+            else:
+                outmess('updatevars: could not crack entity declaration "%s". Ignoring.\n'%(ename+m.group('after')))
+        for k in list(edecl.keys()):
+            if not edecl[k]:
+                del edecl[k]
+        groupcache[groupcounter]['vars'][ename]=edecl
+        if 'varnames' in groupcache[groupcounter]:
+            groupcache[groupcounter]['varnames'].append(ename)
+        last_name = ename
+    return last_name
+
+def cracktypespec(typespec, selector):
+    kindselect=None
+    charselect=None
+    typename=None
+    if selector:
+        if typespec in ['complex', 'integer', 'logical', 'real']:
+            kindselect=kindselector.match(selector)
+            if not kindselect:
+                outmess('cracktypespec: no kindselector pattern found for %s\n'%(repr(selector)))
+                return
+            kindselect=kindselect.groupdict()
+            kindselect['*']=kindselect['kind2']
+            del kindselect['kind2']
+            for k in list(kindselect.keys()):
+                if not kindselect[k]: del kindselect[k]
+            for k, i in list(kindselect.items()):
+                kindselect[k] = rmbadname1(i)
+        elif typespec=='character':
+            charselect=charselector.match(selector)
+            if not charselect:
+                outmess('cracktypespec: no charselector pattern found for %s\n'%(repr(selector)))
+                return
+            charselect=charselect.groupdict()
+            charselect['*']=charselect['charlen']
+            del charselect['charlen']
+            if charselect['lenkind']:
+                lenkind=lenkindpattern.match(markoutercomma(charselect['lenkind']))
+                lenkind=lenkind.groupdict()
+                for lk in ['len', 'kind']:
+                    if lenkind[lk+'2']:
+                        lenkind[lk]=lenkind[lk+'2']
+                    charselect[lk]=lenkind[lk]
+                    del lenkind[lk+'2']
+            del charselect['lenkind']
+            for k in list(charselect.keys()):
+                if not charselect[k]: del charselect[k]
+            for k, i in list(charselect.items()):
+                charselect[k] = rmbadname1(i)
+        elif typespec=='type':
+            typename=re.match(r'\s*\(\s*(?P<name>\w+)\s*\)', selector, re.I)
+            if typename: typename=typename.group('name')
+            else: outmess('cracktypespec: no typename found in %s\n'%(repr(typespec+selector)))
+        else:
+            outmess('cracktypespec: no selector used for %s\n'%(repr(selector)))
+    return kindselect, charselect, typename
+######
+def setattrspec(decl,attr,force=0):
+    if not decl:
+        decl={}
+    if not attr:
+        return decl
+    if 'attrspec' not in decl:
+        decl['attrspec']=[attr]
+        return decl
+    if force: decl['attrspec'].append(attr)
+    if attr in decl['attrspec']: return decl
+    if attr=='static' and 'automatic' not in decl['attrspec']:
+        decl['attrspec'].append(attr)
+    elif attr=='automatic' and 'static' not in decl['attrspec']:
+        decl['attrspec'].append(attr)
+    elif attr=='public' and 'private' not in decl['attrspec']:
+        decl['attrspec'].append(attr)
+    elif attr=='private' and 'public' not in decl['attrspec']:
+        decl['attrspec'].append(attr)
+    else:
+        decl['attrspec'].append(attr)
+    return decl
+
+def setkindselector(decl,sel,force=0):
+    if not decl:
+        decl={}
+    if not sel:
+        return decl
+    if 'kindselector' not in decl:
+        decl['kindselector']=sel
+        return decl
+    for k in list(sel.keys()):
+        if force or k not in decl['kindselector']:
+            decl['kindselector'][k]=sel[k]
+    return decl
+
+def setcharselector(decl,sel,force=0):
+    if not decl:
+        decl={}
+    if not sel:
+        return decl
+    if 'charselector' not in decl:
+        decl['charselector']=sel
+        return decl
+    for k in list(sel.keys()):
+        if force or k not in decl['charselector']:
+            decl['charselector'][k]=sel[k]
+    return decl
+
+def getblockname(block,unknown='unknown'):
+    if 'name' in block:
+        return block['name']
+    return unknown
+
+###### post processing
+
+def setmesstext(block):
+    global filepositiontext
+    try:
+        filepositiontext='In: %s:%s\n'%(block['from'], block['name'])
+    except:
+        pass
+
+def get_usedict(block):
+    usedict = {}
+    if 'parent_block' in block:
+        usedict = get_usedict(block['parent_block'])
+    if 'use' in block:
+        usedict.update(block['use'])
+    return usedict
+
+def get_useparameters(block, param_map=None):
+    global f90modulevars
+    if param_map is None:
+        param_map = {}
+    usedict = get_usedict(block)
+    if not usedict:
+        return param_map
+    for usename, mapping in list(usedict.items()):
+        usename = usename.lower()
+        if usename not in f90modulevars:
+            outmess('get_useparameters: no module %s info used by %s\n' % (usename, block.get('name')))
+            continue
+        mvars = f90modulevars[usename]
+        params = get_parameters(mvars)
+        if not params:
+            continue
+        # XXX: apply mapping
+        if mapping:
+            errmess('get_useparameters: mapping for %s not impl.' % (mapping))
+        for k, v in list(params.items()):
+            if k in param_map:
+                outmess('get_useparameters: overriding parameter %s with'\
+                        ' value from module %s' % (repr(k), repr(usename)))
+            param_map[k] = v
+
+    return param_map
+
+def postcrack2(block,tab='',param_map=None):
+    global f90modulevars
+    if not f90modulevars:
+        return block
+    if isinstance(block, list):
+        ret = []
+        for g in block:
+            g = postcrack2(g, tab=tab+'\t', param_map=param_map)
+            ret.append(g)
+        return ret
+    setmesstext(block)
+    outmess('%sBlock: %s\n'%(tab, block['name']), 0)
+
+    if param_map is None:
+        param_map = get_useparameters(block)
+
+    if param_map is not None and 'vars' in block:
+        vars = block['vars']
+        for n in list(vars.keys()):
+            var = vars[n]
+            if 'kindselector' in var:
+                kind = var['kindselector']
+                if 'kind' in kind:
+                    val = kind['kind']
+                    if val in param_map:
+                        kind['kind'] = param_map[val]
+    new_body = []
+    for b in block['body']:
+        b = postcrack2(b, tab=tab+'\t', param_map=param_map)
+        new_body.append(b)
+    block['body'] = new_body
+
+    return block
+
+def postcrack(block,args=None,tab=''):
+    """
+    TODO:
+          function return values
+          determine expression types if in argument list
+    """
+    global usermodules, onlyfunctions
+    if isinstance(block, list):
+        gret=[]
+        uret=[]
+        for g in block:
+            setmesstext(g)
+            g=postcrack(g, tab=tab+'\t')
+            if 'name' in g and '__user__' in g['name']: # sort user routines to appear first
+                uret.append(g)
+            else:
+                gret.append(g)
+        return uret+gret
+    setmesstext(block)
+    if not isinstance(block, dict) and 'block' not in block:
+        raise Exception('postcrack: Expected block dictionary instead of ' + \
+                        str(block))
+    if 'name' in block and not block['name']=='unknown_interface':
+        outmess('%sBlock: %s\n'%(tab, block['name']), 0)
+    blocktype=block['block']
+    block=analyzeargs(block)
+    block=analyzecommon(block)
+    block['vars']=analyzevars(block)
+    block['sortvars']=sortvarnames(block['vars'])
+    if 'args' in block and block['args']:
+        args=block['args']
+    block['body']=analyzebody(block, args, tab=tab)
+
+    userisdefined=[]
+##     fromuser = []
+    if 'use' in block:
+        useblock=block['use']
+        for k in list(useblock.keys()):
+            if '__user__' in k:
+                userisdefined.append(k)
+##                 if 'map' in useblock[k]:
+##                     for n in useblock[k]['map'].itervalues():
+##                         if n not in fromuser: fromuser.append(n)
+    else: useblock={}
+    name=''
+    if 'name' in block:
+        name=block['name']
+    if 'externals' in block and block['externals']:# and not userisdefined: # Build a __user__ module
+        interfaced=[]
+        if 'interfaced' in block:
+            interfaced=block['interfaced']
+        mvars=copy.copy(block['vars'])
+        if name:
+            mname=name+'__user__routines'
+        else:
+            mname='unknown__user__routines'
+        if mname in userisdefined:
+            i=1
+            while '%s_%i'%(mname, i) in userisdefined: i=i+1
+            mname='%s_%i'%(mname, i)
+        interface={'block':'interface','body':[],'vars':{},'name':name+'_user_interface'}
+        for e in block['externals']:
+##             if e in fromuser:
+##                 outmess('  Skipping %s that is defined explicitly in another use statement\n'%(`e`))
+##                 continue
+            if e in interfaced:
+                edef=[]
+                j=-1
+                for b in block['body']:
+                    j=j+1
+                    if b['block']=='interface':
+                        i=-1
+                        for bb in b['body']:
+                            i=i+1
+                            if 'name' in bb and bb['name']==e:
+                                edef=copy.copy(bb)
+                                del b['body'][i]
+                                break
+                        if edef:
+                            if not b['body']: del block['body'][j]
+                            del interfaced[interfaced.index(e)]
+                            break
+                interface['body'].append(edef)
+            else:
+                if e in mvars and not isexternal(mvars[e]):
+                    interface['vars'][e]=mvars[e]
+        if interface['vars'] or interface['body']:
+            block['interfaced']=interfaced
+            mblock={'block':'python module','body':[interface],'vars':{},'name':mname,'interfaced':block['externals']}
+            useblock[mname]={}
+            usermodules.append(mblock)
+    if useblock:
+        block['use']=useblock
+    return block
+
+def sortvarnames(vars):
+    indep = []
+    dep = []
+    for v in list(vars.keys()):
+        if 'depend' in vars[v] and vars[v]['depend']:
+            dep.append(v)
+            #print '%s depends on %s'%(v,vars[v]['depend'])
+        else: indep.append(v)
+    n = len(dep)
+    i = 0
+    while dep: #XXX: How to catch dependence cycles correctly?
+        v = dep[0]
+        fl = 0
+        for w in dep[1:]:
+            if w in vars[v]['depend']:
+                fl = 1
+                break
+        if fl:
+            dep = dep[1:]+[v]
+            i = i + 1
+            if i>n:
+                errmess('sortvarnames: failed to compute dependencies because'
+                        ' of cyclic dependencies between '
+                        +', '.join(dep)+'\n')
+                indep = indep + dep
+                break
+        else:
+            indep.append(v)
+            dep = dep[1:]
+            n = len(dep)
+            i = 0
+    #print indep
+    return indep
+
+def analyzecommon(block):
+    if not hascommon(block): return block
+    commonvars=[]
+    for k in list(block['common'].keys()):
+        comvars=[]
+        for e in block['common'][k]:
+            m=re.match(r'\A\s*\b(?P<name>.*?)\b\s*(\((?P<dims>.*?)\)|)\s*\Z', e, re.I)
+            if m:
+                dims=[]
+                if m.group('dims'):
+                    dims=[x.strip() for x in markoutercomma(m.group('dims')).split('@,@')]
+                n=m.group('name').strip()
+                if n in block['vars']:
+                    if 'attrspec' in block['vars'][n]:
+                        block['vars'][n]['attrspec'].append('dimension(%s)'%(','.join(dims)))
+                    else:
+                        block['vars'][n]['attrspec']=['dimension(%s)'%(','.join(dims))]
+                else:
+                    if dims:
+                        block['vars'][n]={'attrspec':['dimension(%s)'%(','.join(dims))]}
+                    else: block['vars'][n]={}
+                if n not in commonvars: commonvars.append(n)
+            else:
+                n=e
+                errmess('analyzecommon: failed to extract "<name>[(<dims>)]" from "%s" in common /%s/.\n'%(e, k))
+            comvars.append(n)
+        block['common'][k]=comvars
+    if 'commonvars' not in block:
+        block['commonvars']=commonvars
+    else:
+        block['commonvars']=block['commonvars']+commonvars
+    return block
+
+def analyzebody(block,args,tab=''):
+    global usermodules, skipfuncs, onlyfuncs, f90modulevars
+    setmesstext(block)
+    body=[]
+    for b in block['body']:
+        b['parent_block'] = block
+        if b['block'] in ['function', 'subroutine']:
+            if args is not None and b['name'] not in args:
+                continue
+            else:
+                as_=b['args']
+            if b['name'] in skipfuncs:
+                continue
+            if onlyfuncs and b['name'] not in onlyfuncs:
+                continue
+            b['saved_interface'] = crack2fortrangen(b, '\n'+' '*6, as_interface=True)
+
+        else: as_=args
+        b=postcrack(b, as_, tab=tab+'\t')
+        if b['block']=='interface' and not b['body']:
+            if 'f2pyenhancements' not in b:
+                continue
+        if b['block'].replace(' ', '')=='pythonmodule':
+            usermodules.append(b)
+        else:
+            if b['block']=='module':
+                f90modulevars[b['name']] = b['vars']
+            body.append(b)
+    return body
+
+def buildimplicitrules(block):
+    setmesstext(block)
+    implicitrules=defaultimplicitrules
+    attrrules={}
+    if 'implicit' in block:
+        if block['implicit'] is None:
+            implicitrules=None
+            if verbose>1:
+                outmess('buildimplicitrules: no implicit rules for routine %s.\n'%repr(block['name']))
+        else:
+            for k in list(block['implicit'].keys()):
+                if block['implicit'][k].get('typespec') not in ['static', 'automatic']:
+                    implicitrules[k]=block['implicit'][k]
+                else:
+                    attrrules[k]=block['implicit'][k]['typespec']
+    return implicitrules, attrrules
+
+def myeval(e,g=None,l=None):
+    r = eval(e, g, l)
+    if type(r) in [type(0), type(0.0)]:
+        return r
+    raise ValueError('r=%r' % (r))
+
+getlincoef_re_1 = re.compile(r'\A\b\w+\b\Z', re.I)
+def getlincoef(e, xset): # e = a*x+b ; x in xset
+    try:
+        c = int(myeval(e, {}, {}))
+        return 0, c, None
+    except: pass
+    if getlincoef_re_1.match(e):
+        return 1, 0, e
+    len_e = len(e)
+    for x in xset:
+        if len(x)>len_e: continue
+        if re.search(r'\w\s*\([^)]*\b'+x+r'\b', e):
+            # skip function calls having x as an argument, e.g max(1, x)
+            continue
+        re_1 = re.compile(r'(?P<before>.*?)\b'+x+r'\b(?P<after>.*)', re.I)
+        m = re_1.match(e)
+        if m:
+            try:
+                m1 = re_1.match(e)
+                while m1:
+                    ee = '%s(%s)%s'%(m1.group('before'), 0, m1.group('after'))
+                    m1 = re_1.match(ee)
+                b = myeval(ee, {}, {})
+                m1 = re_1.match(e)
+                while m1:
+                    ee = '%s(%s)%s'%(m1.group('before'), 1, m1.group('after'))
+                    m1 = re_1.match(ee)
+                a = myeval(ee, {}, {}) - b
+                m1 = re_1.match(e)
+                while m1:
+                    ee = '%s(%s)%s'%(m1.group('before'), 0.5, m1.group('after'))
+                    m1 = re_1.match(ee)
+                c = myeval(ee, {}, {})
+                # computing another point to be sure that expression is linear
+                m1 = re_1.match(e)
+                while m1:
+                    ee = '%s(%s)%s'%(m1.group('before'), 1.5, m1.group('after'))
+                    m1 = re_1.match(ee)
+                c2 = myeval(ee, {}, {})
+                if (a*0.5+b==c and a*1.5+b==c2):
+                    return a, b, x
+            except: pass
+            break
+    return None, None, None
+
+_varname_match = re.compile(r'\A[a-z]\w*\Z').match
+def getarrlen(dl,args,star='*'):
+    edl = []
+    try: edl.append(myeval(dl[0], {}, {}))
+    except: edl.append(dl[0])
+    try: edl.append(myeval(dl[1], {}, {}))
+    except: edl.append(dl[1])
+    if isinstance(edl[0], int):
+        p1 = 1-edl[0]
+        if p1==0: d = str(dl[1])
+        elif p1<0: d = '%s-%s'%(dl[1], -p1)
+        else: d = '%s+%s'%(dl[1], p1)
+    elif isinstance(edl[1], int):
+        p1 = 1+edl[1]
+        if p1==0: d='-(%s)' % (dl[0])
+        else: d='%s-(%s)' % (p1, dl[0])
+    else: d = '%s-(%s)+1'%(dl[1], dl[0])
+    try: return repr(myeval(d, {}, {})), None, None
+    except: pass
+    d1, d2=getlincoef(dl[0], args), getlincoef(dl[1], args)
+    if None not in [d1[0], d2[0]]:
+        if (d1[0], d2[0])==(0, 0):
+            return repr(d2[1]-d1[1]+1), None, None
+        b = d2[1] - d1[1] + 1
+        d1 = (d1[0], 0, d1[2])
+        d2 = (d2[0], b, d2[2])
+        if d1[0]==0 and d2[2] in args:
+            if b<0: return '%s * %s - %s'%(d2[0], d2[2], -b), d2[2], '+%s)/(%s)'%(-b, d2[0])
+            elif b: return '%s * %s + %s'%(d2[0], d2[2], b), d2[2], '-%s)/(%s)'%(b, d2[0])
+            else: return '%s * %s'%(d2[0], d2[2]), d2[2], ')/(%s)'%(d2[0])
+        if d2[0]==0 and d1[2] in args:
+
+            if b<0: return '%s * %s - %s'%(-d1[0], d1[2], -b), d1[2], '+%s)/(%s)'%(-b, -d1[0])
+            elif b: return '%s * %s + %s'%(-d1[0], d1[2], b), d1[2], '-%s)/(%s)'%(b, -d1[0])
+            else: return '%s * %s'%(-d1[0], d1[2]), d1[2], ')/(%s)'%(-d1[0])
+        if d1[2]==d2[2] and d1[2] in args:
+            a = d2[0] - d1[0]
+            if not a: return repr(b), None, None
+            if b<0: return '%s * %s - %s'%(a, d1[2], -b), d2[2], '+%s)/(%s)'%(-b, a)
+            elif b: return '%s * %s + %s'%(a, d1[2], b), d2[2], '-%s)/(%s)'%(b, a)
+            else: return '%s * %s'%(a, d1[2]), d2[2], ')/(%s)'%(a)
+        if d1[0]==d2[0]==1:
+            c = str(d1[2])
+            if c not in args:
+                if _varname_match(c):
+                    outmess('\tgetarrlen:variable "%s" undefined\n' % (c))
+                c = '(%s)'%c
+            if b==0: d='%s-%s' % (d2[2], c)
+            elif b<0: d='%s-%s-%s' % (d2[2], c, -b)
+            else: d='%s-%s+%s' % (d2[2], c, b)
+        elif d1[0]==0:
+            c2 = str(d2[2])
+            if c2 not in args:
+                if _varname_match(c2):
+                    outmess('\tgetarrlen:variable "%s" undefined\n' % (c2))
+                c2 = '(%s)'%c2
+            if d2[0]==1: pass
+            elif d2[0]==-1: c2='-%s' %c2
+            else: c2='%s*%s'%(d2[0], c2)
+
+            if b==0: d=c2
+            elif b<0: d='%s-%s' % (c2, -b)
+            else: d='%s+%s' % (c2, b)
+        elif d2[0]==0:
+            c1 = str(d1[2])
+            if c1 not in args:
+                if _varname_match(c1):
+                    outmess('\tgetarrlen:variable "%s" undefined\n' % (c1))
+                c1 = '(%s)'%c1
+            if d1[0]==1: c1='-%s'%c1
+            elif d1[0]==-1: c1='+%s'%c1
+            elif d1[0]<0: c1='+%s*%s'%(-d1[0], c1)
+            else: c1 = '-%s*%s' % (d1[0], c1)
+
+            if b==0: d=c1
+            elif b<0: d='%s-%s' % (c1, -b)
+            else: d='%s+%s' % (c1, b)
+        else:
+            c1 = str(d1[2])
+            if c1 not in args:
+                if _varname_match(c1):
+                    outmess('\tgetarrlen:variable "%s" undefined\n' % (c1))
+                c1 = '(%s)'%c1
+            if d1[0]==1: c1='-%s'%c1
+            elif d1[0]==-1: c1='+%s'%c1
+            elif d1[0]<0: c1='+%s*%s'%(-d1[0], c1)
+            else: c1 = '-%s*%s' % (d1[0], c1)
+
+            c2 = str(d2[2])
+            if c2 not in args:
+                if _varname_match(c2):
+                    outmess('\tgetarrlen:variable "%s" undefined\n' % (c2))
+                c2 = '(%s)'%c2
+            if d2[0]==1: pass
+            elif d2[0]==-1: c2='-%s' %c2
+            else: c2='%s*%s'%(d2[0], c2)
+
+            if b==0: d='%s%s' % (c2, c1)
+            elif b<0: d='%s%s-%s' % (c2, c1, -b)
+            else: d='%s%s+%s' % (c2, c1, b)
+    return d, None, None
+
+word_pattern = re.compile(r'\b[a-z][\w$]*\b', re.I)
+
+def _get_depend_dict(name, vars, deps):
+    if name in vars:
+        words = vars[name].get('depend', [])
+
+        if '=' in vars[name] and not isstring(vars[name]):
+            for word in word_pattern.findall(vars[name]['=']):
+                if word not in words and word in vars:
+                    words.append(word)
+        for word in words[:]:
+            for w in deps.get(word, []) \
+                    or _get_depend_dict(word, vars, deps):
+                if w not in words:
+                    words.append(w)
+    else:
+        outmess('_get_depend_dict: no dependence info for %s\n' % (repr(name)))
+        words = []
+    deps[name] = words
+    return words
+
+def _calc_depend_dict(vars):
+    names = list(vars.keys())
+    depend_dict = {}
+    for n in names:
+        _get_depend_dict(n, vars, depend_dict)
+    return depend_dict
+
+def get_sorted_names(vars):
+    """
+    """
+    depend_dict = _calc_depend_dict(vars)
+    names = []
+    for name in list(depend_dict.keys()):
+        if not depend_dict[name]:
+            names.append(name)
+            del depend_dict[name]
+    while depend_dict:
+        for name, lst in list(depend_dict.items()):
+            new_lst = [n for n in lst if n in depend_dict]
+            if not new_lst:
+                names.append(name)
+                del depend_dict[name]
+            else:
+                depend_dict[name] = new_lst
+    return [name for name in names if name in vars]
+
+def _kind_func(string):
+    #XXX: return something sensible.
+    if string[0] in "'\"":
+        string = string[1:-1]
+    if real16pattern.match(string):
+        return 8
+    elif real8pattern.match(string):
+        return 4
+    return 'kind('+string+')'
+
+def _selected_int_kind_func(r):
+    #XXX: This should be processor dependent
+    m = 10**r
+    if m<=2**8: return 1
+    if m<=2**16: return 2
+    if m<=2**32: return 4
+    if m<=2**63: return 8
+    if m<=2**128: return 16
+    return -1
+
+def _selected_real_kind_func(p, r=0, radix=0):
+    #XXX: This should be processor dependent
+    # This is only good for 0 <= p <= 20
+    if p < 7: return 4
+    if p < 16: return 8
+    if platform.machine().lower().startswith('power'):
+        if p <= 20:
+            return 16
+    else:
+        if p < 19:
+            return 10
+        elif p <= 20:
+            return 16
+    return -1
+
+def get_parameters(vars, global_params={}):
+    params = copy.copy(global_params)
+    g_params = copy.copy(global_params)
+    for name, func in [('kind', _kind_func),
+                      ('selected_int_kind', _selected_int_kind_func),
+                      ('selected_real_kind', _selected_real_kind_func),
+                      ]:
+        if name not in g_params:
+            g_params[name] = func
+    param_names = []
+    for n in get_sorted_names(vars):
+        if 'attrspec' in vars[n] and 'parameter' in vars[n]['attrspec']:
+            param_names.append(n)
+    kind_re = re.compile(r'\bkind\s*\(\s*(?P<value>.*)\s*\)', re.I)
+    selected_int_kind_re = re.compile(r'\bselected_int_kind\s*\(\s*(?P<value>.*)\s*\)', re.I)
+    selected_kind_re = re.compile(r'\bselected_(int|real)_kind\s*\(\s*(?P<value>.*)\s*\)', re.I)
+    for n in param_names:
+        if '=' in vars[n]:
+            v = vars[n]['=']
+            if islogical(vars[n]):
+                v = v.lower()
+                for repl in [
+                    ('.false.', 'False'),
+                    ('.true.', 'True'),
+                    #TODO: test .eq., .neq., etc replacements.
+                    ]:
+                    v = v.replace(*repl)
+            v = kind_re.sub(r'kind("\1")', v)
+            v = selected_int_kind_re.sub(r'selected_int_kind(\1)', v)
+            if isinteger(vars[n]) and not selected_kind_re.match(v):
+                v = v.split('_')[0]
+            if isdouble(vars[n]):
+                tt = list(v)
+                for m in real16pattern.finditer(v):
+                    tt[m.start():m.end()] = list(\
+                            v[m.start():m.end()].lower().replace('d', 'e'))
+                v = ''.join(tt)
+            if iscomplex(vars[n]):
+                if v[0]=='(' and v[-1]==')':
+                    l = markoutercomma(v[1:-1]).split('@,@')
+            try:
+                params[n] = eval(v, g_params, params)
+            except Exception as msg:
+                params[n] = v
+                #print params
+                outmess('get_parameters: got "%s" on %s\n' % (msg, repr(v)))
+            if isstring(vars[n]) and isinstance(params[n], int):
+                params[n] = chr(params[n])
+            nl = n.lower()
+            if nl!=n:
+                params[nl] = params[n]
+        else:
+            print(vars[n])
+            outmess('get_parameters:parameter %s does not have value?!\n'%(repr(n)))
+    return params
+
+def _eval_length(length, params):
+    if length in ['(:)', '(*)', '*']:
+        return '(*)'
+    return _eval_scalar(length, params)
+
+_is_kind_number = re.compile(r'\d+_').match
+
+def _eval_scalar(value, params):
+    if _is_kind_number(value):
+        value = value.split('_')[0]
+    try:
+        value = str(eval(value, {}, params))
+    except (NameError, SyntaxError):
+        return value
+    except Exception as msg:
+        errmess('"%s" in evaluating %r '\
+                '(available names: %s)\n' \
+                % (msg, value, list(params.keys())))
+    return value
+
+def analyzevars(block):
+    global f90modulevars
+    setmesstext(block)
+    implicitrules, attrrules=buildimplicitrules(block)
+    vars=copy.copy(block['vars'])
+    if block['block']=='function' and block['name'] not in vars:
+        vars[block['name']]={}
+    if '' in block['vars']:
+        del vars['']
+        if 'attrspec' in block['vars']['']:
+            gen=block['vars']['']['attrspec']
+            for n in list(vars.keys()):
+                for k in ['public', 'private']:
+                    if k in gen:
+                        vars[n]=setattrspec(vars[n], k)
+    svars=[]
+    args = block['args']
+    for a in args:
+        try:
+            vars[a]
+            svars.append(a)
+        except KeyError:
+            pass
+    for n in list(vars.keys()):
+        if n not in args: svars.append(n)
+
+    params = get_parameters(vars, get_useparameters(block))
+
+    dep_matches = {}
+    name_match = re.compile(r'\w[\w\d_$]*').match
+    for v in list(vars.keys()):
+        m = name_match(v)
+        if m:
+            n = v[m.start():m.end()]
+            try:
+                dep_matches[n]
+            except KeyError:
+                dep_matches[n] = re.compile(r'.*\b%s\b'%(v), re.I).match
+    for n in svars:
+        if n[0] in list(attrrules.keys()):
+            vars[n]=setattrspec(vars[n], attrrules[n[0]])
+        if 'typespec' not in vars[n]:
+            if not('attrspec' in vars[n] and 'external' in vars[n]['attrspec']):
+                if implicitrules:
+                    ln0 = n[0].lower()
+                    for k in list(implicitrules[ln0].keys()):
+                        if k=='typespec' and implicitrules[ln0][k]=='undefined':
+                            continue
+                        if k not in vars[n]:
+                            vars[n][k]=implicitrules[ln0][k]
+                        elif k=='attrspec':
+                            for l in implicitrules[ln0][k]:
+                                vars[n]=setattrspec(vars[n], l)
+                elif n in block['args']:
+                    outmess('analyzevars: typespec of variable %s is not defined in routine %s.\n'%(repr(n), block['name']))
+
+        if 'charselector' in vars[n]:
+            if 'len' in vars[n]['charselector']:
+                l = vars[n]['charselector']['len']
+                try:
+                    l = str(eval(l, {}, params))
+                except:
+                    pass
+                vars[n]['charselector']['len'] = l
+
+        if 'kindselector' in vars[n]:
+            if 'kind' in vars[n]['kindselector']:
+                l = vars[n]['kindselector']['kind']
+                try:
+                    l = str(eval(l, {}, params))
+                except:
+                    pass
+                vars[n]['kindselector']['kind'] = l
+
+        savelindims = {}
+        if 'attrspec' in vars[n]:
+            attr=vars[n]['attrspec']
+            attr.reverse()
+            vars[n]['attrspec']=[]
+            dim, intent, depend, check, note=None, None, None, None, None
+            for a in attr:
+                if a[:9]=='dimension': dim=(a[9:].strip())[1:-1]
+                elif a[:6]=='intent': intent=(a[6:].strip())[1:-1]
+                elif a[:6]=='depend': depend=(a[6:].strip())[1:-1]
+                elif a[:5]=='check': check=(a[5:].strip())[1:-1]
+                elif a[:4]=='note': note=(a[4:].strip())[1:-1]
+                else: vars[n]=setattrspec(vars[n], a)
+                if intent:
+                    if 'intent' not in vars[n]:
+                        vars[n]['intent']=[]
+                    for c in [x.strip() for x in markoutercomma(intent).split('@,@')]:
+                        # Remove spaces so that 'in out' becomes 'inout'
+                        tmp = c.replace(' ', '')
+                        if tmp not in vars[n]['intent']:
+                            vars[n]['intent'].append(tmp)
+                    intent=None
+                if note:
+                    note=note.replace('\\n\\n', '\n\n')
+                    note=note.replace('\\n ', '\n')
+                    if 'note' not in vars[n]:
+                        vars[n]['note']=[note]
+                    else:
+                        vars[n]['note'].append(note)
+                    note=None
+                if depend is not None:
+                    if 'depend' not in vars[n]:
+                        vars[n]['depend']=[]
+                    for c in rmbadname([x.strip() for x in markoutercomma(depend).split('@,@')]):
+                        if c not in vars[n]['depend']:
+                            vars[n]['depend'].append(c)
+                    depend=None
+                if check is not None:
+                    if 'check' not in vars[n]:
+                        vars[n]['check']=[]
+                    for c in [x.strip() for x in markoutercomma(check).split('@,@')]:
+                        if c not in vars[n]['check']:
+                            vars[n]['check'].append(c)
+                    check=None
+            if dim and 'dimension' not in vars[n]:
+                vars[n]['dimension']=[]
+                for d in rmbadname([x.strip() for x in markoutercomma(dim).split('@,@')]):
+                    star = '*'
+                    if d==':':
+                        star=':'
+                    if d in params:
+                        d = str(params[d])
+                    for p in list(params.keys()):
+                        m = re.match(r'(?P<before>.*?)\b'+p+r'\b(?P<after>.*)', d, re.I)
+                        if m:
+                            #outmess('analyzevars:replacing parameter %s in %s (dimension of %s) with %s\n'%(`p`,`d`,`n`,`params[p]`))
+                            d = m.group('before')+str(params[p])+m.group('after')
+                    if d==star:
+                        dl = [star]
+                    else:
+                        dl=markoutercomma(d, ':').split('@:@')
+                    if len(dl)==2 and '*' in dl: # e.g. dimension(5:*)
+                        dl = ['*']
+                        d = '*'
+                    if len(dl)==1 and not dl[0]==star: dl = ['1', dl[0]]
+                    if len(dl)==2:
+                        d, v, di = getarrlen(dl, list(block['vars'].keys()))
+                        if d[:4] == '1 * ': d = d[4:]
+                        if di and di[-4:] == '/(1)': di = di[:-4]
+                        if v: savelindims[d] = v, di
+                    vars[n]['dimension'].append(d)
+        if 'dimension' in vars[n]:
+            if isintent_c(vars[n]):
+                shape_macro = 'shape'
+            else:
+                shape_macro = 'shape'#'fshape'
+            if isstringarray(vars[n]):
+                if 'charselector' in vars[n]:
+                    d = vars[n]['charselector']
+                    if '*' in d:
+                        d = d['*']
+                        errmess('analyzevars: character array "character*%s %s(%s)" is considered as "character %s(%s)"; "intent(c)" is forced.\n'\
+                                %(d, n,
+                                  ','.join(vars[n]['dimension']),
+                                  n, ','.join(vars[n]['dimension']+[d])))
+                        vars[n]['dimension'].append(d)
+                        del vars[n]['charselector']
+                        if 'intent' not in vars[n]:
+                            vars[n]['intent'] = []
+                        if 'c' not in vars[n]['intent']:
+                            vars[n]['intent'].append('c')
+                    else:
+                        errmess("analyzevars: charselector=%r unhandled." % (d))
+        if 'check' not in vars[n] and 'args' in block and n in block['args']:
+            flag = 'depend' not in vars[n]
+            if flag:
+                vars[n]['depend']=[]
+            vars[n]['check']=[]
+            if 'dimension' in vars[n]:
+                #/----< no check
+                #vars[n]['check'].append('rank(%s)==%s'%(n,len(vars[n]['dimension'])))
+                i=-1; ni=len(vars[n]['dimension'])
+                for d in vars[n]['dimension']:
+                    ddeps=[] # dependecies of 'd'
+                    ad=''
+                    pd=''
+                    #origd = d
+                    if d not in vars:
+                        if d in savelindims:
+                            pd, ad='(', savelindims[d][1]
+                            d = savelindims[d][0]
+                        else:
+                            for r in block['args']:
+                            #for r in block['vars'].iterkeys():
+                                if r not in vars:
+                                    continue
+                                if re.match(r'.*?\b'+r+r'\b', d, re.I):
+                                    ddeps.append(r)
+                    if d in vars:
+                        if 'attrspec' in vars[d]:
+                            for aa in vars[d]['attrspec']:
+                                if aa[:6]=='depend':
+                                    ddeps += aa[6:].strip()[1:-1].split(',')
+                        if 'depend' in vars[d]:
+                            ddeps=ddeps+vars[d]['depend']
+                    i=i+1
+                    if d in vars and ('depend' not in vars[d]) \
+                       and ('=' not in vars[d]) and (d not in vars[n]['depend']) \
+                       and l_or(isintent_in, isintent_inout, isintent_inplace)(vars[n]):
+                        vars[d]['depend']=[n]
+                        if ni>1:
+                            vars[d]['=']='%s%s(%s,%s)%s'% (pd, shape_macro, n, i, ad)
+                        else:
+                            vars[d]['=']='%slen(%s)%s'% (pd, n, ad)
+                        #  /---< no check
+                        if 1 and 'check' not in vars[d]:
+                            if ni>1:
+                                vars[d]['check']=['%s%s(%s,%i)%s==%s'\
+                                                  %(pd, shape_macro, n, i, ad, d)]
+                            else:
+                                vars[d]['check']=['%slen(%s)%s>=%s'%(pd, n, ad, d)]
+                        if 'attrspec' not in vars[d]:
+                            vars[d]['attrspec']=['optional']
+                        if ('optional' not in vars[d]['attrspec']) and\
+                           ('required' not in vars[d]['attrspec']):
+                            vars[d]['attrspec'].append('optional')
+                    elif d not in ['*', ':']:
+                        #/----< no check
+                        #if ni>1: vars[n]['check'].append('shape(%s,%i)==%s'%(n,i,d))
+                        #else: vars[n]['check'].append('len(%s)>=%s'%(n,d))
+                        if flag:
+                            if d in vars:
+                                if n not in ddeps:
+                                    vars[n]['depend'].append(d)
+                            else:
+                                vars[n]['depend'] = vars[n]['depend'] + ddeps
+            elif isstring(vars[n]):
+                length='1'
+                if 'charselector' in vars[n]:
+                    if '*' in vars[n]['charselector']:
+                        length = _eval_length(vars[n]['charselector']['*'],
+                                              params)
+                        vars[n]['charselector']['*']=length
+                    elif 'len' in vars[n]['charselector']:
+                        length = _eval_length(vars[n]['charselector']['len'],
+                                              params)
+                        del vars[n]['charselector']['len']
+                        vars[n]['charselector']['*']=length
+
+            if not vars[n]['check']:
+                del vars[n]['check']
+            if flag and not vars[n]['depend']:
+                del vars[n]['depend']
+        if '=' in vars[n]:
+            if 'attrspec' not in vars[n]:
+                vars[n]['attrspec']=[]
+            if ('optional' not in vars[n]['attrspec']) and \
+               ('required' not in vars[n]['attrspec']):
+                vars[n]['attrspec'].append('optional')
+            if 'depend' not in vars[n]:
+                vars[n]['depend']=[]
+                for v, m in list(dep_matches.items()):
+                    if m(vars[n]['=']): vars[n]['depend'].append(v)
+                if not vars[n]['depend']: del vars[n]['depend']
+            if isscalar(vars[n]):
+                vars[n]['='] = _eval_scalar(vars[n]['='], params)
+
+    for n in list(vars.keys()):
+        if n==block['name']: # n is block name
+            if 'note' in vars[n]:
+                block['note']=vars[n]['note']
+            if block['block']=='function':
+                if 'result' in block and block['result'] in vars:
+                    vars[n]=appenddecl(vars[n], vars[block['result']])
+                if 'prefix' in block:
+                    pr=block['prefix']; ispure=0; isrec=1
+                    pr1=pr.replace('pure', '')
+                    ispure=(not pr==pr1)
+                    pr=pr1.replace('recursive', '')
+                    isrec=(not pr==pr1)
+                    m=typespattern[0].match(pr)
+                    if m:
+                        typespec, selector, attr, edecl=cracktypespec0(m.group('this'), m.group('after'))
+                        kindselect, charselect, typename=cracktypespec(typespec, selector)
+                        vars[n]['typespec']=typespec
+                        if kindselect:
+                            if 'kind' in kindselect:
+                                try:
+                                    kindselect['kind'] = eval(kindselect['kind'], {}, params)
+                                except:
+                                    pass
+                            vars[n]['kindselector']=kindselect
+                        if charselect: vars[n]['charselector']=charselect
+                        if typename: vars[n]['typename']=typename
+                        if ispure: vars[n]=setattrspec(vars[n], 'pure')
+                        if isrec: vars[n]=setattrspec(vars[n], 'recursive')
+                    else:
+                        outmess('analyzevars: prefix (%s) were not used\n'%repr(block['prefix']))
+    if not block['block'] in ['module', 'pythonmodule', 'python module', 'block data']:
+        if 'commonvars' in block:
+            neededvars=copy.copy(block['args']+block['commonvars'])
+        else:
+            neededvars=copy.copy(block['args'])
+        for n in list(vars.keys()):
+            if l_or(isintent_callback, isintent_aux)(vars[n]):
+                neededvars.append(n)
+        if 'entry' in block:
+            neededvars.extend(list(block['entry'].keys()))
+            for k in list(block['entry'].keys()):
+                for n in block['entry'][k]:
+                    if n not in neededvars:
+                        neededvars.append(n)
+        if block['block']=='function':
+            if 'result' in block:
+                neededvars.append(block['result'])
+            else:
+                neededvars.append(block['name'])
+        if block['block'] in ['subroutine', 'function']:
+            name = block['name']
+            if name in vars and 'intent' in vars[name]:
+                block['intent'] = vars[name]['intent']
+        if block['block'] == 'type':
+            neededvars.extend(list(vars.keys()))
+        for n in list(vars.keys()):
+            if n not in neededvars:
+                del vars[n]
+    return vars
+
+analyzeargs_re_1 = re.compile(r'\A[a-z]+[\w$]*\Z', re.I)
+def expr2name(a, block, args=[]):
+    orig_a = a
+    a_is_expr = not analyzeargs_re_1.match(a)
+    if a_is_expr: # `a` is an expression
+        implicitrules, attrrules=buildimplicitrules(block)
+        at=determineexprtype(a, block['vars'], implicitrules)
+        na='e_'
+        for c in a:
+            c = c.lower()
+            if c not in string.ascii_lowercase+string.digits: c='_'
+            na=na+c
+        if na[-1]=='_': na=na+'e'
+        else: na=na+'_e'
+        a=na
+        while a in block['vars'] or a in block['args']:
+            a=a+'r'
+    if a in args:
+        k = 1
+        while a + str(k) in args:
+            k = k + 1
+        a = a + str(k)
+    if a_is_expr:
+        block['vars'][a]=at
+    else:
+        if a not in block['vars']:
+            if orig_a in block['vars']:
+                block['vars'][a] = block['vars'][orig_a]
+            else:
+                block['vars'][a]={}
+        if 'externals' in block and orig_a in block['externals']+block['interfaced']:
+            block['vars'][a]=setattrspec(block['vars'][a], 'external')
+    return a
+
+def analyzeargs(block):
+    setmesstext(block)
+    implicitrules, attrrules=buildimplicitrules(block)
+    if 'args' not in block:
+        block['args']=[]
+    args=[]
+    for a in block['args']:
+        a = expr2name(a, block, args)
+        args.append(a)
+    block['args']=args
+    if 'entry' in block:
+        for k, args1 in list(block['entry'].items()):
+            for a in args1:
+                if a not in block['vars']:
+                    block['vars'][a]={}
+
+    for b in block['body']:
+        if b['name'] in args:
+            if 'externals' not in block:
+                block['externals']=[]
+            if b['name'] not in block['externals']:
+                block['externals'].append(b['name'])
+    if 'result' in block and block['result'] not in block['vars']:
+        block['vars'][block['result']]={}
+    return block
+
+determineexprtype_re_1 = re.compile(r'\A\(.+?[,].+?\)\Z', re.I)
+determineexprtype_re_2 = re.compile(r'\A[+-]?\d+(_(P<name>[\w]+)|)\Z', re.I)
+determineexprtype_re_3 = re.compile(r'\A[+-]?[\d.]+[\d+-de.]*(_(P<name>[\w]+)|)\Z', re.I)
+determineexprtype_re_4 = re.compile(r'\A\(.*\)\Z', re.I)
+determineexprtype_re_5 = re.compile(r'\A(?P<name>\w+)\s*\(.*?\)\s*\Z', re.I)
+def _ensure_exprdict(r):
+    if isinstance(r, int):
+        return {'typespec':'integer'}
+    if isinstance(r, float):
+        return {'typespec':'real'}
+    if isinstance(r, complex):
+        return {'typespec':'complex'}
+    if isinstance(r, dict):
+        return r
+    raise AssertionError(repr(r))
+
+def determineexprtype(expr,vars,rules={}):
+    if expr in vars:
+        return _ensure_exprdict(vars[expr])
+    expr=expr.strip()
+    if determineexprtype_re_1.match(expr):
+        return {'typespec':'complex'}
+    m=determineexprtype_re_2.match(expr)
+    if m:
+        if 'name' in m.groupdict() and m.group('name'):
+            outmess('determineexprtype: selected kind types not supported (%s)\n'%repr(expr))
+        return {'typespec':'integer'}
+    m = determineexprtype_re_3.match(expr)
+    if m:
+        if 'name' in m.groupdict() and m.group('name'):
+            outmess('determineexprtype: selected kind types not supported (%s)\n'%repr(expr))
+        return {'typespec':'real'}
+    for op in ['+', '-', '*', '/']:
+        for e in [x.strip() for x in markoutercomma(expr, comma=op).split('@'+op+'@')]:
+            if e in vars:
+                return _ensure_exprdict(vars[e])
+    t={}
+    if determineexprtype_re_4.match(expr): # in parenthesis
+        t=determineexprtype(expr[1:-1], vars, rules)
+    else:
+        m = determineexprtype_re_5.match(expr)
+        if m:
+            rn=m.group('name')
+            t=determineexprtype(m.group('name'), vars, rules)
+            if t and 'attrspec' in t:
+                del t['attrspec']
+            if not t:
+                if rn[0] in rules:
+                    return _ensure_exprdict(rules[rn[0]])
+    if expr[0] in '\'"':
+        return {'typespec':'character','charselector':{'*':'*'}}
+    if not t:
+        outmess('determineexprtype: could not determine expressions (%s) type.\n'%(repr(expr)))
+    return t
+
+######
+def crack2fortrangen(block,tab='\n', as_interface=False):
+    global skipfuncs, onlyfuncs
+    setmesstext(block)
+    ret=''
+    if isinstance(block, list):
+        for g in block:
+            if g and g['block'] in ['function', 'subroutine']:
+                if g['name'] in skipfuncs:
+                    continue
+                if onlyfuncs and g['name'] not in onlyfuncs:
+                    continue
+            ret=ret+crack2fortrangen(g, tab, as_interface=as_interface)
+        return ret
+    prefix=''
+    name=''
+    args=''
+    blocktype=block['block']
+    if blocktype=='program': return ''
+    argsl = []
+    if 'name' in block:
+        name=block['name']
+    if 'args' in block:
+        vars = block['vars']
+        for a in block['args']:
+            a = expr2name(a, block, argsl)
+            if not isintent_callback(vars[a]):
+                argsl.append(a)
+        if block['block']=='function' or argsl:
+            args='(%s)'%','.join(argsl)
+    f2pyenhancements = ''
+    if 'f2pyenhancements' in block:
+        for k in list(block['f2pyenhancements'].keys()):
+            f2pyenhancements = '%s%s%s %s'%(f2pyenhancements, tab+tabchar, k, block['f2pyenhancements'][k])
+    intent_lst = block.get('intent', [])[:]
+    if blocktype=='function' and 'callback' in intent_lst:
+        intent_lst.remove('callback')
+    if intent_lst:
+        f2pyenhancements = '%s%sintent(%s) %s'%\
+                           (f2pyenhancements, tab+tabchar,
+                            ','.join(intent_lst), name)
+    use=''
+    if 'use' in block:
+        use=use2fortran(block['use'], tab+tabchar)
+    common=''
+    if 'common' in block:
+        common=common2fortran(block['common'], tab+tabchar)
+    if name=='unknown_interface': name=''
+    result=''
+    if 'result' in block:
+        result=' result (%s)'%block['result']
+        if block['result'] not in argsl:
+            argsl.append(block['result'])
+    #if 'prefix' in block:
+    #    prefix=block['prefix']+' '
+    body=crack2fortrangen(block['body'], tab+tabchar)
+    vars=vars2fortran(block, block['vars'], argsl, tab+tabchar, as_interface=as_interface)
+    mess=''
+    if 'from' in block and not as_interface:
+        mess='! in %s'%block['from']
+    if 'entry' in block:
+        entry_stmts = ''
+        for k, i in list(block['entry'].items()):
+            entry_stmts = '%s%sentry %s(%s)' \
+                          % (entry_stmts, tab+tabchar, k, ','.join(i))
+        body = body + entry_stmts
+    if blocktype=='block data' and name=='_BLOCK_DATA_':
+        name = ''
+    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)
+    return ret
+
+def common2fortran(common,tab=''):
+    ret=''
+    for k in list(common.keys()):
+        if k=='_BLNK_':
+            ret='%s%scommon %s'%(ret, tab, ','.join(common[k]))
+        else:
+            ret='%s%scommon /%s/ %s'%(ret, tab, k, ','.join(common[k]))
+    return ret
+
+def use2fortran(use,tab=''):
+    ret=''
+    for m in list(use.keys()):
+        ret='%s%suse %s,'%(ret, tab, m)
+        if use[m]=={}:
+            if ret and ret[-1]==',': ret=ret[:-1]
+            continue
+        if 'only' in use[m] and use[m]['only']:
+            ret='%s only:'%(ret)
+        if 'map' in use[m] and use[m]['map']:
+            c=' '
+            for k in list(use[m]['map'].keys()):
+                if k==use[m]['map'][k]:
+                    ret='%s%s%s'%(ret, c, k); c=','
+                else:
+                    ret='%s%s%s=>%s'%(ret, c, k, use[m]['map'][k]); c=','
+        if ret and ret[-1]==',': ret=ret[:-1]
+    return ret
+
+def true_intent_list(var):
+    lst = var['intent']
+    ret = []
+    for intent in lst:
+        try:
+            c = eval('isintent_%s(var)' % intent)
+        except NameError:
+            c = 0
+        if c:
+            ret.append(intent)
+    return ret
+
+def vars2fortran(block,vars,args,tab='', as_interface=False):
+    """
+    TODO:
+    public sub
+    ...
+    """
+    setmesstext(block)
+    ret=''
+    nout=[]
+    for a in args:
+        if a in block['vars']:
+            nout.append(a)
+    if 'commonvars' in block:
+        for a in block['commonvars']:
+            if a in vars:
+                if a not in nout:
+                    nout.append(a)
+            else:
+                errmess('vars2fortran: Confused?!: "%s" is not defined in vars.\n'%a)
+    if 'varnames' in block:
+        nout.extend(block['varnames'])
+    if not as_interface:
+        for a in list(vars.keys()):
+            if a not in nout:
+                nout.append(a)
+    for a in nout:
+        if 'depend' in vars[a]:
+            for d in vars[a]['depend']:
+                if d in vars and 'depend' in vars[d] and a in vars[d]['depend']:
+                    errmess('vars2fortran: Warning: cross-dependence between variables "%s" and "%s"\n'%(a, d))
+        if 'externals' in block and a in block['externals']:
+            if isintent_callback(vars[a]):
+                ret='%s%sintent(callback) %s'%(ret, tab, a)
+            ret='%s%sexternal %s'%(ret, tab, a)
+            if isoptional(vars[a]):
+                ret='%s%soptional %s'%(ret, tab, a)
+            if a in vars and 'typespec' not in vars[a]:
+                continue
+            cont=1
+            for b in block['body']:
+                if a==b['name'] and b['block']=='function':
+                    cont=0;break
+            if cont:
+                continue
+        if a not in vars:
+            show(vars)
+            outmess('vars2fortran: No definition for argument "%s".\n'%a)
+            continue
+        if a==block['name'] and not block['block']=='function':
+            continue
+        if 'typespec' not in vars[a]:
+            if 'attrspec' in vars[a] and 'external' in vars[a]['attrspec']:
+                if a in args:
+                    ret='%s%sexternal %s'%(ret, tab, a)
+                continue
+            show(vars[a])
+            outmess('vars2fortran: No typespec for argument "%s".\n'%a)
+            continue
+        vardef=vars[a]['typespec']
+        if vardef=='type' and 'typename' in vars[a]:
+            vardef='%s(%s)'%(vardef, vars[a]['typename'])
+        selector={}
+        if 'kindselector' in vars[a]:
+            selector=vars[a]['kindselector']
+        elif 'charselector' in vars[a]:
+            selector=vars[a]['charselector']
+        if '*' in selector:
+            if selector['*'] in ['*', ':']:
+                vardef='%s*(%s)'%(vardef, selector['*'])
+            else:
+                vardef='%s*%s'%(vardef, selector['*'])
+        else:
+            if 'len' in selector:
+                vardef='%s(len=%s'%(vardef, selector['len'])
+                if 'kind' in selector:
+                    vardef='%s,kind=%s)'%(vardef, selector['kind'])
+                else:
+                    vardef='%s)'%(vardef)
+            elif 'kind' in selector:
+                vardef='%s(kind=%s)'%(vardef, selector['kind'])
+        c=' '
+        if 'attrspec' in vars[a]:
+            attr=[]
+            for l in vars[a]['attrspec']:
+                if l not in ['external']:
+                    attr.append(l)
+            if attr:
+                vardef='%s, %s'%(vardef, ','.join(attr))
+                c=','
+        if 'dimension' in vars[a]:
+#             if not isintent_c(vars[a]):
+#                 vars[a]['dimension'].reverse()
+            vardef='%s%sdimension(%s)'%(vardef, c, ','.join(vars[a]['dimension']))
+            c=','
+        if 'intent' in vars[a]:
+            lst = true_intent_list(vars[a])
+            if lst:
+                vardef='%s%sintent(%s)'%(vardef, c, ','.join(lst))
+            c=','
+        if 'check' in vars[a]:
+            vardef='%s%scheck(%s)'%(vardef, c, ','.join(vars[a]['check']))
+            c=','
+        if 'depend' in vars[a]:
+            vardef='%s%sdepend(%s)'%(vardef, c, ','.join(vars[a]['depend']))
+            c=','
+        if '=' in vars[a]:
+            v = vars[a]['=']
+            if vars[a]['typespec'] in ['complex', 'double complex']:
+                try:
+                    v = eval(v)
+                    v = '(%s,%s)' % (v.real, v.imag)
+                except:
+                    pass
+            vardef='%s :: %s=%s'%(vardef, a, v)
+        else:
+            vardef='%s :: %s'%(vardef, a)
+        ret='%s%s%s'%(ret, tab, vardef)
+    return ret
+######
+
+def crackfortran(files):
+    global usermodules
+    outmess('Reading fortran codes...\n', 0)
+    readfortrancode(files, crackline)
+    outmess('Post-processing...\n', 0)
+    usermodules=[]
+    postlist=postcrack(grouplist[0])
+    outmess('Post-processing (stage 2)...\n', 0)
+    postlist=postcrack2(postlist)
+    return usermodules+postlist
+
+def crack2fortran(block):
+    global f2py_version
+    pyf=crack2fortrangen(block)+'\n'
+    header="""!    -*- f90 -*-
+! Note: the context of this file is case sensitive.
+"""
+    footer="""
+! This file was auto-generated with f2py (version:%s).
+! See http://cens.ioc.ee/projects/f2py2e/
+"""%(f2py_version)
+    return header+pyf+footer
+
+if __name__ == "__main__":
+    files=[]
+    funcs=[]
+    f=1;f2=0;f3=0
+    showblocklist=0
+    for l in sys.argv[1:]:
+        if l=='': pass
+        elif l[0]==':':
+            f=0
+        elif l=='-quiet':
+            quiet=1
+            verbose=0
+        elif l=='-verbose':
+            verbose=2
+            quiet=0
+        elif l=='-fix':
+            if strictf77:
+                outmess('Use option -f90 before -fix if Fortran 90 code is in fix form.\n', 0)
+            skipemptyends=1
+            sourcecodeform='fix'
+        elif l=='-skipemptyends':
+            skipemptyends=1
+        elif l=='--ignore-contains':
+            ignorecontains=1
+        elif l=='-f77':
+            strictf77=1
+            sourcecodeform='fix'
+        elif l=='-f90':
+            strictf77=0
+            sourcecodeform='free'
+            skipemptyends=1
+        elif l=='-h':
+            f2=1
+        elif l=='-show':
+            showblocklist=1
+        elif l=='-m':
+            f3=1
+        elif l[0]=='-':
+            errmess('Unknown option %s\n'%repr(l))
+        elif f2:
+            f2=0
+            pyffilename=l
+        elif f3:
+            f3=0
+            f77modulename=l
+        elif f:
+            try:
+                open(l).close()
+                files.append(l)
+            except IOError as detail:
+                errmess('IOError: %s\n'%str(detail))
+        else:
+            funcs.append(l)
+    if not strictf77 and f77modulename and not skipemptyends:
+        outmess("""\
+  Warning: You have specifyied module name for non Fortran 77 code
+  that should not need one (expect if you are scanning F90 code
+  for non module blocks but then you should use flag -skipemptyends
+  and also be sure that the files do not contain programs without program statement).
+""", 0)
+
+    postlist=crackfortran(files, funcs)
+    if pyffilename:
+        outmess('Writing fortran code to file %s\n'%repr(pyffilename), 0)
+        pyf=crack2fortran(postlist)
+        f=open(pyffilename, 'w')
+        f.write(pyf)
+        f.close()
+    if showblocklist:
+        show(postlist)