-
Notifications
You must be signed in to change notification settings - Fork 42
/
genglue.py
145 lines (123 loc) · 4.32 KB
/
genglue.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
structs = 'sprite,canvas'.split(',')
structs = [ 'struct ' + s for s in structs ]
types = {
'int': 'i',
'char*': 's',
}
ignore = 'get_overview_area_dimensions gfx_fileextensions get_sprite_dimensions ' \
'city_dialog_is_open get_text_size gui_set_rulesets add_idle_callback ' \
'caravan_dialog_is_open popup_pillage_dialog color_alloc get_gui_specific_themes_directories ' \
'get_useable_themes_in_directory ui_main'.split()
mappers = 'city player unit tile packet_game_load text_tag_list unit_list color packet_endgame_report option option_set'.split()
def proc(type, name):
type = type.strip()
while name.startswith('*'):
type += '*'
name = name[1:]
if type.startswith('const '):
type = type[len('const '):]
if type in structs:
raise ValueError('Not supported')
return 'O', name + '.py_object'
if type.endswith('*') and type[:-1] in structs:
return 'O', 'py_get_pyobject(%s)' % name
if type.startswith('enum'):
return 'i', '(int)' + name
if type.startswith('struct '):
type = type[len('struct '):]
if type.endswith('*') and type[:-1] in mappers:
return 'O', 'py_mapper_%s(%s)' % (type[:-1], name)
elif type in mappers:
return 'O', 'py_mapper_%s(&%s)' % (type, name)
else:
raise ValueError('Bad type %s' % type)
if type == 'bool':
return 'i', '(int)' + name
return types[type], name
def proc_ret(type):
if type.endswith('*') and type[:-1] in structs:
return 'PyObject*', 'O', '''
\t%s retstru = py_alloc_struct(retval);
\treturn retstru;
''' % (type, )
if type in structs:
return 'PyObject*', 'O', '''
\t%s retstru;
\tretstru.py_object = retval;
\treturn retstru;
''' % type
if type.startswith('enum '):
return 'int', 'i', 'return (%s)retval;' % type
if type == 'bool':
return 'int', 'i', 'return (bool)retval;'
return type, types[type], 'return retval;'
def p2(x):
if len(x) == 1:
print '// bad length', x
return x
fails = []
import traceback
nign = 0
nproc = 0
was_printed = set()
ignored = []
import sys
sys.stdout = open("src/clientauto.c", 'w')
print '#include "pyclient.h"'
for line in open('gui-stub').readlines() + open('gui-manual').readlines():
if line.startswith('File') or not line.strip() or line.startswith('#'):
continue
print '// %s' % line.strip()
start, rest = line.strip().split('(', 1)
rettype, fname = start.rsplit(None, 1)
while fname.startswith('*'):
rettype += '*'
fname = fname[1:]
if fname in was_printed:
print '// continue %s - was processed' % fname
continue
was_printed.add(fname)
if fname in ignore:
nign += 1
ignored.append(line)
print '// ignored'
print
continue
nproc += 1
try:
rest, _ = rest.split(')', 1)
if rest.strip() in ('void', ''):
args = []
else:
args = [ p2(a.rsplit(None, 1)) for a in rest.split(',') ]
format = [ proc(type, name)[0] for type, name in args ]
args = [ proc(type, name)[1] for type, name in args ]
print line.strip() + '{'
joinedargs = ', '.join(args)
if joinedargs:
joinedargs = ', ' + joinedargs
print '\tPyObject* ret = PY_CALL("s%s", "%s"%s);' % (''.join(format), fname, joinedargs)
if rettype != 'void':
mrettype, retcode, retproc = proc_ret(rettype)
print '\t%s retval;' % mrettype
val = '\tif(PyArg_ParseTuple(ret, "%s", &retval) == 0) fprintf(stderr, "TypeError: bad return value from %s (expected %r)\\n");' % (retcode, fname, retcode)
print val
if retcode == 'O':
print '\tPy_INCREF(retval);'
print '\tPy_DECREF(ret);'
print '\t%s' % retproc
else:
print '\tPy_DECREF(ret);'
print '}'
if rettype != 'void':
pass
except:
f = traceback.format_exc()
fails.append((f, line.strip()))
for i, (f, n) in enumerate(fails):
print >>sys.stderr, '// %d failed' % (i+1), n
print >>sys.stderr, '// ' +f.replace('\n', '\n// ')
print '// IGNORED:'
for ign in ignored:
print '// ', ign.strip()
print '// processed %d ignored %d' % (nproc, nign)