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