/scipy/linalg/interface_gen.py
Python | 162 lines | 157 code | 3 blank | 2 comment | 0 complexity | a4c634adb3c057408912105339377db7 MD5 | raw file
- #!/usr/bin/env python
- import os
- import re
- from distutils.dir_util import mkpath
- def all_subroutines(interface_in):
- # remove comments
- comment_block_exp = re.compile(r'/\*(?:\s|.)*?\*/')
- subroutine_exp = re.compile(r'subroutine (?:\s|.)*?end subroutine.*')
- function_exp = re.compile(r'function (?:\s|.)*?end function.*')
- interface = comment_block_exp.sub('',interface_in)
- subroutine_list = subroutine_exp.findall(interface)
- function_list = function_exp.findall(interface)
- subroutine_list = subroutine_list + function_list
- subroutine_list = map(lambda x: x.strip(),subroutine_list)
- return subroutine_list
- def real_convert(val_string):
- return val_string
- def complex_convert(val_string):
- return '(' + val_string + ',0.)'
- def convert_types(interface_in,converter):
- regexp = re.compile(r'<type_convert=(.*?)>')
- interface = interface_in[:]
- while 1:
- sub = regexp.search(interface)
- if sub is None: break
- converted = converter(sub.group(1))
- interface = interface.replace(sub.group(),converted)
- return interface
- def generic_expand(generic_interface,skip_names=[]):
- generic_types ={'s' :('real', 'real', real_convert,
- 'real'),
- 'd' :('double precision','double precision',real_convert,
- 'double precision'),
- 'c' :('complex', 'complex',complex_convert,
- 'real'),
- 'z' :('double complex', 'double complex',complex_convert,
- 'double precision'),
- 'cs':('complex', 'real',complex_convert,
- 'real'),
- 'zd':('double complex', 'double precision',complex_convert,
- 'double precision'),
- 'sc':('real', 'complex',real_convert,
- 'real'),
- 'dz':('double precision','double complex', real_convert,
- 'double precision')}
- generic_c_types = {'real':'float',
- 'double precision':'double',
- 'complex':'complex_float',
- 'double complex':'complex_double'}
- # cc_types is specific in ATLAS C BLAS, in particular, for complex arguments
- generic_cc_types = {'real':'float',
- 'double precision':'double',
- 'complex':'void',
- 'double complex':'void'}
- #2. get all subroutines
- subs = all_subroutines(generic_interface)
- print len(subs)
- #loop through the subs
- type_exp = re.compile(r'<tchar=(.*?)>')
- TYPE_EXP = re.compile(r'<TCHAR=(.*?)>')
- routine_name = re.compile(r'(subroutine|function)\s*(?P<name>\w+)\s*\(')
- interface = ''
- for sub in subs:
- #3. Find the typecodes to use:
- m = type_exp.search(sub)
- if m is None:
- interface = interface + '\n\n' + sub
- continue
- type_chars = m.group(1)
- # get rid of spaces
- type_chars = type_chars.replace(' ','')
- # get a list of the characters (or character pairs)
- type_chars = type_chars.split(',')
- # Now get rid of the special tag that contained the types
- sub = re.sub(type_exp,'<tchar>',sub)
- m = TYPE_EXP.search(sub)
- if m is not None:
- sub = re.sub(TYPE_EXP,'<TCHAR>',sub)
- sub_generic = sub.strip()
- for char in type_chars:
- type_in,type_out,converter, rtype_in = generic_types[char]
- sub = convert_types(sub_generic,converter)
- function_def = sub.replace('<tchar>',char)
- function_def = function_def.replace('<TCHAR>',char.upper())
- function_def = function_def.replace('<type_in>',type_in)
- function_def = function_def.replace('<type_in_c>',
- generic_c_types[type_in])
- function_def = function_def.replace('<type_in_cc>',
- generic_cc_types[type_in])
- function_def = function_def.replace('<rtype_in>',rtype_in)
- function_def = function_def.replace('<rtype_in_c>',
- generic_c_types[rtype_in])
- function_def = function_def.replace('<type_out>',type_out)
- function_def = function_def.replace('<type_out_c>',
- generic_c_types[type_out])
- m = routine_name.match(function_def)
- if m:
- if m.group('name') in skip_names:
- print 'Skipping',m.group('name')
- continue
- else:
- print 'Possible bug: Failed to determine routines name'
- interface = interface + '\n\n' + function_def
- return interface
- #def interface_to_module(interface_in,module_name,include_list,sdir='.'):
- def interface_to_module(interface_in,module_name):
- pre_prefix = "!%f90 -*- f90 -*-\n"
- # heading and tail of the module definition.
- file_prefix = "\npython module " + module_name +" ! in\n" \
- "!usercode '''#include \"cblas.h\"\n"\
- "!'''\n"\
- " interface \n"
- file_suffix = "\n end interface\n" \
- "end module %s" % module_name
- return pre_prefix + file_prefix + interface_in + file_suffix
- def process_includes(interface_in,sdir='.'):
- include_exp = re.compile(r'\n\s*[^!]\s*<include_file=(.*?)>')
- include_files = include_exp.findall(interface_in)
- for filename in include_files:
- f = open(os.path.join(sdir,filename))
- interface_in = interface_in.replace('<include_file=%s>'%filename,
- f.read())
- f.close()
- return interface_in
- def generate_interface(module_name,src_file,target_file,skip_names=[]):
- print "generating",module_name,"interface"
- f = open(src_file)
- generic_interface = f.read()
- f.close()
- sdir = os.path.dirname(src_file)
- generic_interface = process_includes(generic_interface,sdir)
- generic_interface = generic_expand(generic_interface,skip_names)
- module_def = interface_to_module(generic_interface,module_name)
- mkpath(os.path.dirname(target_file))
- f = open(target_file,'w')
- user_routines = os.path.join(sdir,module_name+"_user_routines.pyf")
- if os.path.exists(user_routines):
- f2 = open(user_routines)
- f.write(f2.read())
- f2.close()
- f.write(module_def)
- f.close()
- def process_all():
- # process the standard files.
- for name in ['fblas','cblas','clapack','flapack']:
- generate_interface(name,'generic_%s.pyf'%(name),name+'.pyf')
- if __name__ == "__main__":
- process_all()