Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 1 | #!/usr/bin/env python |
2 | |||
3 | # Mesa 3-D graphics library |
||
4 | # |
||
5 | # Copyright (C) 2010 LunarG Inc. |
||
6 | # |
||
7 | # Permission is hereby granted, free of charge, to any person obtaining a |
||
8 | # copy of this software and associated documentation files (the "Software"), |
||
9 | # to deal in the Software without restriction, including without limitation |
||
10 | # the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||
11 | # and/or sell copies of the Software, and to permit persons to whom the |
||
12 | # Software is furnished to do so, subject to the following conditions: |
||
13 | # |
||
14 | # The above copyright notice and this permission notice shall be included |
||
15 | # in all copies or substantial portions of the Software. |
||
16 | # |
||
17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||
18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||
20 | # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||
21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||
22 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||
23 | # DEALINGS IN THE SOFTWARE. |
||
24 | # |
||
25 | # Authors: |
||
26 | # Chia-I Wu |
||
27 | |||
28 | import sys |
||
29 | # make it possible to import glapi |
||
30 | import os |
||
31 | GLAPI = os.path.join(".", os.path.dirname(sys.argv[0]), "glapi/gen") |
||
32 | sys.path.append(GLAPI) |
||
33 | |||
34 | import re |
||
35 | from optparse import OptionParser |
||
36 | import gl_XML |
||
37 | import glX_XML |
||
38 | |||
39 | |||
40 | # number of dynamic entries |
||
41 | ABI_NUM_DYNAMIC_ENTRIES = 256 |
||
42 | |||
43 | class ABIEntry(object): |
||
44 | """Represent an ABI entry.""" |
||
45 | |||
46 | _match_c_param = re.compile( |
||
47 | '^(?P |
||
48 | |||
49 | def __init__(self, cols, attrs, xml_data = None): |
||
50 | self._parse(cols) |
||
51 | |||
52 | self.slot = attrs['slot'] |
||
53 | self.hidden = attrs['hidden'] |
||
54 | self.alias = attrs['alias'] |
||
55 | self.handcode = attrs['handcode'] |
||
56 | self.xml_data = xml_data |
||
57 | |||
58 | def c_prototype(self): |
||
59 | return '%s %s(%s)' % (self.c_return(), self.name, self.c_params()) |
||
60 | |||
61 | def c_return(self): |
||
62 | ret = self.ret |
||
63 | if not ret: |
||
64 | ret = 'void' |
||
65 | |||
66 | return ret |
||
67 | |||
68 | def c_params(self): |
||
69 | """Return the parameter list used in the entry prototype.""" |
||
70 | c_params = [] |
||
71 | for t, n, a in self.params: |
||
72 | sep = '' if t.endswith('*') else ' ' |
||
73 | arr = '[%d]' % a if a else '' |
||
74 | c_params.append(t + sep + n + arr) |
||
75 | if not c_params: |
||
76 | c_params.append('void') |
||
77 | |||
78 | return ", ".join(c_params) |
||
79 | |||
80 | def c_args(self): |
||
81 | """Return the argument list used in the entry invocation.""" |
||
82 | c_args = [] |
||
83 | for t, n, a in self.params: |
||
84 | c_args.append(n) |
||
85 | |||
86 | return ", ".join(c_args) |
||
87 | |||
88 | def _parse(self, cols): |
||
89 | ret = cols.pop(0) |
||
90 | if ret == 'void': |
||
91 | ret = None |
||
92 | |||
93 | name = cols.pop(0) |
||
94 | |||
95 | params = [] |
||
96 | if not cols: |
||
97 | raise Exception(cols) |
||
98 | elif len(cols) == 1 and cols[0] == 'void': |
||
99 | pass |
||
100 | else: |
||
101 | for val in cols: |
||
102 | params.append(self._parse_param(val)) |
||
103 | |||
104 | self.ret = ret |
||
105 | self.name = name |
||
106 | self.params = params |
||
107 | |||
108 | def _parse_param(self, c_param): |
||
109 | m = self._match_c_param.match(c_param) |
||
110 | if not m: |
||
111 | raise Exception('unrecognized param ' + c_param) |
||
112 | |||
113 | c_type = m.group('type').strip() |
||
114 | c_name = m.group('name') |
||
115 | c_array = m.group('array') |
||
116 | c_array = int(c_array) if c_array else 0 |
||
117 | |||
118 | return (c_type, c_name, c_array) |
||
119 | |||
120 | def __str__(self): |
||
121 | return self.c_prototype() |
||
122 | |||
123 | def __cmp__(self, other): |
||
124 | # compare slot, alias, and then name |
||
125 | res = cmp(self.slot, other.slot) |
||
126 | if not res: |
||
127 | if not self.alias: |
||
128 | res = -1 |
||
129 | elif not other.alias: |
||
130 | res = 1 |
||
131 | |||
132 | if not res: |
||
133 | res = cmp(self.name, other.name) |
||
134 | |||
135 | return res |
||
136 | |||
137 | def abi_parse_xml(xml): |
||
138 | """Parse a GLAPI XML file for ABI entries.""" |
||
139 | api = gl_XML.parse_GL_API(xml, glX_XML.glx_item_factory()) |
||
140 | |||
141 | entry_dict = {} |
||
142 | for func in api.functionIterateByOffset(): |
||
143 | # make sure func.name appear first |
||
144 | entry_points = func.entry_points[:] |
||
145 | entry_points.remove(func.name) |
||
146 | entry_points.insert(0, func.name) |
||
147 | |||
148 | for name in entry_points: |
||
149 | attrs = { |
||
150 | 'slot': func.offset, |
||
151 | 'hidden': not func.is_static_entry_point(name), |
||
152 | 'alias': None if name == func.name else func.name, |
||
153 | 'handcode': bool(func.has_different_protocol(name)), |
||
154 | } |
||
155 | |||
156 | # post-process attrs |
||
157 | if attrs['alias']: |
||
158 | try: |
||
159 | alias = entry_dict[attrs['alias']] |
||
160 | except KeyError: |
||
161 | raise Exception('failed to alias %s' % attrs['alias']) |
||
162 | if alias.alias: |
||
163 | raise Exception('recursive alias %s' % ent.name) |
||
164 | attrs['alias'] = alias |
||
165 | if attrs['handcode']: |
||
166 | attrs['handcode'] = func.static_glx_name(name) |
||
167 | else: |
||
168 | attrs['handcode'] = None |
||
169 | |||
170 | if entry_dict.has_key(name): |
||
171 | raise Exception('%s is duplicated' % (name)) |
||
172 | |||
173 | cols = [] |
||
174 | cols.append(func.return_type) |
||
175 | cols.append(name) |
||
176 | params = func.get_parameter_string(name) |
||
177 | cols.extend([p.strip() for p in params.split(',')]) |
||
178 | |||
179 | ent = ABIEntry(cols, attrs, func) |
||
180 | entry_dict[ent.name] = ent |
||
181 | |||
182 | entries = entry_dict.values() |
||
183 | entries.sort() |
||
184 | |||
185 | return entries |
||
186 | |||
187 | def abi_parse_line(line): |
||
188 | cols = [col.strip() for col in line.split(',')] |
||
189 | |||
190 | attrs = { |
||
191 | 'slot': -1, |
||
192 | 'hidden': False, |
||
193 | 'alias': None, |
||
194 | 'handcode': None, |
||
195 | } |
||
196 | |||
197 | # extract attributes from the first column |
||
198 | vals = cols[0].split(':') |
||
199 | while len(vals) > 1: |
||
200 | val = vals.pop(0) |
||
201 | if val.startswith('slot='): |
||
202 | attrs['slot'] = int(val[5:]) |
||
203 | elif val == 'hidden': |
||
204 | attrs['hidden'] = True |
||
205 | elif val.startswith('alias='): |
||
206 | attrs['alias'] = val[6:] |
||
207 | elif val.startswith('handcode='): |
||
208 | attrs['handcode'] = val[9:] |
||
209 | elif not val: |
||
210 | pass |
||
211 | else: |
||
212 | raise Exception('unknown attribute %s' % val) |
||
213 | cols[0] = vals[0] |
||
214 | |||
215 | return (attrs, cols) |
||
216 | |||
217 | def abi_parse(filename): |
||
218 | """Parse a CSV file for ABI entries.""" |
||
219 | fp = open(filename) if filename != '-' else sys.stdin |
||
220 | lines = [line.strip() for line in fp.readlines() |
||
221 | if not line.startswith('#') and line.strip()] |
||
222 | |||
223 | entry_dict = {} |
||
224 | next_slot = 0 |
||
225 | for line in lines: |
||
226 | attrs, cols = abi_parse_line(line) |
||
227 | |||
228 | # post-process attributes |
||
229 | if attrs['alias']: |
||
230 | try: |
||
231 | alias = entry_dict[attrs['alias']] |
||
232 | except KeyError: |
||
233 | raise Exception('failed to alias %s' % attrs['alias']) |
||
234 | if alias.alias: |
||
235 | raise Exception('recursive alias %s' % ent.name) |
||
236 | slot = alias.slot |
||
237 | attrs['alias'] = alias |
||
238 | else: |
||
239 | slot = next_slot |
||
240 | next_slot += 1 |
||
241 | |||
242 | if attrs['slot'] < 0: |
||
243 | attrs['slot'] = slot |
||
244 | elif attrs['slot'] != slot: |
||
245 | raise Exception('invalid slot in %s' % (line)) |
||
246 | |||
247 | ent = ABIEntry(cols, attrs) |
||
248 | if entry_dict.has_key(ent.name): |
||
249 | raise Exception('%s is duplicated' % (ent.name)) |
||
250 | entry_dict[ent.name] = ent |
||
251 | |||
252 | entries = entry_dict.values() |
||
253 | entries.sort() |
||
254 | |||
255 | return entries |
||
256 | |||
257 | def abi_sanity_check(entries): |
||
258 | if not entries: |
||
259 | return |
||
260 | |||
261 | all_names = [] |
||
262 | last_slot = entries[-1].slot |
||
263 | i = 0 |
||
264 | for slot in xrange(last_slot + 1): |
||
265 | if entries[i].slot != slot: |
||
266 | raise Exception('entries are not ordered by slots') |
||
267 | if entries[i].alias: |
||
268 | raise Exception('first entry of slot %d aliases %s' |
||
269 | % (slot, entries[i].alias.name)) |
||
270 | handcode = None |
||
271 | while i < len(entries) and entries[i].slot == slot: |
||
272 | ent = entries[i] |
||
273 | if not handcode and ent.handcode: |
||
274 | handcode = ent.handcode |
||
275 | elif ent.handcode != handcode: |
||
276 | raise Exception('two aliases with handcode %s != %s', |
||
277 | ent.handcode, handcode) |
||
278 | |||
279 | if ent.name in all_names: |
||
280 | raise Exception('%s is duplicated' % (ent.name)) |
||
281 | if ent.alias and ent.alias.name not in all_names: |
||
282 | raise Exception('failed to alias %s' % (ent.alias.name)) |
||
283 | all_names.append(ent.name) |
||
284 | i += 1 |
||
285 | if i < len(entries): |
||
286 | raise Exception('there are %d invalid entries' % (len(entries) - 1)) |
||
287 | |||
288 | class ABIPrinter(object): |
||
289 | """MAPI Printer""" |
||
290 | |||
291 | def __init__(self, entries): |
||
292 | self.entries = entries |
||
293 | |||
294 | # sort entries by their names |
||
295 | self.entries_sorted_by_names = self.entries[:] |
||
296 | self.entries_sorted_by_names.sort(lambda x, y: cmp(x.name, y.name)) |
||
297 | |||
298 | self.indent = ' ' * 3 |
||
299 | self.noop_warn = 'noop_warn' |
||
300 | self.noop_generic = 'noop_generic' |
||
301 | self.current_get = 'entry_current_get' |
||
302 | |||
303 | self.api_defines = [] |
||
304 | self.api_headers = ['"KHR/khrplatform.h"'] |
||
305 | self.api_call = 'KHRONOS_APICALL' |
||
306 | self.api_entry = 'KHRONOS_APIENTRY' |
||
307 | self.api_attrs = 'KHRONOS_APIATTRIBUTES' |
||
308 | |||
309 | self.c_header = '' |
||
310 | |||
311 | self.lib_need_table_size = True |
||
312 | self.lib_need_noop_array = True |
||
313 | self.lib_need_stubs = True |
||
314 | self.lib_need_all_entries = True |
||
315 | self.lib_need_non_hidden_entries = False |
||
316 | |||
317 | def c_notice(self): |
||
318 | return '/* This file is automatically generated by mapi_abi.py. Do not modify. */' |
||
319 | |||
320 | def c_public_includes(self): |
||
321 | """Return includes of the client API headers.""" |
||
322 | defines = ['#define ' + d for d in self.api_defines] |
||
323 | includes = ['#include ' + h for h in self.api_headers] |
||
324 | return "\n".join(defines + includes) |
||
325 | |||
326 | def need_entry_point(self, ent): |
||
327 | """Return True if an entry point is needed for the entry.""" |
||
328 | # non-handcode hidden aliases may share the entry they alias |
||
329 | use_alias = (ent.hidden and ent.alias and not ent.handcode) |
||
330 | return not use_alias |
||
331 | |||
332 | def c_public_declarations(self, prefix): |
||
333 | """Return the declarations of public entry points.""" |
||
334 | decls = [] |
||
335 | for ent in self.entries: |
||
336 | if not self.need_entry_point(ent): |
||
337 | continue |
||
338 | export = self.api_call if not ent.hidden else '' |
||
339 | decls.append(self._c_decl(ent, prefix, True, export) + ';') |
||
340 | |||
341 | return "\n".join(decls) |
||
342 | |||
343 | def c_mapi_table(self): |
||
344 | """Return defines of the dispatch table size.""" |
||
345 | num_static_entries = self.entries[-1].slot + 1 |
||
346 | return ('#define MAPI_TABLE_NUM_STATIC %d\n' + \ |
||
347 | '#define MAPI_TABLE_NUM_DYNAMIC %d') % ( |
||
348 | num_static_entries, ABI_NUM_DYNAMIC_ENTRIES) |
||
349 | |||
350 | def c_mapi_table_initializer(self, prefix): |
||
351 | """Return the array initializer for mapi_table_fill.""" |
||
352 | entries = [self._c_function(ent, prefix) |
||
353 | for ent in self.entries if not ent.alias] |
||
354 | pre = self.indent + '(mapi_proc) ' |
||
355 | return pre + (',\n' + pre).join(entries) |
||
356 | |||
357 | def c_mapi_table_spec(self): |
||
358 | """Return the spec for mapi_init.""" |
||
359 | specv1 = [] |
||
360 | line = '"1' |
||
361 | for ent in self.entries: |
||
362 | if not ent.alias: |
||
363 | line += '\\0"\n' |
||
364 | specv1.append(line) |
||
365 | line = '"' |
||
366 | line += '%s\\0' % ent.name |
||
367 | line += '";' |
||
368 | specv1.append(line) |
||
369 | |||
370 | return self.indent + self.indent.join(specv1) |
||
371 | |||
372 | def _c_function(self, ent, prefix, mangle=False, stringify=False): |
||
373 | """Return the function name of an entry.""" |
||
374 | formats = { |
||
375 | True: { True: '%s_STR(%s)', False: '%s(%s)' }, |
||
376 | False: { True: '"%s%s"', False: '%s%s' }, |
||
377 | } |
||
378 | fmt = formats[prefix.isupper()][stringify] |
||
379 | name = ent.name |
||
380 | if mangle and ent.hidden: |
||
381 | name = '_dispatch_stub_' + str(ent.slot) |
||
382 | return fmt % (prefix, name) |
||
383 | |||
384 | def _c_function_call(self, ent, prefix): |
||
385 | """Return the function name used for calling.""" |
||
386 | if ent.handcode: |
||
387 | # _c_function does not handle this case |
||
388 | formats = { True: '%s(%s)', False: '%s%s' } |
||
389 | fmt = formats[prefix.isupper()] |
||
390 | name = fmt % (prefix, ent.handcode) |
||
391 | elif self.need_entry_point(ent): |
||
392 | name = self._c_function(ent, prefix, True) |
||
393 | else: |
||
394 | name = self._c_function(ent.alias, prefix, True) |
||
395 | return name |
||
396 | |||
397 | def _c_decl(self, ent, prefix, mangle=False, export=''): |
||
398 | """Return the C declaration for the entry.""" |
||
399 | decl = '%s %s %s(%s)' % (ent.c_return(), self.api_entry, |
||
400 | self._c_function(ent, prefix, mangle), ent.c_params()) |
||
401 | if export: |
||
402 | decl = export + ' ' + decl |
||
403 | if self.api_attrs: |
||
404 | decl += ' ' + self.api_attrs |
||
405 | |||
406 | return decl |
||
407 | |||
408 | def _c_cast(self, ent): |
||
409 | """Return the C cast for the entry.""" |
||
410 | cast = '%s (%s *)(%s)' % ( |
||
411 | ent.c_return(), self.api_entry, ent.c_params()) |
||
412 | |||
413 | return cast |
||
414 | |||
415 | def c_private_declarations(self, prefix): |
||
416 | """Return the declarations of private functions.""" |
||
417 | decls = [self._c_decl(ent, prefix) + ';' |
||
418 | for ent in self.entries if not ent.alias] |
||
419 | |||
420 | return "\n".join(decls) |
||
421 | |||
422 | def c_public_dispatches(self, prefix, no_hidden): |
||
423 | """Return the public dispatch functions.""" |
||
424 | dispatches = [] |
||
425 | for ent in self.entries: |
||
426 | if ent.hidden and no_hidden: |
||
427 | continue |
||
428 | |||
429 | if not self.need_entry_point(ent): |
||
430 | continue |
||
431 | |||
432 | export = self.api_call if not ent.hidden else '' |
||
433 | |||
434 | proto = self._c_decl(ent, prefix, True, export) |
||
435 | cast = self._c_cast(ent) |
||
436 | |||
437 | ret = '' |
||
438 | if ent.ret: |
||
439 | ret = 'return ' |
||
440 | stmt1 = self.indent |
||
441 | stmt1 += 'const struct mapi_table *_tbl = %s();' % ( |
||
442 | self.current_get) |
||
443 | stmt2 = self.indent |
||
444 | stmt2 += 'mapi_func _func = ((const mapi_func *) _tbl)[%d];' % ( |
||
445 | ent.slot) |
||
446 | stmt3 = self.indent |
||
447 | stmt3 += '%s((%s) _func)(%s);' % (ret, cast, ent.c_args()) |
||
448 | |||
449 | disp = '%s\n{\n%s\n%s\n%s\n}' % (proto, stmt1, stmt2, stmt3) |
||
450 | |||
451 | if ent.handcode: |
||
452 | disp = '#if 0\n' + disp + '\n#endif' |
||
453 | |||
454 | dispatches.append(disp) |
||
455 | |||
456 | return '\n\n'.join(dispatches) |
||
457 | |||
458 | def c_public_initializer(self, prefix): |
||
459 | """Return the initializer for public dispatch functions.""" |
||
460 | names = [] |
||
461 | for ent in self.entries: |
||
462 | if ent.alias: |
||
463 | continue |
||
464 | |||
465 | name = '%s(mapi_func) %s' % (self.indent, |
||
466 | self._c_function_call(ent, prefix)) |
||
467 | names.append(name) |
||
468 | |||
469 | return ',\n'.join(names) |
||
470 | |||
471 | def c_stub_string_pool(self): |
||
472 | """Return the string pool for use by stubs.""" |
||
473 | # sort entries by their names |
||
474 | sorted_entries = self.entries[:] |
||
475 | sorted_entries.sort(lambda x, y: cmp(x.name, y.name)) |
||
476 | |||
477 | pool = [] |
||
478 | offsets = {} |
||
479 | count = 0 |
||
480 | for ent in sorted_entries: |
||
481 | offsets[ent] = count |
||
482 | pool.append('%s' % (ent.name)) |
||
483 | count += len(ent.name) + 1 |
||
484 | |||
485 | pool_str = self.indent + '"' + \ |
||
486 | ('\\0"\n' + self.indent + '"').join(pool) + '";' |
||
487 | return (pool_str, offsets) |
||
488 | |||
489 | def c_stub_initializer(self, prefix, pool_offsets): |
||
490 | """Return the initializer for struct mapi_stub array.""" |
||
491 | stubs = [] |
||
492 | for ent in self.entries_sorted_by_names: |
||
493 | stubs.append('%s{ (void *) %d, %d, NULL }' % ( |
||
494 | self.indent, pool_offsets[ent], ent.slot)) |
||
495 | |||
496 | return ',\n'.join(stubs) |
||
497 | |||
498 | def c_noop_functions(self, prefix, warn_prefix): |
||
499 | """Return the noop functions.""" |
||
500 | noops = [] |
||
501 | for ent in self.entries: |
||
502 | if ent.alias: |
||
503 | continue |
||
504 | |||
505 | proto = self._c_decl(ent, prefix, False, 'static') |
||
506 | |||
507 | stmt1 = self.indent; |
||
508 | space = '' |
||
509 | for t, n, a in ent.params: |
||
510 | stmt1 += "%s(void) %s;" % (space, n) |
||
511 | space = ' ' |
||
512 | |||
513 | if ent.params: |
||
514 | stmt1 += '\n'; |
||
515 | |||
516 | stmt1 += self.indent + '%s(%s);' % (self.noop_warn, |
||
517 | self._c_function(ent, warn_prefix, False, True)) |
||
518 | |||
519 | if ent.ret: |
||
520 | stmt2 = self.indent + 'return (%s) 0;' % (ent.ret) |
||
521 | noop = '%s\n{\n%s\n%s\n}' % (proto, stmt1, stmt2) |
||
522 | else: |
||
523 | noop = '%s\n{\n%s\n}' % (proto, stmt1) |
||
524 | |||
525 | noops.append(noop) |
||
526 | |||
527 | return '\n\n'.join(noops) |
||
528 | |||
529 | def c_noop_initializer(self, prefix, use_generic): |
||
530 | """Return an initializer for the noop dispatch table.""" |
||
531 | entries = [self._c_function(ent, prefix) |
||
532 | for ent in self.entries if not ent.alias] |
||
533 | if use_generic: |
||
534 | entries = [self.noop_generic] * len(entries) |
||
535 | |||
536 | entries.extend([self.noop_generic] * ABI_NUM_DYNAMIC_ENTRIES) |
||
537 | |||
538 | pre = self.indent + '(mapi_func) ' |
||
539 | return pre + (',\n' + pre).join(entries) |
||
540 | |||
541 | def c_asm_gcc(self, prefix, no_hidden): |
||
542 | asm = [] |
||
543 | |||
544 | for ent in self.entries: |
||
545 | if ent.hidden and no_hidden: |
||
546 | continue |
||
547 | |||
548 | if not self.need_entry_point(ent): |
||
549 | continue |
||
550 | |||
551 | name = self._c_function(ent, prefix, True, True) |
||
552 | |||
553 | if ent.handcode: |
||
554 | asm.append('#if 0') |
||
555 | |||
556 | if ent.hidden: |
||
557 | asm.append('".hidden "%s"\\n"' % (name)) |
||
558 | |||
559 | if ent.alias and not (ent.alias.hidden and no_hidden): |
||
560 | asm.append('".globl "%s"\\n"' % (name)) |
||
561 | asm.append('".set "%s", "%s"\\n"' % (name, |
||
562 | self._c_function(ent.alias, prefix, True, True))) |
||
563 | else: |
||
564 | asm.append('STUB_ASM_ENTRY(%s)"\\n"' % (name)) |
||
565 | asm.append('"\\t"STUB_ASM_CODE("%d")"\\n"' % (ent.slot)) |
||
566 | |||
567 | if ent.handcode: |
||
568 | asm.append('#endif') |
||
569 | asm.append('') |
||
570 | |||
571 | return "\n".join(asm) |
||
572 | |||
573 | def output_for_lib(self): |
||
574 | print self.c_notice() |
||
575 | |||
576 | if self.c_header: |
||
577 | |||
578 | print self.c_header |
||
579 | |||
580 | |||
581 | print '#ifdef MAPI_TMP_DEFINES' |
||
582 | print self.c_public_includes() |
||
583 | |||
584 | print self.c_public_declarations(self.prefix_lib) |
||
585 | print '#undef MAPI_TMP_DEFINES' |
||
586 | print '#endif /* MAPI_TMP_DEFINES */' |
||
587 | |||
588 | if self.lib_need_table_size: |
||
589 | |||
590 | print '#ifdef MAPI_TMP_TABLE' |
||
591 | print self.c_mapi_table() |
||
592 | print '#undef MAPI_TMP_TABLE' |
||
593 | print '#endif /* MAPI_TMP_TABLE */' |
||
594 | |||
595 | if self.lib_need_noop_array: |
||
596 | |||
597 | print '#ifdef MAPI_TMP_NOOP_ARRAY' |
||
598 | print '#ifdef DEBUG' |
||
599 | |||
600 | print self.c_noop_functions(self.prefix_noop, self.prefix_warn) |
||
601 | |||
602 | print 'const mapi_func table_%s_array[] = {' % (self.prefix_noop) |
||
603 | print self.c_noop_initializer(self.prefix_noop, False) |
||
604 | print '};' |
||
605 | |||
606 | print '#else /* DEBUG */' |
||
607 | |||
608 | print 'const mapi_func table_%s_array[] = {' % (self.prefix_noop) |
||
609 | print self.c_noop_initializer(self.prefix_noop, True) |
||
610 | print '};' |
||
611 | |||
612 | print '#endif /* DEBUG */' |
||
613 | print '#undef MAPI_TMP_NOOP_ARRAY' |
||
614 | print '#endif /* MAPI_TMP_NOOP_ARRAY */' |
||
615 | |||
616 | if self.lib_need_stubs: |
||
617 | pool, pool_offsets = self.c_stub_string_pool() |
||
618 | |||
619 | print '#ifdef MAPI_TMP_PUBLIC_STUBS' |
||
620 | print 'static const char public_string_pool[] =' |
||
621 | print pool |
||
622 | |||
623 | print 'static const struct mapi_stub public_stubs[] = {' |
||
624 | print self.c_stub_initializer(self.prefix_lib, pool_offsets) |
||
625 | print '};' |
||
626 | print '#undef MAPI_TMP_PUBLIC_STUBS' |
||
627 | print '#endif /* MAPI_TMP_PUBLIC_STUBS */' |
||
628 | |||
629 | if self.lib_need_all_entries: |
||
630 | |||
631 | print '#ifdef MAPI_TMP_PUBLIC_ENTRIES' |
||
632 | print self.c_public_dispatches(self.prefix_lib, False) |
||
633 | |||
634 | print 'static const mapi_func public_entries[] = {' |
||
635 | print self.c_public_initializer(self.prefix_lib) |
||
636 | print '};' |
||
637 | print '#undef MAPI_TMP_PUBLIC_ENTRIES' |
||
638 | print '#endif /* MAPI_TMP_PUBLIC_ENTRIES */' |
||
639 | |||
640 | |||
641 | print '#ifdef MAPI_TMP_STUB_ASM_GCC' |
||
642 | print '__asm__(' |
||
643 | print self.c_asm_gcc(self.prefix_lib, False) |
||
644 | print ');' |
||
645 | print '#undef MAPI_TMP_STUB_ASM_GCC' |
||
646 | print '#endif /* MAPI_TMP_STUB_ASM_GCC */' |
||
647 | |||
648 | if self.lib_need_non_hidden_entries: |
||
649 | all_hidden = True |
||
650 | for ent in self.entries: |
||
651 | if not ent.hidden: |
||
652 | all_hidden = False |
||
653 | break |
||
654 | if not all_hidden: |
||
655 | |||
656 | print '#ifdef MAPI_TMP_PUBLIC_ENTRIES_NO_HIDDEN' |
||
657 | print self.c_public_dispatches(self.prefix_lib, True) |
||
658 | |||
659 | print '/* does not need public_entries */' |
||
660 | print '#undef MAPI_TMP_PUBLIC_ENTRIES_NO_HIDDEN' |
||
661 | print '#endif /* MAPI_TMP_PUBLIC_ENTRIES_NO_HIDDEN */' |
||
662 | |||
663 | |||
664 | print '#ifdef MAPI_TMP_STUB_ASM_GCC_NO_HIDDEN' |
||
665 | print '__asm__(' |
||
666 | print self.c_asm_gcc(self.prefix_lib, True) |
||
667 | print ');' |
||
668 | print '#undef MAPI_TMP_STUB_ASM_GCC_NO_HIDDEN' |
||
669 | print '#endif /* MAPI_TMP_STUB_ASM_GCC_NO_HIDDEN */' |
||
670 | |||
671 | def output_for_app(self): |
||
672 | print self.c_notice() |
||
673 | |||
674 | print self.c_private_declarations(self.prefix_app) |
||
675 | |||
676 | print '#ifdef API_TMP_DEFINE_SPEC' |
||
677 | |||
678 | print 'static const char %s_spec[] =' % (self.prefix_app) |
||
679 | print self.c_mapi_table_spec() |
||
680 | |||
681 | print 'static const mapi_proc %s_procs[] = {' % (self.prefix_app) |
||
682 | print self.c_mapi_table_initializer(self.prefix_app) |
||
683 | print '};' |
||
684 | |||
685 | print '#endif /* API_TMP_DEFINE_SPEC */' |
||
686 | |||
687 | class GLAPIPrinter(ABIPrinter): |
||
688 | """OpenGL API Printer""" |
||
689 | |||
690 | def __init__(self, entries): |
||
691 | for ent in entries: |
||
692 | self._override_for_api(ent) |
||
693 | super(GLAPIPrinter, self).__init__(entries) |
||
694 | |||
695 | self.api_defines = ['GL_GLEXT_PROTOTYPES'] |
||
696 | self.api_headers = ['"GL/gl.h"', '"GL/glext.h"'] |
||
697 | self.api_call = 'GLAPI' |
||
698 | self.api_entry = 'APIENTRY' |
||
699 | self.api_attrs = '' |
||
700 | |||
701 | self.lib_need_table_size = False |
||
702 | self.lib_need_noop_array = False |
||
703 | self.lib_need_stubs = False |
||
704 | self.lib_need_all_entries = False |
||
705 | self.lib_need_non_hidden_entries = True |
||
706 | |||
707 | self.prefix_lib = 'GLAPI_PREFIX' |
||
708 | self.prefix_app = '_mesa_' |
||
709 | self.prefix_noop = 'noop' |
||
710 | self.prefix_warn = self.prefix_lib |
||
711 | |||
712 | self.c_header = self._get_c_header() |
||
713 | |||
714 | def _override_for_api(self, ent): |
||
715 | """Override attributes of an entry if necessary for this |
||
716 | printer.""" |
||
717 | # By default, no override is necessary. |
||
718 | pass |
||
719 | |||
720 | def _get_c_header(self): |
||
721 | header = """#ifndef _GLAPI_TMP_H_ |
||
722 | #define _GLAPI_TMP_H_ |
||
723 | #ifdef USE_MGL_NAMESPACE |
||
724 | #define GLAPI_PREFIX(func) mgl##func |
||
725 | #define GLAPI_PREFIX_STR(func) "mgl"#func |
||
726 | #else |
||
727 | #define GLAPI_PREFIX(func) gl##func |
||
728 | #define GLAPI_PREFIX_STR(func) "gl"#func |
||
729 | #endif /* USE_MGL_NAMESPACE */ |
||
730 | |||
731 | typedef int GLclampx; |
||
732 | #endif /* _GLAPI_TMP_H_ */""" |
||
733 | |||
734 | return header |
||
735 | |||
736 | class ES1APIPrinter(GLAPIPrinter): |
||
737 | """OpenGL ES 1.x API Printer""" |
||
738 | |||
739 | def __init__(self, entries): |
||
740 | super(ES1APIPrinter, self).__init__(entries) |
||
741 | self.prefix_lib = 'gl' |
||
742 | self.prefix_warn = 'gl' |
||
743 | |||
744 | def _override_for_api(self, ent): |
||
745 | if ent.xml_data is None: |
||
746 | raise Exception('ES2 API printer requires XML input') |
||
747 | ent.hidden = ent.name not in \ |
||
748 | ent.xml_data.entry_points_for_api_version('es1') |
||
749 | ent.handcode = False |
||
750 | |||
751 | def _get_c_header(self): |
||
752 | header = """#ifndef _GLAPI_TMP_H_ |
||
753 | #define _GLAPI_TMP_H_ |
||
754 | typedef int GLclampx; |
||
755 | #endif /* _GLAPI_TMP_H_ */""" |
||
756 | |||
757 | return header |
||
758 | |||
759 | class ES2APIPrinter(GLAPIPrinter): |
||
760 | """OpenGL ES 2.x API Printer""" |
||
761 | |||
762 | def __init__(self, entries): |
||
763 | super(ES2APIPrinter, self).__init__(entries) |
||
764 | self.prefix_lib = 'gl' |
||
765 | self.prefix_warn = 'gl' |
||
766 | |||
767 | def _override_for_api(self, ent): |
||
768 | if ent.xml_data is None: |
||
769 | raise Exception('ES2 API printer requires XML input') |
||
770 | ent.hidden = ent.name not in \ |
||
771 | ent.xml_data.entry_points_for_api_version('es2') |
||
772 | ent.handcode = False |
||
773 | |||
774 | def _get_c_header(self): |
||
775 | header = """#ifndef _GLAPI_TMP_H_ |
||
776 | #define _GLAPI_TMP_H_ |
||
777 | typedef int GLclampx; |
||
778 | #endif /* _GLAPI_TMP_H_ */""" |
||
779 | |||
780 | return header |
||
781 | |||
782 | class SharedGLAPIPrinter(GLAPIPrinter): |
||
783 | """Shared GLAPI API Printer""" |
||
784 | |||
785 | def __init__(self, entries): |
||
786 | super(SharedGLAPIPrinter, self).__init__(entries) |
||
787 | |||
788 | self.lib_need_table_size = True |
||
789 | self.lib_need_noop_array = True |
||
790 | self.lib_need_stubs = True |
||
791 | self.lib_need_all_entries = True |
||
792 | self.lib_need_non_hidden_entries = False |
||
793 | |||
794 | self.prefix_lib = 'shared' |
||
795 | self.prefix_warn = 'gl' |
||
796 | |||
797 | def _override_for_api(self, ent): |
||
798 | ent.hidden = True |
||
799 | ent.handcode = False |
||
800 | |||
801 | def _get_c_header(self): |
||
802 | header = """#ifndef _GLAPI_TMP_H_ |
||
803 | #define _GLAPI_TMP_H_ |
||
804 | typedef int GLclampx; |
||
805 | #endif /* _GLAPI_TMP_H_ */""" |
||
806 | |||
807 | return header |
||
808 | |||
809 | class VGAPIPrinter(ABIPrinter): |
||
810 | """OpenVG API Printer""" |
||
811 | |||
812 | def __init__(self, entries): |
||
813 | super(VGAPIPrinter, self).__init__(entries) |
||
814 | |||
815 | self.api_defines = ['VG_VGEXT_PROTOTYPES'] |
||
816 | self.api_headers = ['"VG/openvg.h"', '"VG/vgext.h"'] |
||
817 | self.api_call = 'VG_API_CALL' |
||
818 | self.api_entry = 'VG_API_ENTRY' |
||
819 | self.api_attrs = 'VG_API_EXIT' |
||
820 | |||
821 | self.prefix_lib = 'vg' |
||
822 | self.prefix_app = 'vega' |
||
823 | self.prefix_noop = 'noop' |
||
824 | self.prefix_warn = 'vg' |
||
825 | |||
826 | def parse_args(): |
||
827 | printers = ['vgapi', 'glapi', 'es1api', 'es2api', 'shared-glapi'] |
||
828 | modes = ['lib', 'app'] |
||
829 | |||
830 | parser = OptionParser(usage='usage: %prog [options] |
||
831 | parser.add_option('-p', '--printer', dest='printer', |
||
832 | help='printer to use: %s' % (", ".join(printers))) |
||
833 | parser.add_option('-m', '--mode', dest='mode', |
||
834 | help='target user: %s' % (", ".join(modes))) |
||
835 | |||
836 | options, args = parser.parse_args() |
||
837 | if not args or options.printer not in printers or \ |
||
838 | options.mode not in modes: |
||
839 | parser.print_help() |
||
840 | sys.exit(1) |
||
841 | |||
842 | return (args[0], options) |
||
843 | |||
844 | def main(): |
||
845 | printers = { |
||
846 | 'vgapi': VGAPIPrinter, |
||
847 | 'glapi': GLAPIPrinter, |
||
848 | 'es1api': ES1APIPrinter, |
||
849 | 'es2api': ES2APIPrinter, |
||
850 | 'shared-glapi': SharedGLAPIPrinter, |
||
851 | } |
||
852 | |||
853 | filename, options = parse_args() |
||
854 | |||
855 | if filename.endswith('.xml'): |
||
856 | entries = abi_parse_xml(filename) |
||
857 | else: |
||
858 | entries = abi_parse(filename) |
||
859 | abi_sanity_check(entries) |
||
860 | |||
861 | printer = printers[options.printer](entries) |
||
862 | if options.mode == 'lib': |
||
863 | printer.output_for_lib() |
||
864 | else: |
||
865 | printer.output_for_app() |
||
866 | |||
867 | if __name__ == '__main__': |
||
868 | main()>>> |