Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100755 163 lines (148 sloc) 6.805 kb
a93924c @cournape ENH: make f2py feature explicit + add support for f2py wo .pyf mode.
cournape authored
1 #!/usr/bin/env python
2
3 import os
4 import re
5 from distutils.dir_util import mkpath
6
7 def all_subroutines(interface_in):
8 # remove comments
9 comment_block_exp = re.compile(r'/\*(?:\s|.)*?\*/')
10 subroutine_exp = re.compile(r'subroutine (?:\s|.)*?end subroutine.*')
11 function_exp = re.compile(r'function (?:\s|.)*?end function.*')
12
13 interface = comment_block_exp.sub('',interface_in)
14 subroutine_list = subroutine_exp.findall(interface)
15 function_list = function_exp.findall(interface)
16 subroutine_list = subroutine_list + function_list
17 subroutine_list = map(lambda x: x.strip(),subroutine_list)
18 return subroutine_list
19
20 def real_convert(val_string):
21 return val_string
22
23 def complex_convert(val_string):
24 return '(' + val_string + ',0.)'
25
26 def convert_types(interface_in,converter):
27 regexp = re.compile(r'<type_convert=(.*?)>')
28 interface = interface_in[:]
29 while 1:
30 sub = regexp.search(interface)
31 if sub is None: break
32 converted = converter(sub.group(1))
33 interface = interface.replace(sub.group(),converted)
34 return interface
35
36 def generic_expand(generic_interface,skip_names=[]):
37 generic_types ={'s' :('real', 'real', real_convert,
38 'real'),
39 'd' :('double precision','double precision',real_convert,
40 'double precision'),
41 'c' :('complex', 'complex',complex_convert,
42 'real'),
43 'z' :('double complex', 'double complex',complex_convert,
44 'double precision'),
45 'cs':('complex', 'real',complex_convert,
46 'real'),
47 'zd':('double complex', 'double precision',complex_convert,
48 'double precision'),
49 'sc':('real', 'complex',real_convert,
50 'real'),
51 'dz':('double precision','double complex', real_convert,
52 'double precision')}
53 generic_c_types = {'real':'float',
54 'double precision':'double',
55 'complex':'complex_float',
56 'double complex':'complex_double'}
57 # cc_types is specific in ATLAS C BLAS, in particular, for complex arguments
58 generic_cc_types = {'real':'float',
59 'double precision':'double',
60 'complex':'void',
61 'double complex':'void'}
62 #2. get all subroutines
63 subs = all_subroutines(generic_interface)
64 #print len(subs)
65 #loop through the subs
66 type_exp = re.compile(r'<tchar=(.*?)>')
67 TYPE_EXP = re.compile(r'<TCHAR=(.*?)>')
68 routine_name = re.compile(r'(subroutine|function)\s*(?P<name>\w+)\s*\(')
69 interface = ''
70 for sub in subs:
71 #3. Find the typecodes to use:
72 m = type_exp.search(sub)
73 if m is None:
74 interface = interface + '\n\n' + sub
75 continue
76 type_chars = m.group(1)
77 # get rid of spaces
78 type_chars = type_chars.replace(' ','')
79 # get a list of the characters (or character pairs)
80 type_chars = type_chars.split(',')
81 # Now get rid of the special tag that contained the types
82 sub = re.sub(type_exp,'<tchar>',sub)
83 m = TYPE_EXP.search(sub)
84 if m is not None:
85 sub = re.sub(TYPE_EXP,'<TCHAR>',sub)
86 sub_generic = sub.strip()
87 for char in type_chars:
88 type_in,type_out,converter, rtype_in = generic_types[char]
89 sub = convert_types(sub_generic,converter)
90 function_def = sub.replace('<tchar>',char)
91 function_def = function_def.replace('<TCHAR>',char.upper())
92 function_def = function_def.replace('<type_in>',type_in)
93 function_def = function_def.replace('<type_in_c>',
94 generic_c_types[type_in])
95 function_def = function_def.replace('<type_in_cc>',
96 generic_cc_types[type_in])
97 function_def = function_def.replace('<rtype_in>',rtype_in)
98 function_def = function_def.replace('<rtype_in_c>',
99 generic_c_types[rtype_in])
100 function_def = function_def.replace('<type_out>',type_out)
101 function_def = function_def.replace('<type_out_c>',
102 generic_c_types[type_out])
103 m = routine_name.match(function_def)
104 if m:
105 if m.group('name') in skip_names:
106 print 'Skipping',m.group('name')
107 continue
108 else:
109 print 'Possible bug: Failed to determine routines name'
110 interface = interface + '\n\n' + function_def
111
112 return interface
113
114 #def interface_to_module(interface_in,module_name,include_list,sdir='.'):
115 def interface_to_module(interface_in,module_name):
116 pre_prefix = "!%f90 -*- f90 -*-\n"
117 # heading and tail of the module definition.
118 file_prefix = "\npython module " + module_name +" ! in\n" \
119 "!usercode '''#include \"cblas.h\"\n"\
120 "!'''\n"\
121 " interface \n"
122 file_suffix = "\n end interface\n" \
123 "end module %s" % module_name
124 return pre_prefix + file_prefix + interface_in + file_suffix
125
126 def process_includes(interface_in,sdir='.'):
127 include_exp = re.compile(r'\n\s*[^!]\s*<include_file=(.*?)>')
128 include_files = include_exp.findall(interface_in)
129 for filename in include_files:
130 f = open(os.path.join(sdir,filename))
131 interface_in = interface_in.replace('<include_file=%s>'%filename,
132 f.read())
133 f.close()
134 return interface_in
135
136 def generate_interface(module_name,src_file,target_file,skip_names=[]):
137 #print "generating",module_name,"interface"
138 f = open(src_file)
139 generic_interface = f.read()
140 f.close()
141 sdir = os.path.dirname(src_file)
142 generic_interface = process_includes(generic_interface,sdir)
143 generic_interface = generic_expand(generic_interface,skip_names)
144 module_def = interface_to_module(generic_interface,module_name)
145 mkpath(os.path.dirname(target_file))
146 f = open(target_file,'w')
147 user_routines = os.path.join(sdir,module_name+"_user_routines.pyf")
148 if os.path.exists(user_routines):
149 f2 = open(user_routines)
150 f.write(f2.read())
151 f2.close()
152 f.write(module_def)
153 f.close()
154
155 def process_all():
156 # process the standard files.
157 for name in ['fblas','cblas','clapack','flapack']:
158 generate_interface(name,'generic_%s.pyf'%(name),name+'.pyf')
159
160
161 if __name__ == "__main__":
162 process_all()
Something went wrong with that request. Please try again.