/
generate_wrappers.py
168 lines (139 loc) · 4.72 KB
/
generate_wrappers.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#!/usr/bin/python
# Generate C-style wrapper functions
# Thomas Perl <m@thp.io>; 2012-10-19
# License: See the COPYING file.
import re
import os
import sys
funcs = []
# Some special cases to to avoid having to parse the full C grammar
FIXED_MAPPINGS = {
'struct __jmp_buf_tag __env[1]': '__env',
'void *(*__start_routine)(void *)': '__start_routine',
'void (*__destr_function)(void *)': '__destr_function',
'void (*__init_routine)(void)': '__init_routine',
}
# Never generate wrappers for these functions
BLACKLISTED_FUNCS = [
'pthread_mutex_init',
'pthread_mutex_lock',
'pthread_mutex_trylock',
'pthread_mutex_unlock',
'pthread_mutex_destroy',
]
# Generate wrappers, but do not call original functions
EMPTYCALL_FUNCS = [
'glBindFramebufferOES',
'glBindRenderbufferOES',
'glCheckFramebufferStatusOES',
'glDeleteFramebuffersOES',
'glDeleteRenderbuffersOES',
'glFramebufferRenderbufferOES',
'glFramebufferTexture2DOES',
'glGenFramebuffersOES',
'glGenRenderbuffersOES',
'glRenderbufferStorageOES',
]
def clean_arg(arg):
arg = arg.replace('__restrict', '')
arg = arg.replace('__const', 'const')
return arg.strip()
def mangle(name):
return 'my_' + name
class Argument:
def __init__(self, type_, name):
self.type_ = type_
self.name = name
class Function:
def __init__(self, retval, name, args):
self.retval = retval
self.name = name
self.raw_args = args
self.parsing_error = None
self.args = list(self._parse_args(args))
def _parse_args(self, args):
for arg in map(clean_arg, args.split(',')):
arg = clean_arg(arg)
xarg = re.match(r'^(.*?)([A-Za-z0-9_]+)$', arg)
if not xarg:
# Unknown argument
if arg in FIXED_MAPPINGS:
yield Argument('<fixed>', FIXED_MAPPINGS[arg])
continue
self.parsing_error = 'Could not parse: ' + repr(arg)
print self.parsing_error
continue
type_, name = xarg.groups()
yield Argument(type_, name)
def _format_args(self):
if self.raw_args == 'void':
return ''
else:
return self.raw_args
def _format_return(self):
if self.retval == 'void':
return ''
else:
return 'return '
def _format_call_args(self):
return ', '.join(a.name for a in self.args if a.type_)
def _format_call_args_formatstring(self):
return ''
def _format_call(self):
if self.name in EMPTYCALL_FUNCS:
return '/* No CALL */'
else:
return '%s%s(%s);' % (self._format_return(),
self.name, self._format_call_args())
def _format_prototype(self):
funcname = mangle(self.name)
return """
%s\n%s(%s)
""".strip() % (self.retval,
funcname,
self._format_args())
def prototype(self):
return self._format_prototype() + ' SOFTFP;'
def implementation(self):
return """%s
{
WRAPPERS_DEBUG_PRINTF("%s(%s)\\n"%s%s);
%s
}
""".strip() % (self._format_prototype(),
self.name,
self._format_call_args_formatstring(),
', ' if self._format_call_args() else '',
self._format_call_args(),
self._format_call())
def mapping(self):
if self.parsing_error:
return '/* unmapped: %s (%s) */' % (self.name, self.parsing_error)
return """
{"%s", %s},
""".strip() % (self.name, mangle(self.name))
if len(sys.argv) != 2:
print >>sys.stderr, """
Usage: %s output/<yoursharedlib>.required.includes.harmattan.h
""" % (sys.argv[0],)
sys.exit(1)
filename = sys.argv[1]
for line in open(filename):
retval, funcname, args = re.match(r'^(.+ [*]?)([A-Za-z0-9_]+)\((.*)\);\s*$', line).groups()
retval, funcname, args = [x.strip() for x in (retval, funcname, args)]
if funcname not in BLACKLISTED_FUNCS:
funcs.append(Function(retval, funcname, args))
basename = os.path.basename(filename)
basename = basename[:basename.index('.')]
with open('output/'+basename+'_wrappers.h', 'w') as fp:
print >>fp, open('output/'+basename+'.required.includes').read()
print >>fp, open('default_includes.h').read()
for function in funcs:
print >>fp, function.prototype()
with open('output/'+basename+'_wrappers.c', 'w') as fp:
print >>fp, '#include "'+basename+'_wrappers.h"'
for function in funcs:
print >>fp, function.implementation()
with open('output/'+basename+'_mapping.h', 'w') as fp:
for function in funcs:
print >>fp, function.mapping()