13464ebd5Sriastradh 23464ebd5Sriastradh# (C) Copyright IBM Corporation 2004, 2005 33464ebd5Sriastradh# All Rights Reserved. 43464ebd5Sriastradh# 53464ebd5Sriastradh# Permission is hereby granted, free of charge, to any person obtaining a 63464ebd5Sriastradh# copy of this software and associated documentation files (the "Software"), 73464ebd5Sriastradh# to deal in the Software without restriction, including without limitation 83464ebd5Sriastradh# on the rights to use, copy, modify, merge, publish, distribute, sub 93464ebd5Sriastradh# license, and/or sell copies of the Software, and to permit persons to whom 103464ebd5Sriastradh# the Software is furnished to do so, subject to the following conditions: 113464ebd5Sriastradh# 123464ebd5Sriastradh# The above copyright notice and this permission notice (including the next 133464ebd5Sriastradh# paragraph) shall be included in all copies or substantial portions of the 143464ebd5Sriastradh# Software. 153464ebd5Sriastradh# 163464ebd5Sriastradh# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 173464ebd5Sriastradh# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 183464ebd5Sriastradh# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 193464ebd5Sriastradh# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 203464ebd5Sriastradh# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 213464ebd5Sriastradh# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 223464ebd5Sriastradh# IN THE SOFTWARE. 233464ebd5Sriastradh# 243464ebd5Sriastradh# Authors: 253464ebd5Sriastradh# Ian Romanick <idr@us.ibm.com> 263464ebd5Sriastradh 2701e04c3fSmrgfrom collections import OrderedDict 28af69d88dSmrgfrom decimal import Decimal 29af69d88dSmrgimport xml.etree.ElementTree as ET 3001e04c3fSmrgimport re, sys 31af69d88dSmrgimport os.path 323464ebd5Sriastradhimport typeexpr 3301e04c3fSmrgimport static_data 343464ebd5Sriastradh 353464ebd5Sriastradh 363464ebd5Sriastradhdef parse_GL_API( file_name, factory = None ): 373464ebd5Sriastradh 38af69d88dSmrg if not factory: 39af69d88dSmrg factory = gl_item_factory() 403464ebd5Sriastradh 41af69d88dSmrg api = factory.create_api() 42af69d88dSmrg api.parse_file( file_name ) 433464ebd5Sriastradh 44af69d88dSmrg # After the XML has been processed, we need to go back and assign 45af69d88dSmrg # dispatch offsets to the functions that request that their offsets 46af69d88dSmrg # be assigned by the scripts. Typically this means all functions 47af69d88dSmrg # that are not part of the ABI. 483464ebd5Sriastradh 49af69d88dSmrg for func in api.functionIterateByCategory(): 509f464c52Smaya if func.assign_offset and func.offset < 0: 51af69d88dSmrg func.offset = api.next_offset; 52af69d88dSmrg api.next_offset += 1 533464ebd5Sriastradh 54af69d88dSmrg return api 553464ebd5Sriastradh 563464ebd5Sriastradh 57af69d88dSmrgdef is_attr_true( element, name, default = "false" ): 58af69d88dSmrg """Read a name value from an element's attributes. 593464ebd5Sriastradh 60af69d88dSmrg The value read from the attribute list must be either 'true' or 61af69d88dSmrg 'false'. If the value is 'false', zero will be returned. If the 62af69d88dSmrg value is 'true', non-zero will be returned. An exception will be 63af69d88dSmrg raised for any other value.""" 643464ebd5Sriastradh 65af69d88dSmrg value = element.get( name, default ) 66af69d88dSmrg if value == "true": 67af69d88dSmrg return 1 68af69d88dSmrg elif value == "false": 69af69d88dSmrg return 0 70af69d88dSmrg else: 71af69d88dSmrg raise RuntimeError('Invalid value "%s" for boolean "%s".' % (value, name)) 723464ebd5Sriastradh 733464ebd5Sriastradh 74af69d88dSmrgclass gl_print_base(object): 75af69d88dSmrg """Base class of all API pretty-printers. 763464ebd5Sriastradh 77af69d88dSmrg In the model-view-controller pattern, this is the view. Any derived 78af69d88dSmrg class will want to over-ride the printBody, printRealHader, and 79af69d88dSmrg printRealFooter methods. Some derived classes may want to over-ride 80af69d88dSmrg printHeader and printFooter, or even Print (though this is unlikely). 81af69d88dSmrg """ 823464ebd5Sriastradh 83af69d88dSmrg def __init__(self): 84af69d88dSmrg # Name of the script that is generating the output file. 85af69d88dSmrg # Every derived class should set this to the name of its 86af69d88dSmrg # source file. 873464ebd5Sriastradh 88af69d88dSmrg self.name = "a" 893464ebd5Sriastradh 903464ebd5Sriastradh 91af69d88dSmrg # License on the *generated* source file. This may differ 92af69d88dSmrg # from the license on the script that is generating the file. 93af69d88dSmrg # Every derived class should set this to some reasonable 94af69d88dSmrg # value. 95af69d88dSmrg # 96af69d88dSmrg # See license.py for an example of a reasonable value. 973464ebd5Sriastradh 98af69d88dSmrg self.license = "The license for this file is unspecified." 993464ebd5Sriastradh 1003464ebd5Sriastradh 101af69d88dSmrg # The header_tag is the name of the C preprocessor define 102af69d88dSmrg # used to prevent multiple inclusion. Typically only 103af69d88dSmrg # generated C header files need this to be set. Setting it 104af69d88dSmrg # causes code to be generated automatically in printHeader 105af69d88dSmrg # and printFooter. 1063464ebd5Sriastradh 107af69d88dSmrg self.header_tag = None 1083464ebd5Sriastradh 1093464ebd5Sriastradh 110af69d88dSmrg # List of file-private defines that must be undefined at the 111af69d88dSmrg # end of the file. This can be used in header files to define 112af69d88dSmrg # names for use in the file, then undefine them at the end of 113af69d88dSmrg # the header file. 1143464ebd5Sriastradh 115af69d88dSmrg self.undef_list = [] 116af69d88dSmrg return 1173464ebd5Sriastradh 1183464ebd5Sriastradh 119af69d88dSmrg def Print(self, api): 120af69d88dSmrg self.printHeader() 121af69d88dSmrg self.printBody(api) 122af69d88dSmrg self.printFooter() 123af69d88dSmrg return 1243464ebd5Sriastradh 1253464ebd5Sriastradh 126af69d88dSmrg def printHeader(self): 127af69d88dSmrg """Print the header associated with all files and call the printRealHeader method.""" 1283464ebd5Sriastradh 12901e04c3fSmrg print('/* DO NOT EDIT - This file generated automatically by %s script */' \ 13001e04c3fSmrg % (self.name)) 13101e04c3fSmrg print('') 13201e04c3fSmrg print('/*') 13301e04c3fSmrg print((' * ' + self.license.replace('\n', '\n * ')).replace(' \n', '\n')) 13401e04c3fSmrg print(' */') 13501e04c3fSmrg print('') 136af69d88dSmrg if self.header_tag: 13701e04c3fSmrg print('#if !defined( %s )' % (self.header_tag)) 13801e04c3fSmrg print('# define %s' % (self.header_tag)) 13901e04c3fSmrg print('') 140af69d88dSmrg self.printRealHeader(); 141af69d88dSmrg return 1423464ebd5Sriastradh 1433464ebd5Sriastradh 144af69d88dSmrg def printFooter(self): 145af69d88dSmrg """Print the header associated with all files and call the printRealFooter method.""" 1463464ebd5Sriastradh 147af69d88dSmrg self.printRealFooter() 1483464ebd5Sriastradh 149af69d88dSmrg if self.undef_list: 15001e04c3fSmrg print('') 151af69d88dSmrg for u in self.undef_list: 15201e04c3fSmrg print("# undef %s" % (u)) 1533464ebd5Sriastradh 154af69d88dSmrg if self.header_tag: 15501e04c3fSmrg print('') 15601e04c3fSmrg print('#endif /* !defined( %s ) */' % (self.header_tag)) 1573464ebd5Sriastradh 1583464ebd5Sriastradh 159af69d88dSmrg def printRealHeader(self): 160af69d88dSmrg """Print the "real" header for the created file. 1613464ebd5Sriastradh 162af69d88dSmrg In the base class, this function is empty. All derived 163af69d88dSmrg classes should over-ride this function.""" 164af69d88dSmrg return 1653464ebd5Sriastradh 1663464ebd5Sriastradh 167af69d88dSmrg def printRealFooter(self): 168af69d88dSmrg """Print the "real" footer for the created file. 1693464ebd5Sriastradh 170af69d88dSmrg In the base class, this function is empty. All derived 171af69d88dSmrg classes should over-ride this function.""" 172af69d88dSmrg return 1733464ebd5Sriastradh 174af69d88dSmrg 175af69d88dSmrg def printPure(self): 176af69d88dSmrg """Conditionally define `PURE' function attribute. 177af69d88dSmrg 178af69d88dSmrg Conditionally defines a preprocessor macro `PURE' that wraps 179af69d88dSmrg GCC's `pure' function attribute. The conditional code can be 180af69d88dSmrg easilly adapted to other compilers that support a similar 181af69d88dSmrg feature. 182af69d88dSmrg 183af69d88dSmrg The name is also added to the file's undef_list. 184af69d88dSmrg """ 185af69d88dSmrg self.undef_list.append("PURE") 18601e04c3fSmrg print("""# if defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) 1873464ebd5Sriastradh# define PURE __attribute__((pure)) 1883464ebd5Sriastradh# else 1893464ebd5Sriastradh# define PURE 19001e04c3fSmrg# endif""") 191af69d88dSmrg return 1923464ebd5Sriastradh 1933464ebd5Sriastradh 194af69d88dSmrg def printFastcall(self): 195af69d88dSmrg """Conditionally define `FASTCALL' function attribute. 1963464ebd5Sriastradh 197af69d88dSmrg Conditionally defines a preprocessor macro `FASTCALL' that 198af69d88dSmrg wraps GCC's `fastcall' function attribute. The conditional 199af69d88dSmrg code can be easilly adapted to other compilers that support a 200af69d88dSmrg similar feature. 2013464ebd5Sriastradh 202af69d88dSmrg The name is also added to the file's undef_list. 203af69d88dSmrg """ 2043464ebd5Sriastradh 205af69d88dSmrg self.undef_list.append("FASTCALL") 20601e04c3fSmrg print("""# if defined(__i386__) && defined(__GNUC__) && !defined(__CYGWIN__) && !defined(__MINGW32__) 2073464ebd5Sriastradh# define FASTCALL __attribute__((fastcall)) 2083464ebd5Sriastradh# else 2093464ebd5Sriastradh# define FASTCALL 21001e04c3fSmrg# endif""") 211af69d88dSmrg return 2123464ebd5Sriastradh 2133464ebd5Sriastradh 214af69d88dSmrg def printVisibility(self, S, s): 215af69d88dSmrg """Conditionally define visibility function attribute. 2163464ebd5Sriastradh 217af69d88dSmrg Conditionally defines a preprocessor macro name S that wraps 218af69d88dSmrg GCC's visibility function attribute. The visibility used is 219af69d88dSmrg the parameter s. The conditional code can be easilly adapted 220af69d88dSmrg to other compilers that support a similar feature. 2213464ebd5Sriastradh 222af69d88dSmrg The name is also added to the file's undef_list. 223af69d88dSmrg """ 2243464ebd5Sriastradh 225af69d88dSmrg self.undef_list.append(S) 22601e04c3fSmrg print("""# if defined(__GNUC__) && !defined(__CYGWIN__) && !defined(__MINGW32__) 2273464ebd5Sriastradh# define %s __attribute__((visibility("%s"))) 2283464ebd5Sriastradh# else 2293464ebd5Sriastradh# define %s 23001e04c3fSmrg# endif""" % (S, s, S)) 231af69d88dSmrg return 2323464ebd5Sriastradh 2333464ebd5Sriastradh 234af69d88dSmrg def printNoinline(self): 235af69d88dSmrg """Conditionally define `NOINLINE' function attribute. 2363464ebd5Sriastradh 237af69d88dSmrg Conditionally defines a preprocessor macro `NOINLINE' that 238af69d88dSmrg wraps GCC's `noinline' function attribute. The conditional 239af69d88dSmrg code can be easilly adapted to other compilers that support a 240af69d88dSmrg similar feature. 2413464ebd5Sriastradh 242af69d88dSmrg The name is also added to the file's undef_list. 243af69d88dSmrg """ 2443464ebd5Sriastradh 245af69d88dSmrg self.undef_list.append("NOINLINE") 24601e04c3fSmrg print("""# if defined(__GNUC__) 2473464ebd5Sriastradh# define NOINLINE __attribute__((noinline)) 2483464ebd5Sriastradh# else 2493464ebd5Sriastradh# define NOINLINE 25001e04c3fSmrg# endif""") 251af69d88dSmrg return 2523464ebd5Sriastradh 2533464ebd5Sriastradh 2543464ebd5Sriastradhdef real_function_name(element): 255af69d88dSmrg name = element.get( "name" ) 256af69d88dSmrg alias = element.get( "alias" ) 257af69d88dSmrg 258af69d88dSmrg if alias: 259af69d88dSmrg return alias 260af69d88dSmrg else: 261af69d88dSmrg return name 2623464ebd5Sriastradh 2633464ebd5Sriastradh 2643464ebd5Sriastradhdef real_category_name(c): 265af69d88dSmrg if re.compile("[1-9][0-9]*[.][0-9]+").match(c): 266af69d88dSmrg return "GL_VERSION_" + c.replace(".", "_") 267af69d88dSmrg else: 268af69d88dSmrg return c 2693464ebd5Sriastradh 2703464ebd5Sriastradh 2713464ebd5Sriastradhdef classify_category(name, number): 272af69d88dSmrg """Based on the category name and number, select a numerical class for it. 2733464ebd5Sriastradh 274af69d88dSmrg Categories are divided into four classes numbered 0 through 3. The 275af69d88dSmrg classes are: 2763464ebd5Sriastradh 277af69d88dSmrg 0. Core GL versions, sorted by version number. 278af69d88dSmrg 1. ARB extensions, sorted by extension number. 279af69d88dSmrg 2. Non-ARB extensions, sorted by extension number. 280af69d88dSmrg 3. Un-numbered extensions, sorted by extension name. 281af69d88dSmrg """ 2823464ebd5Sriastradh 283af69d88dSmrg try: 284af69d88dSmrg core_version = float(name) 28501e04c3fSmrg except Exception: 286af69d88dSmrg core_version = 0.0 2873464ebd5Sriastradh 288af69d88dSmrg if core_version > 0.0: 289af69d88dSmrg cat_type = 0 290af69d88dSmrg key = name 291af69d88dSmrg elif name.startswith("GL_ARB_") or name.startswith("GLX_ARB_") or name.startswith("WGL_ARB_"): 292af69d88dSmrg cat_type = 1 293af69d88dSmrg key = int(number) 294af69d88dSmrg else: 295af69d88dSmrg if number != None: 296af69d88dSmrg cat_type = 2 297af69d88dSmrg key = int(number) 298af69d88dSmrg else: 299af69d88dSmrg cat_type = 3 300af69d88dSmrg key = name 3013464ebd5Sriastradh 3023464ebd5Sriastradh 303af69d88dSmrg return [cat_type, key] 3043464ebd5Sriastradh 3053464ebd5Sriastradh 306af69d88dSmrgdef create_parameter_string(parameters, include_names): 307af69d88dSmrg """Create a parameter string from a list of gl_parameters.""" 3083464ebd5Sriastradh 309af69d88dSmrg list = [] 310af69d88dSmrg for p in parameters: 311af69d88dSmrg if p.is_padding: 312af69d88dSmrg continue 3133464ebd5Sriastradh 314af69d88dSmrg if include_names: 315af69d88dSmrg list.append( p.string() ) 316af69d88dSmrg else: 317af69d88dSmrg list.append( p.type_string() ) 3183464ebd5Sriastradh 319af69d88dSmrg if len(list) == 0: list = ["void"] 3203464ebd5Sriastradh 32101e04c3fSmrg return ", ".join(list) 3223464ebd5Sriastradh 3233464ebd5Sriastradh 324af69d88dSmrgclass gl_item(object): 325af69d88dSmrg def __init__(self, element, context, category): 326af69d88dSmrg self.context = context 327af69d88dSmrg self.name = element.get( "name" ) 328af69d88dSmrg self.category = real_category_name( category ) 3293464ebd5Sriastradh 330af69d88dSmrg return 3313464ebd5Sriastradh 3323464ebd5Sriastradh 333af69d88dSmrgclass gl_type( gl_item ): 334af69d88dSmrg def __init__(self, element, context, category): 335af69d88dSmrg gl_item.__init__(self, element, context, category) 336af69d88dSmrg self.size = int( element.get( "size" ), 0 ) 337af69d88dSmrg 338af69d88dSmrg te = typeexpr.type_expression( None ) 339af69d88dSmrg tn = typeexpr.type_node() 340af69d88dSmrg tn.size = int( element.get( "size" ), 0 ) 341af69d88dSmrg tn.integer = not is_attr_true( element, "float" ) 342af69d88dSmrg tn.unsigned = is_attr_true( element, "unsigned" ) 343af69d88dSmrg tn.pointer = is_attr_true( element, "pointer" ) 344af69d88dSmrg tn.name = "GL" + self.name 345af69d88dSmrg te.set_base_type_node( tn ) 3463464ebd5Sriastradh 347af69d88dSmrg self.type_expr = te 348af69d88dSmrg return 3493464ebd5Sriastradh 3503464ebd5Sriastradh 351af69d88dSmrg def get_type_expression(self): 352af69d88dSmrg return self.type_expr 3533464ebd5Sriastradh 3543464ebd5Sriastradh 355af69d88dSmrgclass gl_enum( gl_item ): 356af69d88dSmrg def __init__(self, element, context, category): 357af69d88dSmrg gl_item.__init__(self, element, context, category) 358af69d88dSmrg self.value = int( element.get( "value" ), 0 ) 359af69d88dSmrg 360af69d88dSmrg temp = element.get( "count" ) 361af69d88dSmrg if not temp or temp == "?": 362af69d88dSmrg self.default_count = -1 363af69d88dSmrg else: 364af69d88dSmrg try: 365af69d88dSmrg c = int(temp) 36601e04c3fSmrg except Exception: 367af69d88dSmrg raise RuntimeError('Invalid count value "%s" for enum "%s" in function "%s" when an integer was expected.' % (temp, self.name, n)) 368af69d88dSmrg 369af69d88dSmrg self.default_count = c 3703464ebd5Sriastradh 371af69d88dSmrg return 3723464ebd5Sriastradh 3733464ebd5Sriastradh 374af69d88dSmrg def priority(self): 375af69d88dSmrg """Calculate a 'priority' for this enum name. 3763464ebd5Sriastradh 377af69d88dSmrg When an enum is looked up by number, there may be many 378af69d88dSmrg possible names, but only one is the 'prefered' name. The 379af69d88dSmrg priority is used to select which name is the 'best'. 3803464ebd5Sriastradh 381af69d88dSmrg Highest precedence is given to core GL name. ARB extension 382af69d88dSmrg names have the next highest, followed by EXT extension names. 383af69d88dSmrg Vendor extension names are the lowest. 384af69d88dSmrg """ 3853464ebd5Sriastradh 386af69d88dSmrg if self.name.endswith( "_BIT" ): 387af69d88dSmrg bias = 1 388af69d88dSmrg else: 389af69d88dSmrg bias = 0 3903464ebd5Sriastradh 391af69d88dSmrg if self.category.startswith( "GL_VERSION_" ): 392af69d88dSmrg priority = 0 393af69d88dSmrg elif self.category.startswith( "GL_ARB_" ): 394af69d88dSmrg priority = 2 395af69d88dSmrg elif self.category.startswith( "GL_EXT_" ): 396af69d88dSmrg priority = 4 397af69d88dSmrg else: 398af69d88dSmrg priority = 6 3993464ebd5Sriastradh 400af69d88dSmrg return priority + bias 4013464ebd5Sriastradh 4023464ebd5Sriastradh 4033464ebd5Sriastradh 404af69d88dSmrgclass gl_parameter(object): 405af69d88dSmrg def __init__(self, element, context): 406af69d88dSmrg self.name = element.get( "name" ) 4073464ebd5Sriastradh 408af69d88dSmrg ts = element.get( "type" ) 409af69d88dSmrg self.type_expr = typeexpr.type_expression( ts, context ) 4103464ebd5Sriastradh 411af69d88dSmrg temp = element.get( "variable_param" ) 412af69d88dSmrg if temp: 413af69d88dSmrg self.count_parameter_list = temp.split( ' ' ) 414af69d88dSmrg else: 415af69d88dSmrg self.count_parameter_list = [] 4163464ebd5Sriastradh 417af69d88dSmrg # The count tag can be either a numeric string or the name of 418af69d88dSmrg # a variable. If it is the name of a variable, the int(c) 419af69d88dSmrg # statement will throw an exception, and the except block will 420af69d88dSmrg # take over. 4213464ebd5Sriastradh 422af69d88dSmrg c = element.get( "count" ) 423af69d88dSmrg try: 424af69d88dSmrg count = int(c) 425af69d88dSmrg self.count = count 426af69d88dSmrg self.counter = None 42701e04c3fSmrg except Exception: 428af69d88dSmrg count = 1 429af69d88dSmrg self.count = 0 430af69d88dSmrg self.counter = c 4313464ebd5Sriastradh 4327ec681f3Smrg self.marshal_count = element.get("marshal_count") 433af69d88dSmrg self.count_scale = int(element.get( "count_scale", "1" )) 4343464ebd5Sriastradh 435af69d88dSmrg elements = (count * self.count_scale) 436af69d88dSmrg if elements == 1: 437af69d88dSmrg elements = 0 4383464ebd5Sriastradh 439af69d88dSmrg #if ts == "GLdouble": 440af69d88dSmrg # print '/* stack size -> %s = %u (before)*/' % (self.name, self.type_expr.get_stack_size()) 441af69d88dSmrg # print '/* # elements = %u */' % (elements) 442af69d88dSmrg self.type_expr.set_elements( elements ) 443af69d88dSmrg #if ts == "GLdouble": 444af69d88dSmrg # print '/* stack size -> %s = %u (after) */' % (self.name, self.type_expr.get_stack_size()) 4453464ebd5Sriastradh 446af69d88dSmrg self.is_client_only = is_attr_true( element, 'client_only' ) 447af69d88dSmrg self.is_counter = is_attr_true( element, 'counter' ) 448af69d88dSmrg self.is_output = is_attr_true( element, 'output' ) 4493464ebd5Sriastradh 4503464ebd5Sriastradh 451af69d88dSmrg # Pixel data has special parameters. 4523464ebd5Sriastradh 453af69d88dSmrg self.width = element.get('img_width') 454af69d88dSmrg self.height = element.get('img_height') 455af69d88dSmrg self.depth = element.get('img_depth') 456af69d88dSmrg self.extent = element.get('img_extent') 4573464ebd5Sriastradh 458af69d88dSmrg self.img_xoff = element.get('img_xoff') 459af69d88dSmrg self.img_yoff = element.get('img_yoff') 460af69d88dSmrg self.img_zoff = element.get('img_zoff') 461af69d88dSmrg self.img_woff = element.get('img_woff') 4623464ebd5Sriastradh 463af69d88dSmrg self.img_format = element.get('img_format') 464af69d88dSmrg self.img_type = element.get('img_type') 465af69d88dSmrg self.img_target = element.get('img_target') 4663464ebd5Sriastradh 467af69d88dSmrg self.img_pad_dimensions = is_attr_true( element, 'img_pad_dimensions' ) 468af69d88dSmrg self.img_null_flag = is_attr_true( element, 'img_null_flag' ) 469af69d88dSmrg self.img_send_null = is_attr_true( element, 'img_send_null' ) 4703464ebd5Sriastradh 471af69d88dSmrg self.is_padding = is_attr_true( element, 'padding' ) 472af69d88dSmrg return 4733464ebd5Sriastradh 4743464ebd5Sriastradh 475af69d88dSmrg def compatible(self, other): 476af69d88dSmrg return 1 4773464ebd5Sriastradh 4783464ebd5Sriastradh 479af69d88dSmrg def is_array(self): 480af69d88dSmrg return self.is_pointer() 4813464ebd5Sriastradh 4823464ebd5Sriastradh 483af69d88dSmrg def is_pointer(self): 484af69d88dSmrg return self.type_expr.is_pointer() 4853464ebd5Sriastradh 4863464ebd5Sriastradh 487af69d88dSmrg def is_image(self): 488af69d88dSmrg if self.width: 489af69d88dSmrg return 1 490af69d88dSmrg else: 491af69d88dSmrg return 0 4923464ebd5Sriastradh 4933464ebd5Sriastradh 494af69d88dSmrg def is_variable_length(self): 4957ec681f3Smrg return len(self.count_parameter_list) or self.counter or self.marshal_count 4963464ebd5Sriastradh 4973464ebd5Sriastradh 498af69d88dSmrg def is_64_bit(self): 499af69d88dSmrg count = self.type_expr.get_element_count() 500af69d88dSmrg if count: 501af69d88dSmrg if (self.size() / count) == 8: 502af69d88dSmrg return 1 503af69d88dSmrg else: 504af69d88dSmrg if self.size() == 8: 505af69d88dSmrg return 1 5063464ebd5Sriastradh 507af69d88dSmrg return 0 5083464ebd5Sriastradh 5093464ebd5Sriastradh 510af69d88dSmrg def string(self): 511af69d88dSmrg return self.type_expr.original_string + " " + self.name 5123464ebd5Sriastradh 5133464ebd5Sriastradh 514af69d88dSmrg def type_string(self): 515af69d88dSmrg return self.type_expr.original_string 5163464ebd5Sriastradh 5173464ebd5Sriastradh 518af69d88dSmrg def get_base_type_string(self): 519af69d88dSmrg return self.type_expr.get_base_name() 5203464ebd5Sriastradh 5213464ebd5Sriastradh 522af69d88dSmrg def get_dimensions(self): 523af69d88dSmrg if not self.width: 524af69d88dSmrg return [ 0, "0", "0", "0", "0" ] 5253464ebd5Sriastradh 526af69d88dSmrg dim = 1 527af69d88dSmrg w = self.width 528af69d88dSmrg h = "1" 529af69d88dSmrg d = "1" 530af69d88dSmrg e = "1" 5313464ebd5Sriastradh 532af69d88dSmrg if self.height: 533af69d88dSmrg dim = 2 534af69d88dSmrg h = self.height 5353464ebd5Sriastradh 536af69d88dSmrg if self.depth: 537af69d88dSmrg dim = 3 538af69d88dSmrg d = self.depth 5393464ebd5Sriastradh 540af69d88dSmrg if self.extent: 541af69d88dSmrg dim = 4 542af69d88dSmrg e = self.extent 5433464ebd5Sriastradh 544af69d88dSmrg return [ dim, w, h, d, e ] 5453464ebd5Sriastradh 5463464ebd5Sriastradh 547af69d88dSmrg def get_stack_size(self): 548af69d88dSmrg return self.type_expr.get_stack_size() 5493464ebd5Sriastradh 5503464ebd5Sriastradh 551af69d88dSmrg def size(self): 552af69d88dSmrg if self.is_image(): 553af69d88dSmrg return 0 554af69d88dSmrg else: 555af69d88dSmrg return self.type_expr.get_element_size() 5563464ebd5Sriastradh 5573464ebd5Sriastradh 558af69d88dSmrg def get_element_count(self): 559af69d88dSmrg c = self.type_expr.get_element_count() 560af69d88dSmrg if c == 0: 561af69d88dSmrg return 1 5623464ebd5Sriastradh 563af69d88dSmrg return c 5643464ebd5Sriastradh 5653464ebd5Sriastradh 5667ec681f3Smrg def size_string(self, use_parens = 1, marshal = 0): 5677ec681f3Smrg base_size_str = "" 5687ec681f3Smrg 5697ec681f3Smrg count = self.get_element_count() 5707ec681f3Smrg if count: 5717ec681f3Smrg base_size_str = "%d * " % count 5727ec681f3Smrg 5737ec681f3Smrg base_size_str += "sizeof(%s)" % ( self.get_base_type_string() ) 5747ec681f3Smrg 5757ec681f3Smrg if self.counter or self.count_parameter_list or (self.marshal_count and marshal): 576af69d88dSmrg list = [ "compsize" ] 5773464ebd5Sriastradh 5787ec681f3Smrg if self.marshal_count and marshal: 5797ec681f3Smrg list = [ self.marshal_count ] 5807ec681f3Smrg elif self.counter and self.count_parameter_list: 581af69d88dSmrg list.append( self.counter ) 582af69d88dSmrg elif self.counter: 583af69d88dSmrg list = [ self.counter ] 5843464ebd5Sriastradh 5857ec681f3Smrg if self.size() > 1: 5867ec681f3Smrg list.append( base_size_str ) 5873464ebd5Sriastradh 588af69d88dSmrg if len(list) > 1 and use_parens : 58901e04c3fSmrg return "safe_mul(%s)" % ", ".join(list) 590af69d88dSmrg else: 59101e04c3fSmrg return " * ".join(list) 5923464ebd5Sriastradh 593af69d88dSmrg elif self.is_image(): 594af69d88dSmrg return "compsize" 595af69d88dSmrg else: 5967ec681f3Smrg return base_size_str 5973464ebd5Sriastradh 5983464ebd5Sriastradh 599af69d88dSmrg def format_string(self): 600af69d88dSmrg if self.type_expr.original_string == "GLenum": 601af69d88dSmrg return "0x%x" 602af69d88dSmrg else: 603af69d88dSmrg return self.type_expr.format_string() 604af69d88dSmrg 605af69d88dSmrg 606af69d88dSmrgclass gl_function( gl_item ): 607af69d88dSmrg def __init__(self, element, context): 608af69d88dSmrg self.context = context 609af69d88dSmrg self.name = None 610af69d88dSmrg 611af69d88dSmrg self.entry_points = [] 612af69d88dSmrg self.return_type = "void" 613af69d88dSmrg self.parameters = [] 614af69d88dSmrg self.offset = -1 615af69d88dSmrg self.initialized = 0 616af69d88dSmrg self.images = [] 617af69d88dSmrg self.exec_flavor = 'mesa' 618af69d88dSmrg self.desktop = True 619af69d88dSmrg self.deprecated = None 62001e04c3fSmrg self.has_no_error_variant = False 621af69d88dSmrg 622af69d88dSmrg # self.api_map[api] is a decimal value indicating the earliest 623af69d88dSmrg # version of the given API in which ANY alias for the function 624af69d88dSmrg # exists. The map only lists APIs which contain the function 625af69d88dSmrg # in at least one version. For example, for the ClipPlanex 6269f464c52Smaya # function, self.api_map == { 'es1': 627af69d88dSmrg # Decimal('1.1') }. 628af69d88dSmrg self.api_map = {} 629af69d88dSmrg 63001e04c3fSmrg self.assign_offset = False 631af69d88dSmrg 632af69d88dSmrg self.static_entry_points = [] 633af69d88dSmrg 634af69d88dSmrg # Track the parameter string (for the function prototype) 635af69d88dSmrg # for each entry-point. This is done because some functions 636af69d88dSmrg # change their prototype slightly when promoted from extension 637af69d88dSmrg # to ARB extension to core. glTexImage3DEXT and glTexImage3D 638af69d88dSmrg # are good examples of this. Scripts that need to generate 639af69d88dSmrg # code for these differing aliases need to real prototype 640af69d88dSmrg # for each entry-point. Otherwise, they may generate code 641af69d88dSmrg # that won't compile. 642af69d88dSmrg 643af69d88dSmrg self.entry_point_parameters = {} 644af69d88dSmrg 645af69d88dSmrg self.process_element( element ) 646af69d88dSmrg 647af69d88dSmrg return 648af69d88dSmrg 649af69d88dSmrg 650af69d88dSmrg def process_element(self, element): 651af69d88dSmrg name = element.get( "name" ) 652af69d88dSmrg alias = element.get( "alias" ) 653af69d88dSmrg 6547ec681f3Smrg # marshal isn't allowed with alias 6557ec681f3Smrg assert not alias or not element.get('marshal') 6567ec681f3Smrg assert not alias or not element.get('marshal_count') 6577ec681f3Smrg assert not alias or not element.get('marshal_sync') 6587ec681f3Smrg assert not alias or not element.get('marshal_call_after') 6597ec681f3Smrg 66001e04c3fSmrg if name in static_data.functions: 661af69d88dSmrg self.static_entry_points.append(name) 662af69d88dSmrg 663af69d88dSmrg self.entry_points.append( name ) 664af69d88dSmrg 665af69d88dSmrg for api in ('es1', 'es2'): 666af69d88dSmrg version_str = element.get(api, 'none') 667af69d88dSmrg assert version_str is not None 668af69d88dSmrg if version_str != 'none': 669af69d88dSmrg version_decimal = Decimal(version_str) 670af69d88dSmrg if api not in self.api_map or \ 671af69d88dSmrg version_decimal < self.api_map[api]: 672af69d88dSmrg self.api_map[api] = version_decimal 673af69d88dSmrg 674af69d88dSmrg exec_flavor = element.get('exec') 675af69d88dSmrg if exec_flavor: 676af69d88dSmrg self.exec_flavor = exec_flavor 677af69d88dSmrg 678af69d88dSmrg deprecated = element.get('deprecated', 'none') 679af69d88dSmrg if deprecated != 'none': 680af69d88dSmrg self.deprecated = Decimal(deprecated) 681af69d88dSmrg 682af69d88dSmrg if not is_attr_true(element, 'desktop', 'true'): 683af69d88dSmrg self.desktop = False 684af69d88dSmrg 68501e04c3fSmrg if self.has_no_error_variant or is_attr_true(element, 'no_error'): 68601e04c3fSmrg self.has_no_error_variant = True 68701e04c3fSmrg else: 68801e04c3fSmrg self.has_no_error_variant = False 68901e04c3fSmrg 690af69d88dSmrg if alias: 691af69d88dSmrg true_name = alias 692af69d88dSmrg else: 693af69d88dSmrg true_name = name 694af69d88dSmrg 695af69d88dSmrg # Only try to set the offset when a non-alias entry-point 696af69d88dSmrg # is being processed. 697af69d88dSmrg 6989f464c52Smaya if name in static_data.offsets and static_data.offsets[name] <= static_data.MAX_OFFSETS: 69901e04c3fSmrg self.offset = static_data.offsets[name] 7009f464c52Smaya elif name in static_data.offsets and static_data.offsets[name] > static_data.MAX_OFFSETS: 7019f464c52Smaya self.offset = static_data.offsets[name] 7029f464c52Smaya self.assign_offset = True 70301e04c3fSmrg else: 7049f464c52Smaya if self.exec_flavor != "skip": 7059f464c52Smaya raise RuntimeError("Entry-point %s is missing offset in static_data.py. Add one at the bottom of the list." % (name)) 70601e04c3fSmrg self.assign_offset = self.exec_flavor != "skip" or name in static_data.unused_functions 707af69d88dSmrg 708af69d88dSmrg if not self.name: 709af69d88dSmrg self.name = true_name 710af69d88dSmrg elif self.name != true_name: 711af69d88dSmrg raise RuntimeError("Function true name redefined. Was %s, now %s." % (self.name, true_name)) 712af69d88dSmrg 713af69d88dSmrg 714af69d88dSmrg # There are two possible cases. The first time an entry-point 715af69d88dSmrg # with data is seen, self.initialized will be 0. On that 716af69d88dSmrg # pass, we just fill in the data. The next time an 717af69d88dSmrg # entry-point with data is seen, self.initialized will be 1. 718af69d88dSmrg # On that pass we have to make that the new values match the 719af69d88dSmrg # valuse from the previous entry-point. 720af69d88dSmrg 721af69d88dSmrg parameters = [] 722af69d88dSmrg return_type = "void" 7237ec681f3Smrg for child in element: 724af69d88dSmrg if child.tag == "return": 725af69d88dSmrg return_type = child.get( "type", "void" ) 726af69d88dSmrg elif child.tag == "param": 727af69d88dSmrg param = self.context.factory.create_parameter(child, self.context) 728af69d88dSmrg parameters.append( param ) 7293464ebd5Sriastradh 7303464ebd5Sriastradh 731af69d88dSmrg if self.initialized: 732af69d88dSmrg if self.return_type != return_type: 733af69d88dSmrg raise RuntimeError( "Return type changed in %s. Was %s, now %s." % (name, self.return_type, return_type)) 734af69d88dSmrg 735af69d88dSmrg if len(parameters) != len(self.parameters): 736af69d88dSmrg raise RuntimeError( "Parameter count mismatch in %s. Was %d, now %d." % (name, len(self.parameters), len(parameters))) 7373464ebd5Sriastradh 738af69d88dSmrg for j in range(0, len(parameters)): 739af69d88dSmrg p1 = parameters[j] 740af69d88dSmrg p2 = self.parameters[j] 741af69d88dSmrg if not p1.compatible( p2 ): 742af69d88dSmrg raise RuntimeError( 'Parameter type mismatch in %s. "%s" was "%s", now "%s".' % (name, p2.name, p2.type_expr.original_string, p1.type_expr.original_string)) 743af69d88dSmrg 744af69d88dSmrg 745af69d88dSmrg if true_name == name or not self.initialized: 746af69d88dSmrg self.return_type = return_type 747af69d88dSmrg self.parameters = parameters 748af69d88dSmrg 749af69d88dSmrg for param in self.parameters: 750af69d88dSmrg if param.is_image(): 751af69d88dSmrg self.images.append( param ) 752af69d88dSmrg 7537ec681f3Smrg if list(element): 754af69d88dSmrg self.initialized = 1 755af69d88dSmrg self.entry_point_parameters[name] = parameters 756af69d88dSmrg else: 757af69d88dSmrg self.entry_point_parameters[name] = [] 758af69d88dSmrg 759af69d88dSmrg return 760af69d88dSmrg 761af69d88dSmrg def filter_entry_points(self, entry_point_list): 762af69d88dSmrg """Filter out entry points not in entry_point_list.""" 763af69d88dSmrg if not self.initialized: 764af69d88dSmrg raise RuntimeError('%s is not initialized yet' % self.name) 765af69d88dSmrg 766af69d88dSmrg entry_points = [] 767af69d88dSmrg for ent in self.entry_points: 768af69d88dSmrg if ent not in entry_point_list: 769af69d88dSmrg if ent in self.static_entry_points: 770af69d88dSmrg self.static_entry_points.remove(ent) 771af69d88dSmrg self.entry_point_parameters.pop(ent) 772af69d88dSmrg else: 773af69d88dSmrg entry_points.append(ent) 774af69d88dSmrg 775af69d88dSmrg if not entry_points: 776af69d88dSmrg raise RuntimeError('%s has no entry point after filtering' % self.name) 7773464ebd5Sriastradh 778af69d88dSmrg self.entry_points = entry_points 779af69d88dSmrg if self.name not in entry_points: 780af69d88dSmrg # use the first remaining entry point 781af69d88dSmrg self.name = entry_points[0] 782af69d88dSmrg self.parameters = self.entry_point_parameters[entry_points[0]] 7833464ebd5Sriastradh 784af69d88dSmrg def get_images(self): 785af69d88dSmrg """Return potentially empty list of input images.""" 786af69d88dSmrg return self.images 7873464ebd5Sriastradh 788af69d88dSmrg 789af69d88dSmrg def parameterIterator(self, name = None): 790af69d88dSmrg if name is not None: 79101e04c3fSmrg return iter(self.entry_point_parameters[name]); 792af69d88dSmrg else: 79301e04c3fSmrg return iter(self.parameters); 7943464ebd5Sriastradh 7953464ebd5Sriastradh 796af69d88dSmrg def get_parameter_string(self, entrypoint = None): 797af69d88dSmrg if entrypoint: 798af69d88dSmrg params = self.entry_point_parameters[ entrypoint ] 799af69d88dSmrg else: 800af69d88dSmrg params = self.parameters 8013464ebd5Sriastradh 802af69d88dSmrg return create_parameter_string( params, 1 ) 8033464ebd5Sriastradh 804af69d88dSmrg def get_called_parameter_string(self): 805af69d88dSmrg p_string = "" 806af69d88dSmrg comma = "" 807af69d88dSmrg 808af69d88dSmrg for p in self.parameterIterator(): 809af69d88dSmrg if p.is_padding: 810af69d88dSmrg continue 811af69d88dSmrg p_string = p_string + comma + p.name 812af69d88dSmrg comma = ", " 8133464ebd5Sriastradh 814af69d88dSmrg return p_string 8153464ebd5Sriastradh 8163464ebd5Sriastradh 817af69d88dSmrg def is_abi(self): 818af69d88dSmrg return (self.offset >= 0 and not self.assign_offset) 8193464ebd5Sriastradh 820af69d88dSmrg def is_static_entry_point(self, name): 821af69d88dSmrg return name in self.static_entry_points 8223464ebd5Sriastradh 823af69d88dSmrg def dispatch_name(self): 824af69d88dSmrg if self.name in self.static_entry_points: 825af69d88dSmrg return self.name 826af69d88dSmrg else: 827af69d88dSmrg return "_dispatch_stub_%u" % (self.offset) 8283464ebd5Sriastradh 829af69d88dSmrg def static_name(self, name): 830af69d88dSmrg if name in self.static_entry_points: 831af69d88dSmrg return name 832af69d88dSmrg else: 833af69d88dSmrg return "_dispatch_stub_%u" % (self.offset) 8343464ebd5Sriastradh 835af69d88dSmrgclass gl_item_factory(object): 836af69d88dSmrg """Factory to create objects derived from gl_item.""" 8373464ebd5Sriastradh 838af69d88dSmrg def create_function(self, element, context): 839af69d88dSmrg return gl_function(element, context) 8403464ebd5Sriastradh 841af69d88dSmrg def create_type(self, element, context, category): 842af69d88dSmrg return gl_type(element, context, category) 8433464ebd5Sriastradh 844af69d88dSmrg def create_enum(self, element, context, category): 845af69d88dSmrg return gl_enum(element, context, category) 8463464ebd5Sriastradh 847af69d88dSmrg def create_parameter(self, element, context): 848af69d88dSmrg return gl_parameter(element, context) 8493464ebd5Sriastradh 850af69d88dSmrg def create_api(self): 851af69d88dSmrg return gl_api(self) 8523464ebd5Sriastradh 8533464ebd5Sriastradh 854af69d88dSmrgclass gl_api(object): 855af69d88dSmrg def __init__(self, factory): 85601e04c3fSmrg self.functions_by_name = OrderedDict() 857af69d88dSmrg self.enums_by_name = {} 858af69d88dSmrg self.types_by_name = {} 8593464ebd5Sriastradh 860af69d88dSmrg self.category_dict = {} 861af69d88dSmrg self.categories = [{}, {}, {}, {}] 8623464ebd5Sriastradh 863af69d88dSmrg self.factory = factory 8643464ebd5Sriastradh 865af69d88dSmrg self.next_offset = 0 8663464ebd5Sriastradh 867af69d88dSmrg typeexpr.create_initial_types() 868af69d88dSmrg return 8693464ebd5Sriastradh 870af69d88dSmrg def parse_file(self, file_name): 871af69d88dSmrg doc = ET.parse( file_name ) 872af69d88dSmrg self.process_element(file_name, doc) 8733464ebd5Sriastradh 8743464ebd5Sriastradh 875af69d88dSmrg def process_element(self, file_name, doc): 876af69d88dSmrg element = doc.getroot() 877af69d88dSmrg if element.tag == "OpenGLAPI": 878af69d88dSmrg self.process_OpenGLAPI(file_name, element) 879af69d88dSmrg return 8803464ebd5Sriastradh 8813464ebd5Sriastradh 882af69d88dSmrg def process_OpenGLAPI(self, file_name, element): 8837ec681f3Smrg for child in element: 884af69d88dSmrg if child.tag == "category": 885af69d88dSmrg self.process_category( child ) 886af69d88dSmrg elif child.tag == "OpenGLAPI": 887af69d88dSmrg self.process_OpenGLAPI( file_name, child ) 888af69d88dSmrg elif child.tag == '{http://www.w3.org/2001/XInclude}include': 889af69d88dSmrg href = child.get('href') 890af69d88dSmrg href = os.path.join(os.path.dirname(file_name), href) 891af69d88dSmrg self.parse_file(href) 8923464ebd5Sriastradh 893af69d88dSmrg return 8943464ebd5Sriastradh 8953464ebd5Sriastradh 896af69d88dSmrg def process_category(self, cat): 897af69d88dSmrg cat_name = cat.get( "name" ) 898af69d88dSmrg cat_number = cat.get( "number" ) 8993464ebd5Sriastradh 900af69d88dSmrg [cat_type, key] = classify_category(cat_name, cat_number) 901af69d88dSmrg self.categories[cat_type][key] = [cat_name, cat_number] 9023464ebd5Sriastradh 9037ec681f3Smrg for child in cat: 904af69d88dSmrg if child.tag == "function": 905af69d88dSmrg func_name = real_function_name( child ) 9063464ebd5Sriastradh 907af69d88dSmrg temp_name = child.get( "name" ) 908af69d88dSmrg self.category_dict[ temp_name ] = [cat_name, cat_number] 9093464ebd5Sriastradh 91001e04c3fSmrg if func_name in self.functions_by_name: 911af69d88dSmrg func = self.functions_by_name[ func_name ] 912af69d88dSmrg func.process_element( child ) 913af69d88dSmrg else: 914af69d88dSmrg func = self.factory.create_function( child, self ) 915af69d88dSmrg self.functions_by_name[ func_name ] = func 9163464ebd5Sriastradh 917af69d88dSmrg if func.offset >= self.next_offset: 918af69d88dSmrg self.next_offset = func.offset + 1 9193464ebd5Sriastradh 9203464ebd5Sriastradh 921af69d88dSmrg elif child.tag == "enum": 922af69d88dSmrg enum = self.factory.create_enum( child, self, cat_name ) 923af69d88dSmrg self.enums_by_name[ enum.name ] = enum 924af69d88dSmrg elif child.tag == "type": 925af69d88dSmrg t = self.factory.create_type( child, self, cat_name ) 926af69d88dSmrg self.types_by_name[ "GL" + t.name ] = t 9273464ebd5Sriastradh 928af69d88dSmrg return 9293464ebd5Sriastradh 9303464ebd5Sriastradh 931af69d88dSmrg def functionIterateByCategory(self, cat = None): 932af69d88dSmrg """Iterate over functions by category. 9333464ebd5Sriastradh 934af69d88dSmrg If cat is None, all known functions are iterated in category 935af69d88dSmrg order. See classify_category for details of the ordering. 936af69d88dSmrg Within a category, functions are sorted by name. If cat is 937af69d88dSmrg not None, then only functions in that category are iterated. 938af69d88dSmrg """ 939af69d88dSmrg lists = [{}, {}, {}, {}] 9403464ebd5Sriastradh 941af69d88dSmrg for func in self.functionIterateAll(): 942af69d88dSmrg [cat_name, cat_number] = self.category_dict[func.name] 9433464ebd5Sriastradh 944af69d88dSmrg if (cat == None) or (cat == cat_name): 945af69d88dSmrg [func_cat_type, key] = classify_category(cat_name, cat_number) 9463464ebd5Sriastradh 94701e04c3fSmrg if key not in lists[func_cat_type]: 948af69d88dSmrg lists[func_cat_type][key] = {} 9493464ebd5Sriastradh 950af69d88dSmrg lists[func_cat_type][key][func.name] = func 9513464ebd5Sriastradh 9523464ebd5Sriastradh 953af69d88dSmrg functions = [] 954af69d88dSmrg for func_cat_type in range(0,4): 95501e04c3fSmrg keys = sorted(lists[func_cat_type].keys()) 9563464ebd5Sriastradh 957af69d88dSmrg for key in keys: 95801e04c3fSmrg names = sorted(lists[func_cat_type][key].keys()) 9593464ebd5Sriastradh 960af69d88dSmrg for name in names: 961af69d88dSmrg functions.append(lists[func_cat_type][key][name]) 9623464ebd5Sriastradh 96301e04c3fSmrg return iter(functions) 9643464ebd5Sriastradh 9653464ebd5Sriastradh 966af69d88dSmrg def functionIterateByOffset(self): 967af69d88dSmrg max_offset = -1 96801e04c3fSmrg for func in self.functions_by_name.values(): 969af69d88dSmrg if func.offset > max_offset: 970af69d88dSmrg max_offset = func.offset 9713464ebd5Sriastradh 9723464ebd5Sriastradh 973af69d88dSmrg temp = [None for i in range(0, max_offset + 1)] 97401e04c3fSmrg for func in self.functions_by_name.values(): 975af69d88dSmrg if func.offset != -1: 976af69d88dSmrg temp[ func.offset ] = func 9773464ebd5Sriastradh 9783464ebd5Sriastradh 979af69d88dSmrg list = [] 980af69d88dSmrg for i in range(0, max_offset + 1): 981af69d88dSmrg if temp[i]: 982af69d88dSmrg list.append(temp[i]) 9833464ebd5Sriastradh 98401e04c3fSmrg return iter(list); 9853464ebd5Sriastradh 9863464ebd5Sriastradh 987af69d88dSmrg def functionIterateAll(self): 98801e04c3fSmrg return self.functions_by_name.values() 9893464ebd5Sriastradh 9903464ebd5Sriastradh 991af69d88dSmrg def enumIterateByName(self): 99201e04c3fSmrg keys = sorted(self.enums_by_name.keys()) 9933464ebd5Sriastradh 994af69d88dSmrg list = [] 995af69d88dSmrg for enum in keys: 996af69d88dSmrg list.append( self.enums_by_name[ enum ] ) 9973464ebd5Sriastradh 99801e04c3fSmrg return iter(list) 9993464ebd5Sriastradh 10003464ebd5Sriastradh 1001af69d88dSmrg def categoryIterate(self): 1002af69d88dSmrg """Iterate over categories. 10033464ebd5Sriastradh 1004af69d88dSmrg Iterate over all known categories in the order specified by 1005af69d88dSmrg classify_category. Each iterated value is a tuple of the 1006af69d88dSmrg name and number (which may be None) of the category. 1007af69d88dSmrg """ 10083464ebd5Sriastradh 1009af69d88dSmrg list = [] 1010af69d88dSmrg for cat_type in range(0,4): 101101e04c3fSmrg keys = sorted(self.categories[cat_type].keys()) 10123464ebd5Sriastradh 1013af69d88dSmrg for key in keys: 1014af69d88dSmrg list.append(self.categories[cat_type][key]) 10153464ebd5Sriastradh 101601e04c3fSmrg return iter(list) 10173464ebd5Sriastradh 10183464ebd5Sriastradh 1019af69d88dSmrg def get_category_for_name( self, name ): 102001e04c3fSmrg if name in self.category_dict: 1021af69d88dSmrg return self.category_dict[name] 1022af69d88dSmrg else: 1023af69d88dSmrg return ["<unknown category>", None] 10243464ebd5Sriastradh 10253464ebd5Sriastradh 1026af69d88dSmrg def typeIterate(self): 102701e04c3fSmrg return self.types_by_name.values() 10283464ebd5Sriastradh 10293464ebd5Sriastradh 1030af69d88dSmrg def find_type( self, type_name ): 1031af69d88dSmrg if type_name in self.types_by_name: 1032af69d88dSmrg return self.types_by_name[ type_name ].type_expr 1033af69d88dSmrg else: 103401e04c3fSmrg print("Unable to find base type matching \"%s\"." % (type_name)) 1035af69d88dSmrg return None 1036