9 global PARAM_TYPE_COLUMN
10 space =
' ' * (PARAM_TYPE_COLUMN - len(typ))
11 return typ + space +
':: ' + name
14 decls = [line
for line
in [l.strip()
for l
in open(source_cc).read().splitlines()]
15 if line.find(
'odbql_') <> -1
16 and not line.startswith(
'//')
17 and line.find(
'return') == -1
18 and line.find(
'virtual') == -1
19 and line.find(
'::') == -1
20 and line.find(
'typedef') == -1]
25 lines = [line.strip()
for line
in open(source_h).read().splitlines()
26 if line.startswith(
'#define ODBQL_')
27 and len(line.split()) > 2]
29 defs = [line.split(
None, 2)[1:]
for line
in lines]
36 e = e.replace(c, CONSTANTS[c])
37 return ' [' +
str(eval(e)) +
']'
41 value = value_and_possibly_comment.split(
'/*')[0].strip()
44 if len(value_and_possibly_comment.split(
'/*')) > 1:
45 comment = value_and_possibly_comment.split(
'/*')[1].split(
'*/')[0]
47 if value.find(
'|') <> -1:
49 l,r = [x.strip(
' ()')
for x
in value.split(
'|')]
50 i, shift = [x.strip()
for x
in r.split(
'<<')]
51 value =
'IOR(%s, LSHIFT(%s,%s))' % (l, i, shift)
53 if value.startswith(
'0x'):
54 comment = value +
' ' + comment
57 return value,
'! ' + comment
62 name, value_and_possibly_comment = define
65 if value_and_possibly_comment.find(
'"') <> -1:
66 typ =
'character(len=*)'
68 if name ==
'ODBQL_TRANSIENT':
69 value, comment =
'-1',
" ! ((odbql_destructor_type)-1)"
70 elif name ==
'ODBQL_STATIC':
71 value, comment =
'0',
' ! ((odbql_destructor_type)0)'
75 CONSTANTS[name] = value
77 return '%s, parameter :: %s = %s %s' % (typ, name, value, comment)
81 module odbql_constants
86 end module odbql_constants
99 if p ==
'void(*d)(void*)':
return 'void(*)(void*)',
'd'
101 param_name = re.findall(
r"[\w']+", p)[-1]
102 param_type = p[:len(p) - len(param_name)].strip()
105 return param_type, param_name
109 ret_and_fun_name = decl.split(
'(', 1)[0].strip()
110 fun_name = re.findall(
r"[\w']+", ret_and_fun_name)[-1]
111 return_type = ret_and_fun_name[:-len(fun_name)].strip()
114 params = decl.split(
'(',1)[1].strip().rsplit(
')', 1)[0].strip()
115 params = list([
parseParam(p)
for p
in params.split(
',')])
118 if len(params) == 1
and (len(params[0][0]) == 0
and params[0][1] ==
'void'):
120 return (decl, (return_type, fun_name, params))
124 if t ==
'const char*':
return 'character(kind=C_CHAR), dimension(*)'
125 if t ==
'const char**':
return 'character(kind=C_CHAR), dimension(*)'
126 if t ==
'double':
return 'real(kind=C_DOUBLE), value'
127 if t ==
'int':
return 'integer(kind=C_INT), value'
128 if t ==
'odbql*':
return 'type(C_PTR), VALUE'
129 if t ==
'odbql**':
return 'type(C_PTR)'
130 if t ==
'odbql_stmt*':
return 'type(C_PTR), VALUE'
131 if t ==
'odbql_stmt**':
return 'type(C_PTR)'
132 if t ==
'odbql_value*':
return 'type(C_PTR), VALUE'
133 if t ==
'odbql_value**':
return 'type(C_PTR)'
134 if t ==
'void(*)(void*)':
return 'type(C_PTR), VALUE'
136 raise Exception(
"Don't know how to translate '" + t +
"'")
141 if t ==
'const char*':
return 'type(C_PTR)'
142 if t ==
'const unsigned char*':
return 'type(C_PTR)'
143 if t ==
'int':
return 'integer(kind=C_INT)'
144 if t ==
'double':
return 'real(kind=C_DOUBLE)'
145 if t ==
'odbql_value*':
return 'type(C_PTR)'
146 if t ==
'error_code_t':
return 'integer(kind=C_INT)'
148 raise Exception(
"Don't know how to translate '" + t +
"'")
153 if t ==
'const char*':
return 'character(len=*), intent(in)'
154 if t ==
'const char**':
return 'character(len=*), intent(out)'
155 if t ==
'double':
return 'real(kind=C_DOUBLE), value'
156 if t ==
'int':
return 'integer(kind=C_INT), value'
157 if t ==
'odbql*':
return 'type(odbql), value'
158 if t ==
'odbql**':
return 'type(odbql)'
159 if t ==
'odbql_stmt*':
return 'type(odbql_stmt), value'
160 if t ==
'odbql_stmt**':
return 'type(odbql_stmt)'
161 if t ==
'odbql_value*':
return 'type(odbql_value), value'
162 if t ==
'odbql_value**':
return 'type(odbql_value)'
163 if t ==
'void(*)(void*)':
return 'type(C_PTR), value'
165 raise Exception(
"Don't know how to translate '" + t +
"'")
170 if t ==
'const char*':
return 'character(len=*), intent(out)'
171 if t ==
'const unsigned char*':
return 'character(len=*), intent(out)'
172 if t ==
'int':
return 'integer(kind=C_INT)'
173 if t ==
'double':
return 'real(kind=C_DOUBLE)'
174 if t ==
'odbql_value*':
return 'type(odbql_value)'
175 if t ==
'error_code_t':
return 'integer(kind=C_INT), intent(out), optional'
177 raise Exception(
"Don't know how to translate '" + t +
"'")
180 typ, parameter_name = p
181 fortran_type = translate_type(typ)
186 helper_functions =
"""
188 !> Helper routine to convert C '\\0' terminated strings to Fortran strings
190 subroutine C_to_F_string(c_string_pointer, out_string)
192 use, intrinsic :: iso_c_binding, only: c_ptr,c_f_pointer,c_char,c_null_char
194 type(c_ptr), intent(in) :: c_string_pointer
195 character(len=*), intent(out) :: out_string
196 character(kind=c_char), dimension(:), pointer :: char_array_pointer
199 char_array_pointer => null()
200 call c_f_pointer(c_string_pointer,char_array_pointer,[255])
202 if (.not.associated(char_array_pointer)) then
208 do i = 1, len(out_string)
209 if (char_array_pointer(i) == c_null_char) exit
210 out_string(i:i) = char_array_pointer(i)
218 status_handling_code =
"""
219 if (present(status)) then
220 status = rc ! let user handle the error
222 if (rc /= ODBQL_OK .and. rc /= ODBQL_ROW .and. rc /= ODBQL_DONE .and. rc /= ODBQL_METADATA_CHANGED) then
223 write (0,*) 'Error in %(function_name)s'
228 status_handling_code = nl_indent.join (status_handling_code.splitlines())
234 if p[1] ==
'iCol':
return p[1] +
'-1'
235 if p[0] ==
'const char*':
return p[1] +
'_tmp'
236 if p[0] ==
'odbql*':
return p[1] +
'%this'
237 if p[0] ==
'odbql**':
return p[1] +
'%this'
238 if p[0] ==
'odbql_stmt*':
return p[1] +
'%this'
239 if p[0] ==
'odbql_stmt**':
return p[1] +
'%this'
240 if p[0] ==
'odbql_value*':
return p[1] +
'%this'
241 if p[0] ==
'odbql_value**':
return p[1] +
'%this'
246 print 'generateWrapper:', signature, comment, template
247 global status_handling_code
249 return_type, function_name, params = signature
250 procedure_keyword =
'function'
252 output_parameter = function_name
255 fortran_params = [p
for p
in params
if not parameter_type(p) ==
'void(*)(void*)']
256 fortran_params_excluding_return_parameter = fortran_params[:]
258 binding_parameter_list =
'(' +
','.join([p[1]
for p
in params]) +
')'
259 actual_binding_parameter_list =
'(' +
','.join([
actual_parameter(p)
for p
in params]) +
')'
261 temporary_variables_declarations = nl_indent.join(
262 [
formatParameter(
'character(len=len_trim('+p[1]+
')+1)', p[1] +
'_tmp')
for p
in params
if p[0] ==
'const char*']
263 + [
formatParameter(
'type(C_PTR)', p[1])
for p
in params
if p[0] ==
'void(*)(void*)'])
264 temporary_variables_assignments = nl_indent.join(p[1] +
'_tmp = ' + p[1] +
'//achar(0)'
265 for p
in params
if p[0] ==
'const char*')
266 call_binding = function_name +
'_c' + actual_binding_parameter_list
269 return_value_tmp =
None
271 if return_type ==
'odbql_value*':
272 return_value_tmp = output_parameter +
"%this"
275 if return_type ==
'error_code_t':
276 procedure_keyword =
'subroutine'
277 output_parameter =
'status'
278 return_value_tmp =
'rc'
279 temporary_variables_declarations = nl_indent.join(
280 [temporary_variables_declarations,
282 fortran_params.append( (return_type, output_parameter) )
283 error_handling = status_handling_code % locals()
285 if return_type ==
'const char*' or return_type ==
'const unsigned char*':
286 procedure_keyword =
'subroutine'
287 output_parameter =
'return_value'
288 fortran_params.append( (return_type, output_parameter) )
291 return_value_assignment =
"call C_to_F_string(%s, %s)" % (call_binding, (return_value_tmp
or output_parameter))
296 return_value_assignment = (return_value_tmp
or output_parameter) +
' = ' + call_binding
301 fortran_parameter_list =
'(' +
','.join([p[1]
for p
in fortran_params]) +
')'
302 fortran_parameters_declarations = nl_indent.join(
304 for p
in fortran_params_excluding_return_parameter])
309 return template % locals()
322 source_h = '../odb_api/odbql.h',
323 binding_f90 = '../fortran/odbql_binding.f90',
324 wrappers_f90 = '../fortran/odbql_wrappers.f90',
325 constants_f90 = '../fortran/odbql_constants.f90'):
329 with open(constants_f90,
'w')
as f:
333 with open(binding_f90,
'w')
as f:
336 !!!!! THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT MANUALLY !!!!!
341 use, intrinsic :: iso_c_binding
346 end module odbql_binding
350 function %(function_name)s_c %(binding_parameter_list)s bind(C, name="%(function_name)s")
352 %(binding_parameters_declarations)s
353 %(binding_return_type_declaration)s
354 end function %(function_name)s_c
361 with open(wrappers_f90,
'w')
as f:
364 !!!!! THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT MANUALLY !!!!!
367 module odbql_wrappers
388 """ % globals(), footer =
"""
389 end module odbql_wrappers
393 %(procedure_keyword)s %(function_name)s %(fortran_parameter_list)s
396 %(fortran_parameters_declarations)s
397 %(fortran_return_type_declaration)s
399 %(temporary_variables_declarations)s
401 %(temporary_variables_assignments)s
402 %(return_value_assignment)s
405 end %(procedure_keyword)s %(function_name)s
def fortranParamTypeDeclaration(p, translate_type=translate_type_for_binding)
def declarations(source_cc='odbql.cc')
def constants(source_h='odbql.h')
def translate_value_and_comment(value_and_possibly_comment)
def generateParameter(define)
def evaluated_expression(s)
def generateWrappers(decls, header, footer, template)
def translate_type_for_binding(t)
def translate_type_for_fortran(t)
def generateParameters(defs)
def formatParameter(typ, name)
def translate_type_for_binding_return(t)
def generateBindings(source_cc='../odb_api/odbql.cc', source_h='../odb_api/odbql.h', binding_f90='../fortran/odbql_binding.f90', wrappers_f90='../fortran/odbql_wrappers.f90', constants_f90='../fortran/odbql_constants.f90')
def generateWrapper(signature, comment, template)
def parseDeclaration(decl)
def translate_type_for_fortran_return(t)