def main(): fname_wrapper = 'cWrapper.f95' fname_signature = 'shtools.h' print('now cracking Fortran file ' + fname_wrapper + ' using f2py function...') crackfortran.verbose = False crackfortran.dolowercase = False cracked_shtools = crackfortran.crackfortran(fname_wrapper) with open(fname_signature, 'w') as outfile: outfile.write('#pragma once\n') outfile.write('namespace shtools{\n') outfile.write('extern "C"\n{\n') for subroutine in cracked_shtools: return_type = 'void' if subroutine['block'] == 'function': return_type = TYPEMAP[subroutine['vars'][subroutine['name']] ['typespec']] newline = return_type + ' ' + subroutine['name'] \ + '( ' + create_signature(subroutine) + ')' + ';' outfile.write(newline + '\n') outfile.write('}\n}\n') os.system('clang-format -i -style=Mozilla ' + fname_signature)
def test_defaultPrivate(self, tmp_path): f_path = tmp_path / "mod.f90" with f_path.open('w') as ff: ff.write( textwrap.dedent("""\ module foo private integer :: a public :: setA integer :: b contains subroutine setA(v) integer, intent(in) :: v a = v end subroutine setA end module foo """)) mod = crackfortran.crackfortran([str(f_path)]) assert len(mod) == 1 mod = mod[0] assert 'private' in mod['vars']['a']['attrspec'] assert 'public' not in mod['vars']['a']['attrspec'] assert 'private' in mod['vars']['b']['attrspec'] assert 'public' not in mod['vars']['b']['attrspec'] assert 'private' not in mod['vars']['seta']['attrspec'] assert 'public' in mod['vars']['seta']['attrspec']
def test_defaultPublic(self, tmp_path): f_path = tmp_path / "mod.f90" with f_path.open("w") as ff: ff.write( textwrap.dedent( """\ module foo public integer, private :: a public :: setA contains subroutine setA(v) integer, intent(in) :: v a = v end subroutine setA end module foo """ ) ) mod = crackfortran.crackfortran([str(f_path)]) assert len(mod) == 1 mod = mod[0] assert "private" in mod["vars"]["a"]["attrspec"] assert "public" not in mod["vars"]["a"]["attrspec"] assert "private" not in mod["vars"]["seta"]["attrspec"] assert "public" in mod["vars"]["seta"]["attrspec"]
def main(): fname_wrapper = 'PythonWrapper.f95' fname_signature = 'pyshtools.pyf' print('now cracking Fortran file SHTOOLS.f95 using f2py function...') crackfortran.verbose = False crackfortran.dolowercase = False cracked_shtools = crackfortran.crackfortran(fname_wrapper) for subroutine in cracked_shtools: subroutine['f2pyenhancements'] = \ {'fortranname': subroutine['name'].lower()} for subroutine in cracked_shtools: subroutine['name'] = subroutine['name'][2:] interface = { 'block': 'interface', 'name': 'unknown_interface', 'from': '', 'body': cracked_shtools, 'externals': [], 'interfaced': [], 'vars': {} } module = { 'block': 'python module', 'name': '_SHTOOLS', 'from': '', 'body': interface, 'externals': [], 'interfaced': [], 'vars': {} } out = crackfortran.crack2fortran(module) with open(fname_signature, 'w') as outfile: outfile.write(out)
def test_parse_abstract_interface(self): # Test gh18403 fpath = util.getpath("tests", "src", "abstract_interface", "gh18403_mod.f90") mod = crackfortran.crackfortran([str(fpath)]) assert len(mod) == 1 assert len(mod[0]["body"]) == 1 assert mod[0]["body"][0]["block"] == "abstract interface"
def test_access_type(self, tmp_path): fpath = util.getpath("tests", "src", "crackfortran", "accesstype.f90") mod = crackfortran.crackfortran([str(fpath)]) assert len(mod) == 1 tt = mod[0]['vars'] assert set(tt['a']['attrspec']) == {'private', 'bind(c)'} assert set(tt['b_']['attrspec']) == {'public', 'bind(c)'} assert set(tt['c']['attrspec']) == {'public'}
def test_defaultPublic(self, tmp_path): fpath = util.getpath("tests", "src", "crackfortran", "publicmod.f90") mod = crackfortran.crackfortran([str(fpath)]) assert len(mod) == 1 mod = mod[0] assert "private" in mod["vars"]["a"]["attrspec"] assert "public" not in mod["vars"]["a"]["attrspec"] assert "private" not in mod["vars"]["seta"]["attrspec"] assert "public" in mod["vars"]["seta"]["attrspec"]
def make_signature(filename): info = crackfortran.crackfortran(filename)[0] name = info['name'] if info['block'] == 'subroutine': return_type = 'void' else: return_type = get_type(info, name) arglist = [' *'.join([get_type(info, arg), arg]) for arg in info['args']] args = ', '.join(arglist) # Eliminate strange variable naming that replaces rank with rank_bn. args = args.replace('rank_bn', 'rank') return '{0} {1}({2})\n'.format(return_type, name, args)
def test_input_encoding(self, tmp_path, encoding): # gh-635 f_path = tmp_path / f"input_with_{encoding}_encoding.f90" # explicit BOM is required for UTF8 bom = {'utf-8': codecs.BOM_UTF8}.get(encoding, b'') with f_path.open('w', encoding=encoding) as ff: ff.write( bom.decode(encoding) + """ subroutine foo() end subroutine foo """) mod = crackfortran.crackfortran([str(f_path)]) assert mod[0]['name'] == 'foo'
def test_notPublicPrivate(self, tmp_path): fpath = util.getpath("tests", "src", "crackfortran", "pubprivmod.f90") mod = crackfortran.crackfortran([str(fpath)]) assert len(mod) == 1 mod = mod[0] assert mod['vars']['a']['attrspec'] == [ 'private', ] assert mod['vars']['b']['attrspec'] == [ 'public', ] assert mod['vars']['seta']['attrspec'] == [ 'public', ]
def test_dependencies(self, tmp_path): f_path = tmp_path / "mod.f90" with f_path.open('w') as ff: ff.write( textwrap.dedent("""\ module foo type bar character(len = 4) :: text end type bar type(bar), parameter :: abar = bar('abar') end module foo """)) mod = crackfortran.crackfortran([str(f_path)]) assert len(mod) == 1 assert mod[0]['vars']['abar']['='] == "bar('abar')"
def test_parse_abstract_interface(self, tmp_path): # Test gh18403 f_path = tmp_path / "gh18403_mod.f90" with f_path.open('w') as ff: ff.write(textwrap.dedent("""\ module test abstract interface subroutine foo() end subroutine end interface end module test """)) mod = crackfortran.crackfortran([str(f_path)]) assert len(mod) == 1 assert len(mod[0]['body']) == 1 assert mod[0]['body'][0]['block'] == 'abstract interface'
def test_moduleOperators(self, tmp_path): fpath = util.getpath("tests", "src", "crackfortran", "operators.f90") mod = crackfortran.crackfortran([str(fpath)]) assert len(mod) == 1 mod = mod[0] assert "body" in mod and len(mod["body"]) == 9 assert mod["body"][1]["name"] == "operator(.item.)" assert "implementedby" in mod["body"][1] assert mod["body"][1]["implementedby"] == \ ["item_int", "item_real"] assert mod["body"][2]["name"] == "operator(==)" assert "implementedby" in mod["body"][2] assert mod["body"][2]["implementedby"] == ["items_are_equal"] assert mod["body"][3]["name"] == "assignment(=)" assert "implementedby" in mod["body"][3] assert mod["body"][3]["implementedby"] == \ ["get_int", "get_real"]
def main(): fname_wrapper = 'PythonWrapper.f95' fname_signature = 'pyshtools.pyf' print('now cracking Fortran file SHTOOLS.f95 using f2py function...') crackfortran.verbose = False crackfortran.dolowercase = False cracked_shtools = crackfortran.crackfortran(fname_wrapper) for subroutine in cracked_shtools: subroutine['f2pyenhancements'] = {'fortranname': subroutine['name'].lower()} for subroutine in cracked_shtools: subroutine['name'] = subroutine['name'][2:] interface = {'block': 'interface', 'name': 'unknown_interface', 'from': '', 'body': cracked_shtools, 'externals': [], 'interfaced': [], 'vars': {}} module = {'block': 'python module', 'name': '_SHTOOLS', 'from': '', 'body': interface, 'externals': [], 'interfaced': [], 'vars': {}} out = crackfortran.crack2fortran(module) with open(fname_signature, 'w') as outfile: outfile.write(out)
# - final setup if len(site_libs): libs = site_libs if len(site_libdirs): libdirs.extend(site_libdirs) # Special setups extra_link_args=[] if sys.platform=='darwin': extra_link_args += ['-bundle','-bundle_loader '+sys.prefix+'/bin/python'] kwext = dict(libraries=libs, library_dirs=libdirs, extra_link_args=extra_link_args) if __name__=='__main__': # Generate pyf files crackfortran.f77modulename = '_core' pyfcode = crackfortran.crack2fortran(crackfortran.crackfortran(['lib/spanlib/spanlib_pywrap.f90'])) f = open('lib/spanlib/spanlib.pyf', 'w') f.write(pyfcode) f.close() crackfortran.f77modulename = 'anaxv' pyfcode = crackfortran.crack2fortran(crackfortran.crackfortran(['lib/spanlib/anaxv.f90'])) f = open('lib/spanlib/anaxv.pyf', 'w') f.write(pyfcode) f.close() # Setup the python module s = setup(name="spanlib", version=version, description=description, author=author, author_email=author_email,
def create(file_name): """ Function to create ERSEM module index everytime the docs are built :param file_name: file name of the api :type file_name: str """ main_header = "ERSEM module index" heading_boarder = "#" * len(main_header) index_str = ".. _api:\n\n{}\n{}\n{}\n\n".format(heading_boarder, main_header, heading_boarder) structure = ["include", "!", "module", "extends"] f = io.StringIO() # removing standard output from console with redirect_stdout(f): for fname in glob.glob("../../src/*.F90"): if fname != "../../src/shared.F90": with open(fname, "r") as f: file_contence = f.readlines() module_dict = {"include": [], "!": [], "module": [], "extends": []} for line in file_contence: check = [s in line for s in structure] index = where(check)[0] if len(index) > 0: key = structure[index[0]] value = line.split(key)[1][1:].strip("\n") if key == "extends": value = value.split(")")[0] module_dict[key].append(value) if "extends" in line: break module_dict["class inheritance"] = module_dict.pop("extends") module_dict["description"] = module_dict.pop("!") module_str = "Module name: {}\n{}\n\n".format( module_dict["module"][0], (len(module_dict["module"][0]) + 13) * "~") module_dict.pop('module', None) indent = " " * 4 for key, item in module_dict.items(): if key == "description": list_str = \ "\n".join(item).replace("\n", "\n" + indent * 2) else: list_str = f"\n{2*indent}.. code-block:: bash \n\n{indent*4}" + \ "\n".join(item).replace("\n", "\n" + indent * 4) module_str += f"{indent}**{key.capitalize()}**:\n{indent*2}{list_str}\n\n" # Find additional functions within module interface = [sub["saved_interface"].split("\n")[1:-1] for sub in crackfortran(fname)[0]["body"] if sub["block"] in ["function"]] if interface != []: subroutines = [] for i in interface: joined_str = "\n".join(i) subroutines.append(".. code-block:: bash \n\n" + joined_str) func_str = "{}**Functions**:\n\n{}".format(indent, "\n".join(subroutines)) module_str += func_str.replace("\n", "\n" + indent * 2) +"\n" index_str += module_str with open(file_name, "w") as index_file: index_file.write(index_str)
#it uses the crackfortran module import os import numpy.f2py.crackfortran as cf srcpath = '../src' filelist = os.listdir(srcpath) print filelist filelist2=[] for fname in filelist: filelist2.append(srcpath + '/' + fname) for fname in filelist2: print fname postlist = cf.crackfortran(filelist2[:-1]) def dimlst2str(dimlst): s = '(' for dm in dimlst: s += dm + ',' s = s[:-1] + ')' if 'njas' in s: print dimlst return s for b in postlist: print 'Blockname: ', b['name'] if b.has_key('vars'): for varname in b['vars'].keys(): d = b['vars'][varname] s = ''
def main(): fname_fortran = 'SHTOOLS.f95' fname_wrapper = 'cWrapper.f95' explicite_dims_file = "explicite_dimensions.yml" with open(explicite_dims_file, 'r') as exp_dim_fid: explicite_dims = yaml.safe_load(exp_dim_fid.read()) print('now cracking Fortran file SHTOOLS.f95 using f2py function...') crackfortran.verbose = False crackfortran.dolowercase = False cracked_shtools = crackfortran.crackfortran(fname_fortran) print('decending through shtools module tree...') module = cracked_shtools[0] interface_old = module['body'][0] interface_new = deepcopy(interface_old) for subroutine in interface_new['body']: if subroutine['name'] in explicite_dims: modify_subroutine(subroutine, explicite_dims[subroutine['name']]) else: modify_subroutine(subroutine) print('create interface string...') wrapper = crackfortran.crack2fortran(interface_new) wrapperlines = wrapper.split('\n') # search for the indices of 'use shtools,' to insert 'implicit none' after iusestatement = [ iline for iline, line in enumerate(wrapperlines) if 'use shtools,' in line ] assert len(iusestatement) == len(interface_new['body']), \ 'number of subroutines don\'t match' # search for the indices of 'end subroutine' iendsubroutine = [ iline for iline, line in enumerate(wrapperlines) if 'end subroutine' in line or 'end function' in line ] assert len(iendsubroutine) == len(interface_new['body']), \ 'number of subroutines don\'t match' print('sort variables...') for i in range(len(iusestatement)): declaration = wrapperlines[iusestatement[i] + 1:iendsubroutine[i]] current_order = [(line.split('::')[1]).strip() for line in declaration] order = interface_new['body'][i]['sortvars'] idx = [] for j in range(len(order)): idx.append(current_order.index(order[j])) declaration[:] = [declaration[k] for k in idx] wrapperlines[iusestatement[i] + 1:iendsubroutine[i]] = declaration[:] print('add implicit none statements') for iline in iusestatement[::-1]: wrapperlines.insert(iline + 1, 2 * crackfortran.tabchar + 'implicit none') print('add shtools subroutine calls...') # search for the indices of 'end subroutine' iendsubroutine = [ iline for iline, line in enumerate(wrapperlines) if 'end subroutine' in line or 'end function' in line ] assert len(iendsubroutine) == len(interface_new['body']), \ 'number of subroutines don\'t match' # insert call statements before 'end subroutine' line starting from the # end such that we don't change the preceding indices for sroutine_new, sroutine_old, iline in list( zip(interface_new['body'], interface_old['body'], iendsubroutine))[::-1]: args = create_arg_list(sroutine_old) if sroutine_new['block'] == 'function': newline = 2 * crackfortran.tabchar +\ '%s=%s(' % (sroutine_new['name'], sroutine_old['name']) +\ args+ ')' elif sroutine_new['block'] == 'subroutine': newline = 2 * crackfortran.tabchar +\ 'call %s(' % sroutine_old['name'] +\ args+ ')' wrapperlines.insert(iline + 1, '') wrapperlines.insert(iline, newline) print('add bind statment...') p = re.compile('\s*(subroutine|function)') # search for the indices of 'subroutine' isubroutine = [ iline for iline, line in enumerate(wrapperlines) if p.match(line) is not None ] assert len(isubroutine) == len(interface_new['body']), \ 'number of subroutines don\'t match' for sroutine_new, sroutine_old, iline in list( zip(interface_new['body'], interface_old['body'], isubroutine))[::-1]: wrapperlines[iline] = wrapperlines[iline] + ' bind(c, name=\"' \ + sroutine_old['name'] + '\")' newline = 2 * crackfortran.tabchar + 'use, intrinsic :: iso_c_binding' wrapperlines.insert(iline + 1, newline) print('writing wrapper to file %s' % fname_wrapper) for iline, line in enumerate(wrapperlines): try: firstword = line.split()[0] secondword = line.split()[1] words = [ 'real(kind=c_double)', 'complex(kind=c_double_complex)', 'integer(kind=c_int)', 'character(kind=c_char)', 'real(kind=8)', 'real*8', 'integer', 'integer(kind=4)', 'character*(*)', 'complex*16' ] for word in words: if (firstword == word and not secondword[0] == ':' or secondword[0] == ','): line = line.replace(word, word + ',') wrapperlines[iline] = line except IndexError: pass with open(fname_wrapper, 'w') as outfile: for line in wrapperlines[4:-5]: line = line.replace('! in SHTOOLS.f95:SHTOOLS:unknown_interface', '') if len(line) <= 80: outfile.write(line + '\n') else: elems = line.split(',') newline = elems[0] for elem in elems[1:]: if len(newline) > 80: outfile.write(newline + '&\n') newline = ' ' * len(elems[0]) newline += ',' + elem outfile.write(newline + '\n') print('\n==== ALL DONE ====\n')
def test_dependencies(self, tmp_path): fpath = util.getpath("tests", "src", "crackfortran", "foo_deps.f90") mod = crackfortran.crackfortran([str(fpath)]) assert len(mod) == 1 assert mod[0]["vars"]["abar"]["="] == "bar('abar')"
def main(): fname_fortran = 'SHTOOLS.f95' fname_wrapper = 'PythonWrapper.f95' outfile = open(fname_wrapper, 'w') print 'now cracking Fortran file SHTOOLS.f95 using f2py function...' crackfortran.verbose = False crackfortran.dolowercase = False cracked_shtools = crackfortran.crackfortran(fname_fortran) print 'decending through shtools module tree...' module = cracked_shtools[0] interface_old = module['body'][0] interface_new = deepcopy(interface_old) for subroutine in interface_new['body']: modify_subroutine(subroutine) print 'create interface string...' wrapper = crackfortran.crack2fortran(interface_new) wrapperlines = wrapper.split('\n') print 'add implicit none statements' # search for the indices of 'use shtools,' to insert 'implicit none' after iusestatement = [iline for iline, line in enumerate(wrapperlines) if 'use shtools,' in line] assert len(iusestatement) == len(interface_new['body']), 'number of subroutines don\'t match' for iline in iusestatement[::-1]: wrapperlines.insert(iline + 1, 2 * crackfortran.tabchar + 'implicit none') print 'add shtools subroutine calls...' # search for the indices of 'end subroutine' iendsubroutine = [iline for iline, line in enumerate(wrapperlines) if 'end subroutine' in line or 'end function' in line] assert len(iendsubroutine) == len(interface_new['body']), 'number of subroutines don\'t match' # insert call statements before 'end subroutine' line starting from the end such that we # don't change the preceding indices for sroutine_new, sroutine_old, iline in zip(interface_new['body'], interface_old['body'], iendsubroutine)[::-1]: if sroutine_new['block'] == 'function': newline = 2 * crackfortran.tabchar +\ '%s=%s(' % (sroutine_new['name'], sroutine_old['name']) +\ ','.join(sroutine_old['args']) + ')' elif sroutine_new['block'] == 'subroutine': newline = 2 * crackfortran.tabchar +\ 'call %s(' % sroutine_old['name'] +\ ','.join(sroutine_old['args']) + ')' wrapperlines.insert(iline + 1, '') wrapperlines.insert(iline, newline) print 'writing wrapper to file %s' % fname_wrapper for iline, line in enumerate(wrapperlines): try: firstword = line.split()[0] secondword = line.split()[1] words = ['real*8', 'integer', 'integer(kind=4)', 'character*(*)', 'complex*16'] for word in words: if firstword == word and not secondword[0] == ':' or secondword[0] == ',': line = line.replace(word, word + ',') wrapperlines[iline] = line except IndexError: pass for line in wrapperlines[4:-5]: line = line.replace('! in SHTOOLS.f95:SHTOOLS:unknown_interface', '') if len(line) <= 100: outfile.write(line + '\n') else: elems = line.split(',') newline = elems[0] for elem in elems[1:]: if len(newline) > 100: outfile.write(newline + '&\n') newline = ' ' * len(elems[0]) newline += ',' + elem outfile.write(newline + '\n') outfile.close() print '\n==== ALL DONE ====\n'
def to_magma(fin, module, magma_src, ignore_func=[]): if magma_src: magma_impl = [ f[:-4] for f in os.listdir(magma_src) if f.endswith('.cpp') ] else: magma_impl = [] ignores = [] blocks = crackfortran([fin]) cfile = [] cfile.append('#include <cuda.h>') cfile.append('#include "magma_v2.h"') cfile.append('#include <stdio.h>') cfile.append('#include <stdlib.h>') cfile.append('typedef struct {float r,i;} complex_float;') cfile.append('typedef struct {double r,i;} complex_double;') for func in blocks[0]['body'][0]['body']: name = func['name'] ignore = False for func_name in ignore_func: startswith = False endswith = False if func_name[0] == '*': endsswith = True func_name = func_name[1:] if func_name[-1] == '*': startswith = True func_name = func_name[:-1] if startswith: if name.startswith(func_name): ignore = True print(f'{name} ignored because starts with {func_name}') if endswith: if name.endswith(func_name): ignore = True print(f'{name} ignored because ends with {func_name}') if name == func_name: ignore = True print(f'{name} ignored because equals {func_name}') if name not in magma_impl: ignore = True print(f'{name} ignored because not found in MAGMA') if not ignore: if 'f2pyenhancements' in func: types = func['f2pyenhancements']['callprotoargument'].split( ',') else: types = get_types(func['saved_interface']) magma_types, params, convs = get_magma_types(magma_src, name) if len(types) != len(magma_types): # not the same number of parameters, ignore this function ignore = True print( f'{name} ignored because parameters between LAPACK and MAGMA mismatch' ) if ignore: ignores.append(name) else: cwrap = [] proto = [] proto.append(f'void _magma_{name}(') proto.append(', '.join([f'{t} {p}' for t, p in zip(types, params)])) proto.append(') {') cwrap.append(''.join(proto)) cwrap.append('#ifdef SCIPY_GPU_DEBUG') cwrap.append(f' fprintf(stderr, "GPU {name}\\n");') for p, t in zip(params, types): pt = {'char*': 'c', 'int*': 'd'}.get(t, None) if pt: cwrap.append(f' fprintf(stderr, "{p}=%{pt}\\n", *{p});') cwrap.append('#endif') # MAGMA function call margs = [] for p, t, mt, c in zip(params, types, magma_types, convs): if c: ma = f'_magma_{p}_' cwrap.append(f' {c}') elif t == mt: ma = p else: ma = f'*{p}' margs.append(ma) margs = ', '.join(margs) cwrap.append(f' magma_{name}({margs});') cwrap.append('}') cwrap = '\n'.join(cwrap) cfile.append(cwrap) with open(f'to_magma.c', 'wt') as f: f.write('\n'.join(cfile)) with open(module) as f: clines = f.readlines() new_clines = [] first_extern = True s0 = 'extern void F_FUNC(' s1 = 'F_FUNC(' for l in clines: line_done = False if not line_done: if (s0 in l) and not l.startswith('/*'): if first_extern: first_extern = False new_clines.append('extern void magma_init();\n') new_clines.append('extern void magma_finalize();\n') i0 = l.find(s0) + len(s0) i1 = l.find(',') name = l[i0:i1] i2 = l.find(')') if name not in ignores: line_done = True new_l = f'extern void _magma_{name}' + l[i2 + 1:] new_clines.append(new_l) if not line_done: if (s1 in l) and ('f2py_init_func') in l: i0 = l.find(s1) i1 = i0 + len(s1) i2 = l[i1:].find(',') + i1 name = l[i1:i2] i3 = l[i1:].find(')') + i1 if name not in ignores: line_done = True new_l = l[:i0] + f'_magma_{name}' + l[i3 + 1:] new_clines.append(new_l) if not line_done: new_clines.append(l) i = len(new_clines) done = False while not done: i -= 1 if 'return RETVAL;' in new_clines[i]: new_clines.insert(i, ' magma_init();\n') new_clines.insert( i, ' on_exit(magma_finalize,(void*)"_flapack");\n') done = True with open(module, 'wt') as f: f.write(''.join(new_clines))
# Special setups extra_link_args = [] if sys.platform == 'darwin': extra_link_args += [ '-bundle', '-bundle_loader ' + sys.prefix + '/bin/python' ] kwext = dict(libraries=libs, library_dirs=libdirs, extra_link_args=extra_link_args) if __name__ == '__main__': # Generate pyf files crackfortran.f77modulename = '_core' pyfcode = crackfortran.crack2fortran( crackfortran.crackfortran(['lib/spanlib/spanlib_pywrap.f90'])) f = open('lib/spanlib/spanlib.pyf', 'w') f.write(pyfcode) f.close() crackfortran.f77modulename = 'anaxv' pyfcode = crackfortran.crack2fortran( crackfortran.crackfortran(['lib/spanlib/anaxv.f90'])) f = open('lib/spanlib/anaxv.pyf', 'w') f.write(pyfcode) f.close() # Setup the python module s = setup( name="spanlib", version=version, description=description,
def main(): fname_fortran = 'SHTOOLS.f95' fname_wrapper = 'PythonWrapper.f95' outfile = open(fname_wrapper, 'w') print 'now cracking Fortran file SHTOOLS.f95 using f2py function...' crackfortran.verbose = False crackfortran.dolowercase = False cracked_shtools = crackfortran.crackfortran(fname_fortran) print 'decending through shtools module tree...' module = cracked_shtools[0] interface_old = module['body'][0] interface_new = deepcopy(interface_old) for subroutine in interface_new['body']: modify_subroutine(subroutine) print 'create interface string...' wrapper = crackfortran.crack2fortran(interface_new) wrapperlines = wrapper.split('\n') print 'add implicit none statements' # search for the indices of 'use shtools,' to insert 'implicit none' after iusestatement = [ iline for iline, line in enumerate(wrapperlines) if 'use shtools,' in line ] assert len(iusestatement) == len( interface_new['body']), 'number of subroutines don\'t match' for iline in iusestatement[::-1]: wrapperlines.insert(iline + 1, 2 * crackfortran.tabchar + 'implicit none') print 'add shtools subroutine calls...' # search for the indices of 'end subroutine' iendsubroutine = [ iline for iline, line in enumerate(wrapperlines) if 'end subroutine' in line or 'end function' in line ] assert len(iendsubroutine) == len( interface_new['body']), 'number of subroutines don\'t match' # insert call statements before 'end subroutine' line starting from the end such that we # don't change the preceding indices for sroutine_new, sroutine_old, iline in zip(interface_new['body'], interface_old['body'], iendsubroutine)[::-1]: if sroutine_new['block'] == 'function': newline = 2 * crackfortran.tabchar +\ '%s=%s(' % (sroutine_new['name'], sroutine_old['name']) +\ ','.join(sroutine_old['args']) + ')' elif sroutine_new['block'] == 'subroutine': newline = 2 * crackfortran.tabchar +\ 'call %s(' % sroutine_old['name'] +\ ','.join(sroutine_old['args']) + ')' wrapperlines.insert(iline + 1, '') wrapperlines.insert(iline, newline) print 'writing wrapper to file %s' % fname_wrapper for iline, line in enumerate(wrapperlines): try: firstword = line.split()[0] secondword = line.split()[1] words = [ 'real*8', 'integer', 'integer(kind=4)', 'character*(*)', 'complex*16' ] for word in words: if firstword == word and not secondword[ 0] == ':' or secondword[0] == ',': line = line.replace(word, word + ',') wrapperlines[iline] = line except IndexError: pass for line in wrapperlines[4:-5]: line = line.replace('! in SHTOOLS.f95:SHTOOLS:unknown_interface', '') if len(line) <= 100: outfile.write(line + '\n') else: elems = line.split(',') newline = elems[0] for elem in elems[1:]: if len(newline) > 100: outfile.write(newline + '&\n') newline = ' ' * len(elems[0]) newline += ',' + elem outfile.write(newline + '\n') outfile.close() print '\n==== ALL DONE ====\n'
def process_fortran(filename): infos = [] # read comments to obtain dimension information dimension_info = {} intent_info = {} with open(filename, "r") as f: text = f.read() for line in text.splitlines(): m = re.match( r"^\*>\s+([A-Z]+) is INTEGER array, dimension \(([A-Z]+)\)\.?\s*$", line, flags=re.I, ) if m: dimension_info[m.group(1).lower()] = ("var", m.group(2).lower()) m = re.match( r"^\*>\s+([A-Z]+) is INTEGER array, dimension \(min\(([A-Z]+),([A-Z]+)\)\)\.?\s*$", line, flags=re.I, ) if m: dimension_info[m.group(1).lower()] = ( "min", m.group(2).lower(), m.group(3).lower(), ) m = re.match( r"^\*>\s+([A-Z]+) is INTEGER array, dimension \(([0-9]+)\*min\(([A-Z]+),([A-Z]+)\)\)\.?\s*$", line, flags=re.I, ) if m: dimension_info[m.group(1).lower()] = ( "mulmin", int(m.group(2).lower()), m.group(3).lower(), m.group(4).lower(), ) m = re.match( r"^\*>\s+([A-Z]+) is INTEGER array, dimension \(max\(1,([A-Z]+)\)\)\.?\s*$", line, flags=re.I, ) if m: dimension_info[m.group(1).lower()] = ("var", m.group(2).lower()) m = re.match( r"^\*>\s+\\param\[(in|out|in,out)\]\s+([A-Z]+)\s*$", line, flags=re.I, ) if m: intent_info[m.group(2).lower()] = m.group(1).split(",") # parse with f2py for info in crackfortran(filename): # Drop unnecessary info for kw in [ "body", "entry", "externals", "from", "interfaced", "sortvars" ]: info.pop(kw, None) for varname, varinfo in info["vars"].items(): for kw in ["check", "depend", "=", "attrspec"]: varinfo.pop(kw, None) # Determine integer array dimensions, if possible for varname, varinfo in info["vars"].items(): if varinfo["typespec"] != "integer": continue dims = varinfo.get("dimension", []) if dims == ["*"]: dt, *di = dimension_info.get(varname, (None, None)) if dt == "var" and di[0] in info["vars"]: varinfo["dimension"] = di if dt == "min" and di[0] in info["vars"] and di[1] in info[ "vars"]: varinfo["dimension"] = [{"min": di}] if dt == "mulmin" and di[1] in info["vars"] and di[2] in info[ "vars"]: varinfo["dimension"] = [{"mulmin": di}] if varname in intent_info: varinfo["intent"] = intent_info[varname] infos.append(info) return filename, infos