1af69d88dSmrg 2af69d88dSmrg# Mesa 3-D graphics library 3af69d88dSmrg# 4af69d88dSmrg# Copyright (C) 2010 LunarG Inc. 5af69d88dSmrg# 6af69d88dSmrg# Permission is hereby granted, free of charge, to any person obtaining a 7af69d88dSmrg# copy of this software and associated documentation files (the "Software"), 8af69d88dSmrg# to deal in the Software without restriction, including without limitation 9af69d88dSmrg# the rights to use, copy, modify, merge, publish, distribute, sublicense, 10af69d88dSmrg# and/or sell copies of the Software, and to permit persons to whom the 11af69d88dSmrg# Software is furnished to do so, subject to the following conditions: 12af69d88dSmrg# 13af69d88dSmrg# The above copyright notice and this permission notice shall be included 14af69d88dSmrg# in all copies or substantial portions of the Software. 15af69d88dSmrg# 16af69d88dSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17af69d88dSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18af69d88dSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19af69d88dSmrg# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20af69d88dSmrg# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21af69d88dSmrg# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22af69d88dSmrg# DEALINGS IN THE SOFTWARE. 23af69d88dSmrg# 24af69d88dSmrg# Authors: 25af69d88dSmrg# Chia-I Wu <olv@lunarg.com> 26af69d88dSmrg 27af69d88dSmrgimport sys 28af69d88dSmrg# make it possible to import glapi 29af69d88dSmrgimport os 309f464c52SmayaGLAPI = os.path.join(".", os.path.dirname(__file__), "glapi", "gen") 319f464c52Smayasys.path.insert(0, GLAPI) 32af69d88dSmrg 3301e04c3fSmrgfrom operator import attrgetter 34af69d88dSmrgimport re 35af69d88dSmrgfrom optparse import OptionParser 36af69d88dSmrgimport gl_XML 37af69d88dSmrgimport glX_XML 38af69d88dSmrg 39af69d88dSmrg 40af69d88dSmrg# number of dynamic entries 41af69d88dSmrgABI_NUM_DYNAMIC_ENTRIES = 256 42af69d88dSmrg 43af69d88dSmrgclass ABIEntry(object): 44af69d88dSmrg """Represent an ABI entry.""" 45af69d88dSmrg 46af69d88dSmrg _match_c_param = re.compile( 47af69d88dSmrg '^(?P<type>[\w\s*]+?)(?P<name>\w+)(\[(?P<array>\d+)\])?$') 48af69d88dSmrg 49af69d88dSmrg def __init__(self, cols, attrs, xml_data = None): 50af69d88dSmrg self._parse(cols) 51af69d88dSmrg 52af69d88dSmrg self.slot = attrs['slot'] 53af69d88dSmrg self.hidden = attrs['hidden'] 54af69d88dSmrg self.alias = attrs['alias'] 55af69d88dSmrg self.handcode = attrs['handcode'] 56af69d88dSmrg self.xml_data = xml_data 57af69d88dSmrg 58af69d88dSmrg def c_prototype(self): 59af69d88dSmrg return '%s %s(%s)' % (self.c_return(), self.name, self.c_params()) 60af69d88dSmrg 61af69d88dSmrg def c_return(self): 62af69d88dSmrg ret = self.ret 63af69d88dSmrg if not ret: 64af69d88dSmrg ret = 'void' 65af69d88dSmrg 66af69d88dSmrg return ret 67af69d88dSmrg 68af69d88dSmrg def c_params(self): 69af69d88dSmrg """Return the parameter list used in the entry prototype.""" 70af69d88dSmrg c_params = [] 71af69d88dSmrg for t, n, a in self.params: 72af69d88dSmrg sep = '' if t.endswith('*') else ' ' 73af69d88dSmrg arr = '[%d]' % a if a else '' 74af69d88dSmrg c_params.append(t + sep + n + arr) 75af69d88dSmrg if not c_params: 76af69d88dSmrg c_params.append('void') 77af69d88dSmrg 78af69d88dSmrg return ", ".join(c_params) 79af69d88dSmrg 80af69d88dSmrg def c_args(self): 81af69d88dSmrg """Return the argument list used in the entry invocation.""" 82af69d88dSmrg c_args = [] 83af69d88dSmrg for t, n, a in self.params: 84af69d88dSmrg c_args.append(n) 85af69d88dSmrg 86af69d88dSmrg return ", ".join(c_args) 87af69d88dSmrg 88af69d88dSmrg def _parse(self, cols): 89af69d88dSmrg ret = cols.pop(0) 90af69d88dSmrg if ret == 'void': 91af69d88dSmrg ret = None 92af69d88dSmrg 93af69d88dSmrg name = cols.pop(0) 94af69d88dSmrg 95af69d88dSmrg params = [] 96af69d88dSmrg if not cols: 97af69d88dSmrg raise Exception(cols) 98af69d88dSmrg elif len(cols) == 1 and cols[0] == 'void': 99af69d88dSmrg pass 100af69d88dSmrg else: 101af69d88dSmrg for val in cols: 102af69d88dSmrg params.append(self._parse_param(val)) 103af69d88dSmrg 104af69d88dSmrg self.ret = ret 105af69d88dSmrg self.name = name 106af69d88dSmrg self.params = params 107af69d88dSmrg 108af69d88dSmrg def _parse_param(self, c_param): 109af69d88dSmrg m = self._match_c_param.match(c_param) 110af69d88dSmrg if not m: 111af69d88dSmrg raise Exception('unrecognized param ' + c_param) 112af69d88dSmrg 113af69d88dSmrg c_type = m.group('type').strip() 114af69d88dSmrg c_name = m.group('name') 115af69d88dSmrg c_array = m.group('array') 116af69d88dSmrg c_array = int(c_array) if c_array else 0 117af69d88dSmrg 118af69d88dSmrg return (c_type, c_name, c_array) 119af69d88dSmrg 120af69d88dSmrg def __str__(self): 121af69d88dSmrg return self.c_prototype() 122af69d88dSmrg 12301e04c3fSmrg def __lt__(self, other): 124af69d88dSmrg # compare slot, alias, and then name 12501e04c3fSmrg if self.slot == other.slot: 126af69d88dSmrg if not self.alias: 12701e04c3fSmrg return True 128af69d88dSmrg elif not other.alias: 12901e04c3fSmrg return False 13001e04c3fSmrg 13101e04c3fSmrg return self.name < other.name 132af69d88dSmrg 13301e04c3fSmrg return self.slot < other.slot 134af69d88dSmrg 135af69d88dSmrg 136af69d88dSmrgdef abi_parse_xml(xml): 137af69d88dSmrg """Parse a GLAPI XML file for ABI entries.""" 138af69d88dSmrg api = gl_XML.parse_GL_API(xml, glX_XML.glx_item_factory()) 139af69d88dSmrg 140af69d88dSmrg entry_dict = {} 141af69d88dSmrg for func in api.functionIterateByOffset(): 142af69d88dSmrg # make sure func.name appear first 143af69d88dSmrg entry_points = func.entry_points[:] 144af69d88dSmrg entry_points.remove(func.name) 145af69d88dSmrg entry_points.insert(0, func.name) 146af69d88dSmrg 147af69d88dSmrg for name in entry_points: 148af69d88dSmrg attrs = { 149af69d88dSmrg 'slot': func.offset, 150af69d88dSmrg 'hidden': not func.is_static_entry_point(name), 151af69d88dSmrg 'alias': None if name == func.name else func.name, 152af69d88dSmrg 'handcode': bool(func.has_different_protocol(name)), 153af69d88dSmrg } 154af69d88dSmrg 155af69d88dSmrg # post-process attrs 156af69d88dSmrg if attrs['alias']: 157af69d88dSmrg try: 158af69d88dSmrg alias = entry_dict[attrs['alias']] 159af69d88dSmrg except KeyError: 160af69d88dSmrg raise Exception('failed to alias %s' % attrs['alias']) 161af69d88dSmrg if alias.alias: 162af69d88dSmrg raise Exception('recursive alias %s' % ent.name) 163af69d88dSmrg attrs['alias'] = alias 164af69d88dSmrg if attrs['handcode']: 165af69d88dSmrg attrs['handcode'] = func.static_glx_name(name) 166af69d88dSmrg else: 167af69d88dSmrg attrs['handcode'] = None 168af69d88dSmrg 16901e04c3fSmrg if name in entry_dict: 170af69d88dSmrg raise Exception('%s is duplicated' % (name)) 171af69d88dSmrg 172af69d88dSmrg cols = [] 173af69d88dSmrg cols.append(func.return_type) 174af69d88dSmrg cols.append(name) 175af69d88dSmrg params = func.get_parameter_string(name) 176af69d88dSmrg cols.extend([p.strip() for p in params.split(',')]) 177af69d88dSmrg 178af69d88dSmrg ent = ABIEntry(cols, attrs, func) 179af69d88dSmrg entry_dict[ent.name] = ent 180af69d88dSmrg 18101e04c3fSmrg entries = sorted(entry_dict.values()) 182af69d88dSmrg 183af69d88dSmrg return entries 184af69d88dSmrg 185af69d88dSmrgdef abi_sanity_check(entries): 186af69d88dSmrg if not entries: 187af69d88dSmrg return 188af69d88dSmrg 189af69d88dSmrg all_names = [] 190af69d88dSmrg last_slot = entries[-1].slot 191af69d88dSmrg i = 0 19201e04c3fSmrg for slot in range(last_slot + 1): 193af69d88dSmrg if entries[i].slot != slot: 194af69d88dSmrg raise Exception('entries are not ordered by slots') 195af69d88dSmrg if entries[i].alias: 196af69d88dSmrg raise Exception('first entry of slot %d aliases %s' 197af69d88dSmrg % (slot, entries[i].alias.name)) 198af69d88dSmrg handcode = None 199af69d88dSmrg while i < len(entries) and entries[i].slot == slot: 200af69d88dSmrg ent = entries[i] 201af69d88dSmrg if not handcode and ent.handcode: 202af69d88dSmrg handcode = ent.handcode 203af69d88dSmrg elif ent.handcode != handcode: 204af69d88dSmrg raise Exception('two aliases with handcode %s != %s', 205af69d88dSmrg ent.handcode, handcode) 206af69d88dSmrg 207af69d88dSmrg if ent.name in all_names: 208af69d88dSmrg raise Exception('%s is duplicated' % (ent.name)) 209af69d88dSmrg if ent.alias and ent.alias.name not in all_names: 210af69d88dSmrg raise Exception('failed to alias %s' % (ent.alias.name)) 211af69d88dSmrg all_names.append(ent.name) 212af69d88dSmrg i += 1 213af69d88dSmrg if i < len(entries): 214af69d88dSmrg raise Exception('there are %d invalid entries' % (len(entries) - 1)) 215af69d88dSmrg 216af69d88dSmrgclass ABIPrinter(object): 217af69d88dSmrg """MAPI Printer""" 218af69d88dSmrg 219af69d88dSmrg def __init__(self, entries): 220af69d88dSmrg self.entries = entries 221af69d88dSmrg 222af69d88dSmrg # sort entries by their names 22301e04c3fSmrg self.entries_sorted_by_names = sorted(self.entries, key=attrgetter('name')) 224af69d88dSmrg 225af69d88dSmrg self.indent = ' ' * 3 226af69d88dSmrg self.noop_warn = 'noop_warn' 227af69d88dSmrg self.noop_generic = 'noop_generic' 228af69d88dSmrg self.current_get = 'entry_current_get' 229af69d88dSmrg 230af69d88dSmrg self.api_defines = [] 231af69d88dSmrg self.api_headers = ['"KHR/khrplatform.h"'] 232af69d88dSmrg self.api_call = 'KHRONOS_APICALL' 233af69d88dSmrg self.api_entry = 'KHRONOS_APIENTRY' 234af69d88dSmrg self.api_attrs = 'KHRONOS_APIATTRIBUTES' 235af69d88dSmrg 236af69d88dSmrg self.c_header = '' 237af69d88dSmrg 238af69d88dSmrg self.lib_need_table_size = True 239af69d88dSmrg self.lib_need_noop_array = True 240af69d88dSmrg self.lib_need_stubs = True 241af69d88dSmrg self.lib_need_all_entries = True 242af69d88dSmrg self.lib_need_non_hidden_entries = False 243af69d88dSmrg 244af69d88dSmrg def c_notice(self): 245af69d88dSmrg return '/* This file is automatically generated by mapi_abi.py. Do not modify. */' 246af69d88dSmrg 247af69d88dSmrg def c_public_includes(self): 248af69d88dSmrg """Return includes of the client API headers.""" 249af69d88dSmrg defines = ['#define ' + d for d in self.api_defines] 250af69d88dSmrg includes = ['#include ' + h for h in self.api_headers] 251af69d88dSmrg return "\n".join(defines + includes) 252af69d88dSmrg 253af69d88dSmrg def need_entry_point(self, ent): 254af69d88dSmrg """Return True if an entry point is needed for the entry.""" 255af69d88dSmrg # non-handcode hidden aliases may share the entry they alias 256af69d88dSmrg use_alias = (ent.hidden and ent.alias and not ent.handcode) 257af69d88dSmrg return not use_alias 258af69d88dSmrg 259af69d88dSmrg def c_public_declarations(self, prefix): 260af69d88dSmrg """Return the declarations of public entry points.""" 261af69d88dSmrg decls = [] 262af69d88dSmrg for ent in self.entries: 263af69d88dSmrg if not self.need_entry_point(ent): 264af69d88dSmrg continue 265af69d88dSmrg export = self.api_call if not ent.hidden else '' 2669f464c52Smaya if not ent.hidden or not self.lib_need_non_hidden_entries: 2679f464c52Smaya decls.append(self._c_decl(ent, prefix, True, export) + ';') 268af69d88dSmrg 269af69d88dSmrg return "\n".join(decls) 270af69d88dSmrg 271af69d88dSmrg def c_mapi_table(self): 272af69d88dSmrg """Return defines of the dispatch table size.""" 273af69d88dSmrg num_static_entries = self.entries[-1].slot + 1 274af69d88dSmrg return ('#define MAPI_TABLE_NUM_STATIC %d\n' + \ 275af69d88dSmrg '#define MAPI_TABLE_NUM_DYNAMIC %d') % ( 276af69d88dSmrg num_static_entries, ABI_NUM_DYNAMIC_ENTRIES) 277af69d88dSmrg 278af69d88dSmrg def _c_function(self, ent, prefix, mangle=False, stringify=False): 279af69d88dSmrg """Return the function name of an entry.""" 280af69d88dSmrg formats = { 281af69d88dSmrg True: { True: '%s_STR(%s)', False: '%s(%s)' }, 282af69d88dSmrg False: { True: '"%s%s"', False: '%s%s' }, 283af69d88dSmrg } 284af69d88dSmrg fmt = formats[prefix.isupper()][stringify] 285af69d88dSmrg name = ent.name 286af69d88dSmrg if mangle and ent.hidden: 287af69d88dSmrg name = '_dispatch_stub_' + str(ent.slot) 288af69d88dSmrg return fmt % (prefix, name) 289af69d88dSmrg 290af69d88dSmrg def _c_function_call(self, ent, prefix): 291af69d88dSmrg """Return the function name used for calling.""" 292af69d88dSmrg if ent.handcode: 293af69d88dSmrg # _c_function does not handle this case 294af69d88dSmrg formats = { True: '%s(%s)', False: '%s%s' } 295af69d88dSmrg fmt = formats[prefix.isupper()] 296af69d88dSmrg name = fmt % (prefix, ent.handcode) 297af69d88dSmrg elif self.need_entry_point(ent): 298af69d88dSmrg name = self._c_function(ent, prefix, True) 299af69d88dSmrg else: 300af69d88dSmrg name = self._c_function(ent.alias, prefix, True) 301af69d88dSmrg return name 302af69d88dSmrg 303af69d88dSmrg def _c_decl(self, ent, prefix, mangle=False, export=''): 304af69d88dSmrg """Return the C declaration for the entry.""" 305af69d88dSmrg decl = '%s %s %s(%s)' % (ent.c_return(), self.api_entry, 306af69d88dSmrg self._c_function(ent, prefix, mangle), ent.c_params()) 307af69d88dSmrg if export: 308af69d88dSmrg decl = export + ' ' + decl 309af69d88dSmrg if self.api_attrs: 310af69d88dSmrg decl += ' ' + self.api_attrs 311af69d88dSmrg 312af69d88dSmrg return decl 313af69d88dSmrg 314af69d88dSmrg def _c_cast(self, ent): 315af69d88dSmrg """Return the C cast for the entry.""" 316af69d88dSmrg cast = '%s (%s *)(%s)' % ( 317af69d88dSmrg ent.c_return(), self.api_entry, ent.c_params()) 318af69d88dSmrg 319af69d88dSmrg return cast 320af69d88dSmrg 321af69d88dSmrg def c_public_dispatches(self, prefix, no_hidden): 322af69d88dSmrg """Return the public dispatch functions.""" 323af69d88dSmrg dispatches = [] 324af69d88dSmrg for ent in self.entries: 325af69d88dSmrg if ent.hidden and no_hidden: 326af69d88dSmrg continue 327af69d88dSmrg 328af69d88dSmrg if not self.need_entry_point(ent): 329af69d88dSmrg continue 330af69d88dSmrg 331af69d88dSmrg export = self.api_call if not ent.hidden else '' 332af69d88dSmrg 333af69d88dSmrg proto = self._c_decl(ent, prefix, True, export) 334af69d88dSmrg cast = self._c_cast(ent) 335af69d88dSmrg 336af69d88dSmrg ret = '' 337af69d88dSmrg if ent.ret: 338af69d88dSmrg ret = 'return ' 339af69d88dSmrg stmt1 = self.indent 34001e04c3fSmrg stmt1 += 'const struct _glapi_table *_tbl = %s();' % ( 341af69d88dSmrg self.current_get) 342af69d88dSmrg stmt2 = self.indent 343af69d88dSmrg stmt2 += 'mapi_func _func = ((const mapi_func *) _tbl)[%d];' % ( 344af69d88dSmrg ent.slot) 345af69d88dSmrg stmt3 = self.indent 346af69d88dSmrg stmt3 += '%s((%s) _func)(%s);' % (ret, cast, ent.c_args()) 347af69d88dSmrg 348af69d88dSmrg disp = '%s\n{\n%s\n%s\n%s\n}' % (proto, stmt1, stmt2, stmt3) 349af69d88dSmrg 350af69d88dSmrg if ent.handcode: 351af69d88dSmrg disp = '#if 0\n' + disp + '\n#endif' 352af69d88dSmrg 353af69d88dSmrg dispatches.append(disp) 354af69d88dSmrg 355af69d88dSmrg return '\n\n'.join(dispatches) 356af69d88dSmrg 357af69d88dSmrg def c_public_initializer(self, prefix): 358af69d88dSmrg """Return the initializer for public dispatch functions.""" 359af69d88dSmrg names = [] 360af69d88dSmrg for ent in self.entries: 361af69d88dSmrg if ent.alias: 362af69d88dSmrg continue 363af69d88dSmrg 364af69d88dSmrg name = '%s(mapi_func) %s' % (self.indent, 365af69d88dSmrg self._c_function_call(ent, prefix)) 366af69d88dSmrg names.append(name) 367af69d88dSmrg 368af69d88dSmrg return ',\n'.join(names) 369af69d88dSmrg 370af69d88dSmrg def c_stub_string_pool(self): 371af69d88dSmrg """Return the string pool for use by stubs.""" 372af69d88dSmrg # sort entries by their names 37301e04c3fSmrg sorted_entries = sorted(self.entries, key=attrgetter('name')) 374af69d88dSmrg 375af69d88dSmrg pool = [] 376af69d88dSmrg offsets = {} 377af69d88dSmrg count = 0 378af69d88dSmrg for ent in sorted_entries: 379af69d88dSmrg offsets[ent] = count 380af69d88dSmrg pool.append('%s' % (ent.name)) 381af69d88dSmrg count += len(ent.name) + 1 382af69d88dSmrg 383af69d88dSmrg pool_str = self.indent + '"' + \ 384af69d88dSmrg ('\\0"\n' + self.indent + '"').join(pool) + '";' 385af69d88dSmrg return (pool_str, offsets) 386af69d88dSmrg 387af69d88dSmrg def c_stub_initializer(self, prefix, pool_offsets): 388af69d88dSmrg """Return the initializer for struct mapi_stub array.""" 389af69d88dSmrg stubs = [] 390af69d88dSmrg for ent in self.entries_sorted_by_names: 391af69d88dSmrg stubs.append('%s{ (void *) %d, %d, NULL }' % ( 392af69d88dSmrg self.indent, pool_offsets[ent], ent.slot)) 393af69d88dSmrg 394af69d88dSmrg return ',\n'.join(stubs) 395af69d88dSmrg 396af69d88dSmrg def c_noop_functions(self, prefix, warn_prefix): 397af69d88dSmrg """Return the noop functions.""" 398af69d88dSmrg noops = [] 399af69d88dSmrg for ent in self.entries: 400af69d88dSmrg if ent.alias: 401af69d88dSmrg continue 402af69d88dSmrg 403af69d88dSmrg proto = self._c_decl(ent, prefix, False, 'static') 404af69d88dSmrg 405af69d88dSmrg stmt1 = self.indent; 406af69d88dSmrg space = '' 407af69d88dSmrg for t, n, a in ent.params: 408af69d88dSmrg stmt1 += "%s(void) %s;" % (space, n) 409af69d88dSmrg space = ' ' 410af69d88dSmrg 411af69d88dSmrg if ent.params: 412af69d88dSmrg stmt1 += '\n'; 413af69d88dSmrg 414af69d88dSmrg stmt1 += self.indent + '%s(%s);' % (self.noop_warn, 415af69d88dSmrg self._c_function(ent, warn_prefix, False, True)) 416af69d88dSmrg 417af69d88dSmrg if ent.ret: 418af69d88dSmrg stmt2 = self.indent + 'return (%s) 0;' % (ent.ret) 419af69d88dSmrg noop = '%s\n{\n%s\n%s\n}' % (proto, stmt1, stmt2) 420af69d88dSmrg else: 421af69d88dSmrg noop = '%s\n{\n%s\n}' % (proto, stmt1) 422af69d88dSmrg 423af69d88dSmrg noops.append(noop) 424af69d88dSmrg 425af69d88dSmrg return '\n\n'.join(noops) 426af69d88dSmrg 427af69d88dSmrg def c_noop_initializer(self, prefix, use_generic): 428af69d88dSmrg """Return an initializer for the noop dispatch table.""" 429af69d88dSmrg entries = [self._c_function(ent, prefix) 430af69d88dSmrg for ent in self.entries if not ent.alias] 431af69d88dSmrg if use_generic: 432af69d88dSmrg entries = [self.noop_generic] * len(entries) 433af69d88dSmrg 434af69d88dSmrg entries.extend([self.noop_generic] * ABI_NUM_DYNAMIC_ENTRIES) 435af69d88dSmrg 436af69d88dSmrg pre = self.indent + '(mapi_func) ' 437af69d88dSmrg return pre + (',\n' + pre).join(entries) 438af69d88dSmrg 439af69d88dSmrg def c_asm_gcc(self, prefix, no_hidden): 440af69d88dSmrg asm = [] 441af69d88dSmrg 442af69d88dSmrg for ent in self.entries: 443af69d88dSmrg if ent.hidden and no_hidden: 444af69d88dSmrg continue 445af69d88dSmrg 446af69d88dSmrg if not self.need_entry_point(ent): 447af69d88dSmrg continue 448af69d88dSmrg 449af69d88dSmrg name = self._c_function(ent, prefix, True, True) 450af69d88dSmrg 451af69d88dSmrg if ent.handcode: 452af69d88dSmrg asm.append('#if 0') 453af69d88dSmrg 454af69d88dSmrg if ent.hidden: 455af69d88dSmrg asm.append('".hidden "%s"\\n"' % (name)) 456af69d88dSmrg 457af69d88dSmrg if ent.alias and not (ent.alias.hidden and no_hidden): 458af69d88dSmrg asm.append('".globl "%s"\\n"' % (name)) 459af69d88dSmrg asm.append('".set "%s", "%s"\\n"' % (name, 460af69d88dSmrg self._c_function(ent.alias, prefix, True, True))) 461af69d88dSmrg else: 462af69d88dSmrg asm.append('STUB_ASM_ENTRY(%s)"\\n"' % (name)) 463af69d88dSmrg asm.append('"\\t"STUB_ASM_CODE("%d")"\\n"' % (ent.slot)) 464af69d88dSmrg 465af69d88dSmrg if ent.handcode: 466af69d88dSmrg asm.append('#endif') 467af69d88dSmrg asm.append('') 468af69d88dSmrg 469af69d88dSmrg return "\n".join(asm) 470af69d88dSmrg 471af69d88dSmrg def output_for_lib(self): 47201e04c3fSmrg print(self.c_notice()) 473af69d88dSmrg 474af69d88dSmrg if self.c_header: 47501e04c3fSmrg print() 47601e04c3fSmrg print(self.c_header) 477af69d88dSmrg 47801e04c3fSmrg print() 47901e04c3fSmrg print('#ifdef MAPI_TMP_DEFINES') 48001e04c3fSmrg print(self.c_public_includes()) 48101e04c3fSmrg print() 4827ec681f3Smrg print('#ifdef MemoryBarrier') 4837ec681f3Smrg print('#undef MemoryBarrier') 4847ec681f3Smrg print('#endif') 4857ec681f3Smrg print() 48601e04c3fSmrg print(self.c_public_declarations(self.prefix_lib)) 48701e04c3fSmrg print('#undef MAPI_TMP_DEFINES') 48801e04c3fSmrg print('#endif /* MAPI_TMP_DEFINES */') 489af69d88dSmrg 490af69d88dSmrg if self.lib_need_table_size: 49101e04c3fSmrg print() 49201e04c3fSmrg print('#ifdef MAPI_TMP_TABLE') 49301e04c3fSmrg print(self.c_mapi_table()) 49401e04c3fSmrg print('#undef MAPI_TMP_TABLE') 49501e04c3fSmrg print('#endif /* MAPI_TMP_TABLE */') 496af69d88dSmrg 497af69d88dSmrg if self.lib_need_noop_array: 49801e04c3fSmrg print() 49901e04c3fSmrg print('#ifdef MAPI_TMP_NOOP_ARRAY') 50001e04c3fSmrg print('#ifdef DEBUG') 50101e04c3fSmrg print() 50201e04c3fSmrg print(self.c_noop_functions(self.prefix_noop, self.prefix_warn)) 50301e04c3fSmrg print() 50401e04c3fSmrg print('const mapi_func table_%s_array[] = {' % (self.prefix_noop)) 50501e04c3fSmrg print(self.c_noop_initializer(self.prefix_noop, False)) 50601e04c3fSmrg print('};') 50701e04c3fSmrg print() 50801e04c3fSmrg print('#else /* DEBUG */') 50901e04c3fSmrg print() 51001e04c3fSmrg print('const mapi_func table_%s_array[] = {' % (self.prefix_noop)) 51101e04c3fSmrg print(self.c_noop_initializer(self.prefix_noop, True)) 51201e04c3fSmrg print('};') 51301e04c3fSmrg print() 51401e04c3fSmrg print('#endif /* DEBUG */') 51501e04c3fSmrg print('#undef MAPI_TMP_NOOP_ARRAY') 51601e04c3fSmrg print('#endif /* MAPI_TMP_NOOP_ARRAY */') 517af69d88dSmrg 518af69d88dSmrg if self.lib_need_stubs: 519af69d88dSmrg pool, pool_offsets = self.c_stub_string_pool() 52001e04c3fSmrg print() 52101e04c3fSmrg print('#ifdef MAPI_TMP_PUBLIC_STUBS') 52201e04c3fSmrg print('static const char public_string_pool[] =') 52301e04c3fSmrg print(pool) 52401e04c3fSmrg print() 52501e04c3fSmrg print('static const struct mapi_stub public_stubs[] = {') 52601e04c3fSmrg print(self.c_stub_initializer(self.prefix_lib, pool_offsets)) 52701e04c3fSmrg print('};') 52801e04c3fSmrg print('#undef MAPI_TMP_PUBLIC_STUBS') 52901e04c3fSmrg print('#endif /* MAPI_TMP_PUBLIC_STUBS */') 530af69d88dSmrg 531af69d88dSmrg if self.lib_need_all_entries: 53201e04c3fSmrg print() 53301e04c3fSmrg print('#ifdef MAPI_TMP_PUBLIC_ENTRIES') 53401e04c3fSmrg print(self.c_public_dispatches(self.prefix_lib, False)) 53501e04c3fSmrg print() 53601e04c3fSmrg print('static const mapi_func public_entries[] = {') 53701e04c3fSmrg print(self.c_public_initializer(self.prefix_lib)) 53801e04c3fSmrg print('};') 53901e04c3fSmrg print('#undef MAPI_TMP_PUBLIC_ENTRIES') 54001e04c3fSmrg print('#endif /* MAPI_TMP_PUBLIC_ENTRIES */') 54101e04c3fSmrg 54201e04c3fSmrg print() 54301e04c3fSmrg print('#ifdef MAPI_TMP_STUB_ASM_GCC') 54401e04c3fSmrg print('__asm__(') 54501e04c3fSmrg print(self.c_asm_gcc(self.prefix_lib, False)) 54601e04c3fSmrg print(');') 54701e04c3fSmrg print('#undef MAPI_TMP_STUB_ASM_GCC') 54801e04c3fSmrg print('#endif /* MAPI_TMP_STUB_ASM_GCC */') 549af69d88dSmrg 550af69d88dSmrg if self.lib_need_non_hidden_entries: 551af69d88dSmrg all_hidden = True 552af69d88dSmrg for ent in self.entries: 553af69d88dSmrg if not ent.hidden: 554af69d88dSmrg all_hidden = False 555af69d88dSmrg break 556af69d88dSmrg if not all_hidden: 55701e04c3fSmrg print() 55801e04c3fSmrg print('#ifdef MAPI_TMP_PUBLIC_ENTRIES_NO_HIDDEN') 55901e04c3fSmrg print(self.c_public_dispatches(self.prefix_lib, True)) 56001e04c3fSmrg print() 56101e04c3fSmrg print('/* does not need public_entries */') 56201e04c3fSmrg print('#undef MAPI_TMP_PUBLIC_ENTRIES_NO_HIDDEN') 56301e04c3fSmrg print('#endif /* MAPI_TMP_PUBLIC_ENTRIES_NO_HIDDEN */') 56401e04c3fSmrg 56501e04c3fSmrg print() 56601e04c3fSmrg print('#ifdef MAPI_TMP_STUB_ASM_GCC_NO_HIDDEN') 56701e04c3fSmrg print('__asm__(') 56801e04c3fSmrg print(self.c_asm_gcc(self.prefix_lib, True)) 56901e04c3fSmrg print(');') 57001e04c3fSmrg print('#undef MAPI_TMP_STUB_ASM_GCC_NO_HIDDEN') 57101e04c3fSmrg print('#endif /* MAPI_TMP_STUB_ASM_GCC_NO_HIDDEN */') 572af69d88dSmrg 573af69d88dSmrgclass GLAPIPrinter(ABIPrinter): 574af69d88dSmrg """OpenGL API Printer""" 575af69d88dSmrg 576af69d88dSmrg def __init__(self, entries): 577af69d88dSmrg for ent in entries: 578af69d88dSmrg self._override_for_api(ent) 579af69d88dSmrg super(GLAPIPrinter, self).__init__(entries) 580af69d88dSmrg 581af69d88dSmrg self.api_defines = ['GL_GLEXT_PROTOTYPES'] 582af69d88dSmrg self.api_headers = ['"GL/gl.h"', '"GL/glext.h"'] 583af69d88dSmrg self.api_call = 'GLAPI' 584af69d88dSmrg self.api_entry = 'APIENTRY' 585af69d88dSmrg self.api_attrs = '' 586af69d88dSmrg 587af69d88dSmrg self.lib_need_table_size = False 588af69d88dSmrg self.lib_need_noop_array = False 589af69d88dSmrg self.lib_need_stubs = False 590af69d88dSmrg self.lib_need_all_entries = False 591af69d88dSmrg self.lib_need_non_hidden_entries = True 592af69d88dSmrg 593af69d88dSmrg self.prefix_lib = 'GLAPI_PREFIX' 594af69d88dSmrg self.prefix_noop = 'noop' 595af69d88dSmrg self.prefix_warn = self.prefix_lib 596af69d88dSmrg 597af69d88dSmrg self.c_header = self._get_c_header() 598af69d88dSmrg 599af69d88dSmrg def _override_for_api(self, ent): 600af69d88dSmrg """Override attributes of an entry if necessary for this 601af69d88dSmrg printer.""" 602af69d88dSmrg # By default, no override is necessary. 603af69d88dSmrg pass 604af69d88dSmrg 605af69d88dSmrg def _get_c_header(self): 606af69d88dSmrg header = """#ifndef _GLAPI_TMP_H_ 607af69d88dSmrg#define _GLAPI_TMP_H_ 608af69d88dSmrg#define GLAPI_PREFIX(func) gl##func 609af69d88dSmrg#define GLAPI_PREFIX_STR(func) "gl"#func 610af69d88dSmrg 611af69d88dSmrgtypedef int GLclampx; 612af69d88dSmrg#endif /* _GLAPI_TMP_H_ */""" 613af69d88dSmrg 614af69d88dSmrg return header 615af69d88dSmrg 616af69d88dSmrgclass SharedGLAPIPrinter(GLAPIPrinter): 617af69d88dSmrg """Shared GLAPI API Printer""" 618af69d88dSmrg 619af69d88dSmrg def __init__(self, entries): 620af69d88dSmrg super(SharedGLAPIPrinter, self).__init__(entries) 621af69d88dSmrg 622af69d88dSmrg self.lib_need_table_size = True 623af69d88dSmrg self.lib_need_noop_array = True 624af69d88dSmrg self.lib_need_stubs = True 625af69d88dSmrg self.lib_need_all_entries = True 626af69d88dSmrg self.lib_need_non_hidden_entries = False 627af69d88dSmrg 628af69d88dSmrg self.prefix_lib = 'shared' 629af69d88dSmrg self.prefix_warn = 'gl' 630af69d88dSmrg 631af69d88dSmrg def _override_for_api(self, ent): 632af69d88dSmrg ent.hidden = True 633af69d88dSmrg ent.handcode = False 634af69d88dSmrg 635af69d88dSmrg def _get_c_header(self): 636af69d88dSmrg header = """#ifndef _GLAPI_TMP_H_ 637af69d88dSmrg#define _GLAPI_TMP_H_ 638af69d88dSmrgtypedef int GLclampx; 639af69d88dSmrg#endif /* _GLAPI_TMP_H_ */""" 640af69d88dSmrg 641af69d88dSmrg return header 642af69d88dSmrg 643af69d88dSmrgdef parse_args(): 64401e04c3fSmrg printers = ['glapi', 'es1api', 'es2api', 'shared-glapi'] 645af69d88dSmrg 6469f464c52Smaya parser = OptionParser(usage='usage: %prog [options] <xml_file>') 647af69d88dSmrg parser.add_option('-p', '--printer', dest='printer', 648af69d88dSmrg help='printer to use: %s' % (", ".join(printers))) 649af69d88dSmrg 650af69d88dSmrg options, args = parser.parse_args() 65101e04c3fSmrg if not args or options.printer not in printers: 652af69d88dSmrg parser.print_help() 653af69d88dSmrg sys.exit(1) 654af69d88dSmrg 6559f464c52Smaya if not args[0].endswith('.xml'): 6569f464c52Smaya parser.print_help() 6579f464c52Smaya sys.exit(1) 6589f464c52Smaya 659af69d88dSmrg return (args[0], options) 660af69d88dSmrg 661af69d88dSmrgdef main(): 662af69d88dSmrg printers = { 663af69d88dSmrg 'glapi': GLAPIPrinter, 664af69d88dSmrg 'shared-glapi': SharedGLAPIPrinter, 665af69d88dSmrg } 666af69d88dSmrg 667af69d88dSmrg filename, options = parse_args() 668af69d88dSmrg 6699f464c52Smaya entries = abi_parse_xml(filename) 670af69d88dSmrg abi_sanity_check(entries) 671af69d88dSmrg 672af69d88dSmrg printer = printers[options.printer](entries) 67301e04c3fSmrg printer.output_for_lib() 674af69d88dSmrg 675af69d88dSmrgif __name__ == '__main__': 676af69d88dSmrg main() 677