PageRenderTime 45ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/interface_gen.py

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