gl_XML.py revision 3464ebd5
1#!/usr/bin/env python 2 3# (C) Copyright IBM Corporation 2004, 2005 4# All Rights Reserved. 5# 6# Permission is hereby granted, free of charge, to any person obtaining a 7# copy of this software and associated documentation files (the "Software"), 8# to deal in the Software without restriction, including without limitation 9# on the rights to use, copy, modify, merge, publish, distribute, sub 10# license, and/or sell copies of the Software, and to permit persons to whom 11# the Software is furnished to do so, subject to the following conditions: 12# 13# The above copyright notice and this permission notice (including the next 14# paragraph) shall be included in all copies or substantial portions of the 15# Software. 16# 17# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 20# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23# IN THE SOFTWARE. 24# 25# Authors: 26# Ian Romanick <idr@us.ibm.com> 27 28import libxml2 29import re, sys, string 30import typeexpr 31 32 33def parse_GL_API( file_name, factory = None ): 34 doc = libxml2.readFile( file_name, None, libxml2.XML_PARSE_XINCLUDE + libxml2.XML_PARSE_NOBLANKS + libxml2.XML_PARSE_DTDVALID + libxml2.XML_PARSE_DTDATTR + libxml2.XML_PARSE_DTDLOAD + libxml2.XML_PARSE_NOENT ) 35 ret = doc.xincludeProcess() 36 37 if not factory: 38 factory = gl_item_factory() 39 40 api = factory.create_item( "api", None, None ) 41 api.process_element( doc ) 42 43 # After the XML has been processed, we need to go back and assign 44 # dispatch offsets to the functions that request that their offsets 45 # be assigned by the scripts. Typically this means all functions 46 # that are not part of the ABI. 47 48 for func in api.functionIterateByCategory(): 49 if func.assign_offset: 50 func.offset = api.next_offset; 51 api.next_offset += 1 52 53 doc.freeDoc() 54 55 return api 56 57 58def is_attr_true( element, name ): 59 """Read a name value from an element's attributes. 60 61 The value read from the attribute list must be either 'true' or 62 'false'. If the value is 'false', zero will be returned. If the 63 value is 'true', non-zero will be returned. An exception will be 64 raised for any other value.""" 65 66 value = element.nsProp( name, None ) 67 if value == "true": 68 return 1 69 elif value == "false": 70 return 0 71 else: 72 raise RuntimeError('Invalid value "%s" for boolean "%s".' % (value, name)) 73 74 75class gl_print_base: 76 """Base class of all API pretty-printers. 77 78 In the model-view-controller pattern, this is the view. Any derived 79 class will want to over-ride the printBody, printRealHader, and 80 printRealFooter methods. Some derived classes may want to over-ride 81 printHeader and printFooter, or even Print (though this is unlikely). 82 """ 83 84 def __init__(self): 85 # Name of the script that is generating the output file. 86 # Every derived class should set this to the name of its 87 # source file. 88 89 self.name = "a" 90 91 92 # License on the *generated* source file. This may differ 93 # from the license on the script that is generating the file. 94 # Every derived class should set this to some reasonable 95 # value. 96 # 97 # See license.py for an example of a reasonable value. 98 99 self.license = "The license for this file is unspecified." 100 101 102 # The header_tag is the name of the C preprocessor define 103 # used to prevent multiple inclusion. Typically only 104 # generated C header files need this to be set. Setting it 105 # causes code to be generated automatically in printHeader 106 # and printFooter. 107 108 self.header_tag = None 109 110 111 # List of file-private defines that must be undefined at the 112 # end of the file. This can be used in header files to define 113 # names for use in the file, then undefine them at the end of 114 # the header file. 115 116 self.undef_list = [] 117 return 118 119 120 def Print(self, api): 121 self.printHeader() 122 self.printBody(api) 123 self.printFooter() 124 return 125 126 127 def printHeader(self): 128 """Print the header associated with all files and call the printRealHeader method.""" 129 130 print '/* DO NOT EDIT - This file generated automatically by %s script */' \ 131 % (self.name) 132 print '' 133 print '/*' 134 print ' * ' + self.license.replace('\n', '\n * ') 135 print ' */' 136 print '' 137 if self.header_tag: 138 print '#if !defined( %s )' % (self.header_tag) 139 print '# define %s' % (self.header_tag) 140 print '' 141 self.printRealHeader(); 142 return 143 144 145 def printFooter(self): 146 """Print the header associated with all files and call the printRealFooter method.""" 147 148 self.printRealFooter() 149 150 if self.undef_list: 151 print '' 152 for u in self.undef_list: 153 print "# undef %s" % (u) 154 155 if self.header_tag: 156 print '' 157 print '#endif /* !defined( %s ) */' % (self.header_tag) 158 159 160 def printRealHeader(self): 161 """Print the "real" header for the created file. 162 163 In the base class, this function is empty. All derived 164 classes should over-ride this function.""" 165 return 166 167 168 def printRealFooter(self): 169 """Print the "real" footer for the created file. 170 171 In the base class, this function is empty. All derived 172 classes should over-ride this function.""" 173 return 174 175 176 def printPure(self): 177 """Conditionally define `PURE' function attribute. 178 179 Conditionally defines a preprocessor macro `PURE' that wraps 180 GCC's `pure' function attribute. The conditional code can be 181 easilly adapted to other compilers that support a similar 182 feature. 183 184 The name is also added to the file's undef_list. 185 """ 186 self.undef_list.append("PURE") 187 print """# if defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) 188# define PURE __attribute__((pure)) 189# else 190# define PURE 191# endif""" 192 return 193 194 195 def printFastcall(self): 196 """Conditionally define `FASTCALL' function attribute. 197 198 Conditionally defines a preprocessor macro `FASTCALL' that 199 wraps GCC's `fastcall' function attribute. The conditional 200 code can be easilly adapted to other compilers that support a 201 similar feature. 202 203 The name is also added to the file's undef_list. 204 """ 205 206 self.undef_list.append("FASTCALL") 207 print """# if defined(__i386__) && defined(__GNUC__) && !defined(__CYGWIN__) && !defined(__MINGW32__) 208# define FASTCALL __attribute__((fastcall)) 209# else 210# define FASTCALL 211# endif""" 212 return 213 214 215 def printVisibility(self, S, s): 216 """Conditionally define visibility function attribute. 217 218 Conditionally defines a preprocessor macro name S that wraps 219 GCC's visibility function attribute. The visibility used is 220 the parameter s. The conditional code can be easilly adapted 221 to other compilers that support a similar feature. 222 223 The name is also added to the file's undef_list. 224 """ 225 226 self.undef_list.append(S) 227 print """# if (defined(__GNUC__) && !defined(__CYGWIN__) && !defined(__MINGW32__)) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590) && defined(__ELF__)) 228# define %s __attribute__((visibility("%s"))) 229# else 230# define %s 231# endif""" % (S, s, S) 232 return 233 234 235 def printNoinline(self): 236 """Conditionally define `NOINLINE' function attribute. 237 238 Conditionally defines a preprocessor macro `NOINLINE' that 239 wraps GCC's `noinline' function attribute. The conditional 240 code can be easilly adapted to other compilers that support a 241 similar feature. 242 243 The name is also added to the file's undef_list. 244 """ 245 246 self.undef_list.append("NOINLINE") 247 print """# if defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) 248# define NOINLINE __attribute__((noinline)) 249# else 250# define NOINLINE 251# endif""" 252 return 253 254 255def real_function_name(element): 256 name = element.nsProp( "name", None ) 257 alias = element.nsProp( "alias", None ) 258 259 if alias: 260 return alias 261 else: 262 return name 263 264 265def real_category_name(c): 266 if re.compile("[1-9][0-9]*[.][0-9]+").match(c): 267 return "GL_VERSION_" + c.replace(".", "_") 268 else: 269 return c 270 271 272def classify_category(name, number): 273 """Based on the category name and number, select a numerical class for it. 274 275 Categories are divided into four classes numbered 0 through 3. The 276 classes are: 277 278 0. Core GL versions, sorted by version number. 279 1. ARB extensions, sorted by extension number. 280 2. Non-ARB extensions, sorted by extension number. 281 3. Un-numbered extensions, sorted by extension name. 282 """ 283 284 try: 285 core_version = float(name) 286 except Exception,e: 287 core_version = 0.0 288 289 if core_version > 0.0: 290 cat_type = 0 291 key = name 292 elif name.startswith("GL_ARB_") or name.startswith("GLX_ARB_") or name.startswith("WGL_ARB_"): 293 cat_type = 1 294 key = int(number) 295 else: 296 if number != None: 297 cat_type = 2 298 key = int(number) 299 else: 300 cat_type = 3 301 key = name 302 303 304 return [cat_type, key] 305 306 307def create_parameter_string(parameters, include_names): 308 """Create a parameter string from a list of gl_parameters.""" 309 310 list = [] 311 for p in parameters: 312 if p.is_padding: 313 continue 314 315 if include_names: 316 list.append( p.string() ) 317 else: 318 list.append( p.type_string() ) 319 320 if len(list) == 0: list = ["void"] 321 322 return string.join(list, ", ") 323 324 325class gl_item: 326 def __init__(self, element, context): 327 self.context = context 328 self.name = element.nsProp( "name", None ) 329 self.category = real_category_name( element.parent.nsProp( "name", None ) ) 330 return 331 332 333class gl_type( gl_item ): 334 def __init__(self, element, context): 335 gl_item.__init__(self, element, context) 336 self.size = int( element.nsProp( "size", None ), 0 ) 337 338 te = typeexpr.type_expression( None ) 339 tn = typeexpr.type_node() 340 tn.size = int( element.nsProp( "size", None ), 0 ) 341 tn.integer = not is_attr_true( element, "float" ) 342 tn.unsigned = is_attr_true( element, "unsigned" ) 343 tn.name = "GL" + self.name 344 te.set_base_type_node( tn ) 345 346 self.type_expr = te 347 return 348 349 350 def get_type_expression(self): 351 return self.type_expr 352 353 354class gl_enum( gl_item ): 355 def __init__(self, element, context): 356 gl_item.__init__(self, element, context) 357 self.value = int( element.nsProp( "value", None ), 0 ) 358 359 temp = element.nsProp( "count", None ) 360 if not temp or temp == "?": 361 self.default_count = -1 362 else: 363 try: 364 c = int(temp) 365 except Exception,e: 366 raise RuntimeError('Invalid count value "%s" for enum "%s" in function "%s" when an integer was expected.' % (temp, self.name, n)) 367 368 self.default_count = c 369 370 return 371 372 373 def priority(self): 374 """Calculate a 'priority' for this enum name. 375 376 When an enum is looked up by number, there may be many 377 possible names, but only one is the 'prefered' name. The 378 priority is used to select which name is the 'best'. 379 380 Highest precedence is given to core GL name. ARB extension 381 names have the next highest, followed by EXT extension names. 382 Vendor extension names are the lowest. 383 """ 384 385 if self.name.endswith( "_BIT" ): 386 bias = 1 387 else: 388 bias = 0 389 390 if self.category.startswith( "GL_VERSION_" ): 391 priority = 0 392 elif self.category.startswith( "GL_ARB_" ): 393 priority = 2 394 elif self.category.startswith( "GL_EXT_" ): 395 priority = 4 396 else: 397 priority = 6 398 399 return priority + bias 400 401 402 403class gl_parameter: 404 def __init__(self, element, context): 405 self.name = element.nsProp( "name", None ) 406 407 ts = element.nsProp( "type", None ) 408 self.type_expr = typeexpr.type_expression( ts, context ) 409 410 temp = element.nsProp( "variable_param", None ) 411 if temp: 412 self.count_parameter_list = temp.split( ' ' ) 413 else: 414 self.count_parameter_list = [] 415 416 # The count tag can be either a numeric string or the name of 417 # a variable. If it is the name of a variable, the int(c) 418 # statement will throw an exception, and the except block will 419 # take over. 420 421 c = element.nsProp( "count", None ) 422 try: 423 count = int(c) 424 self.count = count 425 self.counter = None 426 except Exception,e: 427 count = 1 428 self.count = 0 429 self.counter = c 430 431 self.count_scale = int(element.nsProp( "count_scale", None )) 432 433 elements = (count * self.count_scale) 434 if elements == 1: 435 elements = 0 436 437 #if ts == "GLdouble": 438 # print '/* stack size -> %s = %u (before)*/' % (self.name, self.type_expr.get_stack_size()) 439 # print '/* # elements = %u */' % (elements) 440 self.type_expr.set_elements( elements ) 441 #if ts == "GLdouble": 442 # print '/* stack size -> %s = %u (after) */' % (self.name, self.type_expr.get_stack_size()) 443 444 self.is_client_only = is_attr_true( element, 'client_only' ) 445 self.is_counter = is_attr_true( element, 'counter' ) 446 self.is_output = is_attr_true( element, 'output' ) 447 448 449 # Pixel data has special parameters. 450 451 self.width = element.nsProp('img_width', None) 452 self.height = element.nsProp('img_height', None) 453 self.depth = element.nsProp('img_depth', None) 454 self.extent = element.nsProp('img_extent', None) 455 456 self.img_xoff = element.nsProp('img_xoff', None) 457 self.img_yoff = element.nsProp('img_yoff', None) 458 self.img_zoff = element.nsProp('img_zoff', None) 459 self.img_woff = element.nsProp('img_woff', None) 460 461 self.img_format = element.nsProp('img_format', None) 462 self.img_type = element.nsProp('img_type', None) 463 self.img_target = element.nsProp('img_target', None) 464 465 self.img_pad_dimensions = is_attr_true( element, 'img_pad_dimensions' ) 466 self.img_null_flag = is_attr_true( element, 'img_null_flag' ) 467 self.img_send_null = is_attr_true( element, 'img_send_null' ) 468 469 self.is_padding = is_attr_true( element, 'padding' ) 470 return 471 472 473 def compatible(self, other): 474 return 1 475 476 477 def is_array(self): 478 return self.is_pointer() 479 480 481 def is_pointer(self): 482 return self.type_expr.is_pointer() 483 484 485 def is_image(self): 486 if self.width: 487 return 1 488 else: 489 return 0 490 491 492 def is_variable_length(self): 493 return len(self.count_parameter_list) or self.counter 494 495 496 def is_64_bit(self): 497 count = self.type_expr.get_element_count() 498 if count: 499 if (self.size() / count) == 8: 500 return 1 501 else: 502 if self.size() == 8: 503 return 1 504 505 return 0 506 507 508 def string(self): 509 return self.type_expr.original_string + " " + self.name 510 511 512 def type_string(self): 513 return self.type_expr.original_string 514 515 516 def get_base_type_string(self): 517 return self.type_expr.get_base_name() 518 519 520 def get_dimensions(self): 521 if not self.width: 522 return [ 0, "0", "0", "0", "0" ] 523 524 dim = 1 525 w = self.width 526 h = "1" 527 d = "1" 528 e = "1" 529 530 if self.height: 531 dim = 2 532 h = self.height 533 534 if self.depth: 535 dim = 3 536 d = self.depth 537 538 if self.extent: 539 dim = 4 540 e = self.extent 541 542 return [ dim, w, h, d, e ] 543 544 545 def get_stack_size(self): 546 return self.type_expr.get_stack_size() 547 548 549 def size(self): 550 if self.is_image(): 551 return 0 552 else: 553 return self.type_expr.get_element_size() 554 555 556 def get_element_count(self): 557 c = self.type_expr.get_element_count() 558 if c == 0: 559 return 1 560 561 return c 562 563 564 def size_string(self, use_parens = 1): 565 s = self.size() 566 if self.counter or self.count_parameter_list: 567 list = [ "compsize" ] 568 569 if self.counter and self.count_parameter_list: 570 list.append( self.counter ) 571 elif self.counter: 572 list = [ self.counter ] 573 574 if s > 1: 575 list.append( str(s) ) 576 577 if len(list) > 1 and use_parens : 578 return "(%s)" % (string.join(list, " * ")) 579 else: 580 return string.join(list, " * ") 581 582 elif self.is_image(): 583 return "compsize" 584 else: 585 return str(s) 586 587 588 def format_string(self): 589 if self.type_expr.original_string == "GLenum": 590 return "0x%x" 591 else: 592 return self.type_expr.format_string() 593 594 595 596class gl_function( gl_item ): 597 def __init__(self, element, context): 598 self.context = context 599 self.name = None 600 601 self.entry_points = [] 602 self.return_type = "void" 603 self.parameters = [] 604 self.offset = -1 605 self.initialized = 0 606 self.images = [] 607 608 self.assign_offset = 0 609 610 self.static_entry_points = [] 611 612 # Track the parameter string (for the function prototype) 613 # for each entry-point. This is done because some functions 614 # change their prototype slightly when promoted from extension 615 # to ARB extension to core. glTexImage3DEXT and glTexImage3D 616 # are good examples of this. Scripts that need to generate 617 # code for these differing aliases need to real prototype 618 # for each entry-point. Otherwise, they may generate code 619 # that won't compile. 620 621 self.parameter_strings = {} 622 623 self.process_element( element ) 624 625 return 626 627 628 def process_element(self, element): 629 name = element.nsProp( "name", None ) 630 alias = element.nsProp( "alias", None ) 631 632 if is_attr_true(element, "static_dispatch"): 633 self.static_entry_points.append(name) 634 635 self.entry_points.append( name ) 636 if alias: 637 true_name = alias 638 else: 639 true_name = name 640 641 # Only try to set the offset when a non-alias 642 # entry-point is being processes. 643 644 offset = element.nsProp( "offset", None ) 645 if offset: 646 try: 647 o = int( offset ) 648 self.offset = o 649 except Exception, e: 650 self.offset = -1 651 if offset == "assign": 652 self.assign_offset = 1 653 654 655 if not self.name: 656 self.name = true_name 657 elif self.name != true_name: 658 raise RuntimeError("Function true name redefined. Was %s, now %s." % (self.name, true_name)) 659 660 661 # There are two possible cases. The first time an entry-point 662 # with data is seen, self.initialized will be 0. On that 663 # pass, we just fill in the data. The next time an 664 # entry-point with data is seen, self.initialized will be 1. 665 # On that pass we have to make that the new values match the 666 # valuse from the previous entry-point. 667 668 parameters = [] 669 return_type = "void" 670 child = element.children 671 while child: 672 if child.type == "element": 673 if child.name == "return": 674 return_type = child.nsProp( "type", None ) 675 elif child.name == "param": 676 param = self.context.factory.create_item( "parameter", child, self.context) 677 parameters.append( param ) 678 679 child = child.next 680 681 682 if self.initialized: 683 if self.return_type != return_type: 684 raise RuntimeError( "Return type changed in %s. Was %s, now %s." % (name, self.return_type, return_type)) 685 686 if len(parameters) != len(self.parameters): 687 raise RuntimeError( "Parameter count mismatch in %s. Was %d, now %d." % (name, len(self.parameters), len(parameters))) 688 689 for j in range(0, len(parameters)): 690 p1 = parameters[j] 691 p2 = self.parameters[j] 692 if not p1.compatible( p2 ): 693 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)) 694 695 696 if true_name == name or not self.initialized: 697 self.return_type = return_type 698 self.parameters = parameters 699 700 for param in self.parameters: 701 if param.is_image(): 702 self.images.append( param ) 703 704 if element.children: 705 self.initialized = 1 706 self.parameter_strings[name] = create_parameter_string(parameters, 1) 707 else: 708 self.parameter_strings[name] = None 709 710 return 711 712 713 def get_images(self): 714 """Return potentially empty list of input images.""" 715 return self.images 716 717 718 def parameterIterator(self): 719 return self.parameters.__iter__(); 720 721 722 def get_parameter_string(self, entrypoint = None): 723 if entrypoint: 724 s = self.parameter_strings[ entrypoint ] 725 if s: 726 return s 727 728 return create_parameter_string( self.parameters, 1 ) 729 730 def get_called_parameter_string(self): 731 p_string = "" 732 comma = "" 733 734 for p in self.parameterIterator(): 735 p_string = p_string + comma + p.name 736 comma = ", " 737 738 return p_string 739 740 741 def is_abi(self): 742 return (self.offset >= 0 and not self.assign_offset) 743 744 def is_static_entry_point(self, name): 745 return name in self.static_entry_points 746 747 def dispatch_name(self): 748 if self.name in self.static_entry_points: 749 return self.name 750 else: 751 return "_dispatch_stub_%u" % (self.offset) 752 753 def static_name(self, name): 754 if name in self.static_entry_points: 755 return name 756 else: 757 return "_dispatch_stub_%u" % (self.offset) 758 759 760class gl_item_factory: 761 """Factory to create objects derived from gl_item.""" 762 763 def create_item(self, item_name, element, context): 764 if item_name == "function": 765 return gl_function(element, context) 766 if item_name == "type": 767 return gl_type(element, context) 768 elif item_name == "enum": 769 return gl_enum(element, context) 770 elif item_name == "parameter": 771 return gl_parameter(element, context) 772 elif item_name == "api": 773 return gl_api(self) 774 else: 775 return None 776 777 778class gl_api: 779 def __init__(self, factory): 780 self.functions_by_name = {} 781 self.enums_by_name = {} 782 self.types_by_name = {} 783 784 self.category_dict = {} 785 self.categories = [{}, {}, {}, {}] 786 787 self.factory = factory 788 789 self.next_offset = 0 790 791 typeexpr.create_initial_types() 792 return 793 794 795 def process_element(self, doc): 796 element = doc.children 797 while element.type != "element" or element.name != "OpenGLAPI": 798 element = element.next 799 800 if element: 801 self.process_OpenGLAPI(element) 802 return 803 804 805 def process_OpenGLAPI(self, element): 806 child = element.children 807 while child: 808 if child.type == "element": 809 if child.name == "category": 810 self.process_category( child ) 811 elif child.name == "OpenGLAPI": 812 self.process_OpenGLAPI( child ) 813 814 child = child.next 815 816 return 817 818 819 def process_category(self, cat): 820 cat_name = cat.nsProp( "name", None ) 821 cat_number = cat.nsProp( "number", None ) 822 823 [cat_type, key] = classify_category(cat_name, cat_number) 824 self.categories[cat_type][key] = [cat_name, cat_number] 825 826 child = cat.children 827 while child: 828 if child.type == "element": 829 if child.name == "function": 830 func_name = real_function_name( child ) 831 832 temp_name = child.nsProp( "name", None ) 833 self.category_dict[ temp_name ] = [cat_name, cat_number] 834 835 if self.functions_by_name.has_key( func_name ): 836 func = self.functions_by_name[ func_name ] 837 func.process_element( child ) 838 else: 839 func = self.factory.create_item( "function", child, self ) 840 self.functions_by_name[ func_name ] = func 841 842 if func.offset >= self.next_offset: 843 self.next_offset = func.offset + 1 844 845 846 elif child.name == "enum": 847 enum = self.factory.create_item( "enum", child, self ) 848 self.enums_by_name[ enum.name ] = enum 849 elif child.name == "type": 850 t = self.factory.create_item( "type", child, self ) 851 self.types_by_name[ "GL" + t.name ] = t 852 853 854 child = child.next 855 856 return 857 858 859 def functionIterateByCategory(self, cat = None): 860 """Iterate over functions by category. 861 862 If cat is None, all known functions are iterated in category 863 order. See classify_category for details of the ordering. 864 Within a category, functions are sorted by name. If cat is 865 not None, then only functions in that category are iterated. 866 """ 867 lists = [{}, {}, {}, {}] 868 869 for func in self.functionIterateAll(): 870 [cat_name, cat_number] = self.category_dict[func.name] 871 872 if (cat == None) or (cat == cat_name): 873 [func_cat_type, key] = classify_category(cat_name, cat_number) 874 875 if not lists[func_cat_type].has_key(key): 876 lists[func_cat_type][key] = {} 877 878 lists[func_cat_type][key][func.name] = func 879 880 881 functions = [] 882 for func_cat_type in range(0,4): 883 keys = lists[func_cat_type].keys() 884 keys.sort() 885 886 for key in keys: 887 names = lists[func_cat_type][key].keys() 888 names.sort() 889 890 for name in names: 891 functions.append(lists[func_cat_type][key][name]) 892 893 return functions.__iter__() 894 895 896 def functionIterateByOffset(self): 897 max_offset = -1 898 for func in self.functions_by_name.itervalues(): 899 if func.offset > max_offset: 900 max_offset = func.offset 901 902 903 temp = [None for i in range(0, max_offset + 1)] 904 for func in self.functions_by_name.itervalues(): 905 if func.offset != -1: 906 temp[ func.offset ] = func 907 908 909 list = [] 910 for i in range(0, max_offset + 1): 911 if temp[i]: 912 list.append(temp[i]) 913 914 return list.__iter__(); 915 916 917 def functionIterateAll(self): 918 return self.functions_by_name.itervalues() 919 920 921 def enumIterateByName(self): 922 keys = self.enums_by_name.keys() 923 keys.sort() 924 925 list = [] 926 for enum in keys: 927 list.append( self.enums_by_name[ enum ] ) 928 929 return list.__iter__() 930 931 932 def categoryIterate(self): 933 """Iterate over categories. 934 935 Iterate over all known categories in the order specified by 936 classify_category. Each iterated value is a tuple of the 937 name and number (which may be None) of the category. 938 """ 939 940 list = [] 941 for cat_type in range(0,4): 942 keys = self.categories[cat_type].keys() 943 keys.sort() 944 945 for key in keys: 946 list.append(self.categories[cat_type][key]) 947 948 return list.__iter__() 949 950 951 def get_category_for_name( self, name ): 952 if self.category_dict.has_key(name): 953 return self.category_dict[name] 954 else: 955 return ["<unknown category>", None] 956 957 958 def typeIterate(self): 959 return self.types_by_name.itervalues() 960 961 962 def find_type( self, type_name ): 963 if type_name in self.types_by_name: 964 return self.types_by_name[ type_name ].type_expr 965 else: 966 print "Unable to find base type matching \"%s\"." % (type_name) 967 return None 968