47f8dd5b96214b757855fc5af9557b82aac911b6
3 # (C) Copyright IBM Corporation 2004, 2005
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:
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
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
26 # Ian Romanick <idr@us.ibm.com>
28 from decimal
import Decimal
30 import re
, sys
, string
34 def parse_GL_API( file_name
, factory
= None ):
35 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
)
36 ret
= doc
.xincludeProcess()
39 factory
= gl_item_factory()
41 api
= factory
.create_item( "api", None, None )
42 api
.process_element( doc
)
44 # After the XML has been processed, we need to go back and assign
45 # dispatch offsets to the functions that request that their offsets
46 # be assigned by the scripts. Typically this means all functions
47 # that are not part of the ABI.
49 for func
in api
.functionIterateByCategory():
50 if func
.assign_offset
:
51 func
.offset
= api
.next_offset
;
59 def is_attr_true( element
, name
):
60 """Read a name value from an element's attributes.
62 The value read from the attribute list must be either 'true' or
63 'false'. If the value is 'false', zero will be returned. If the
64 value is 'true', non-zero will be returned. An exception will be
65 raised for any other value."""
67 value
= element
.nsProp( name
, None )
70 elif value
== "false":
73 raise RuntimeError('Invalid value "%s" for boolean "%s".' % (value
, name
))
76 class gl_print_base(object):
77 """Base class of all API pretty-printers.
79 In the model-view-controller pattern, this is the view. Any derived
80 class will want to over-ride the printBody, printRealHader, and
81 printRealFooter methods. Some derived classes may want to over-ride
82 printHeader and printFooter, or even Print (though this is unlikely).
86 # Name of the script that is generating the output file.
87 # Every derived class should set this to the name of its
93 # License on the *generated* source file. This may differ
94 # from the license on the script that is generating the file.
95 # Every derived class should set this to some reasonable
98 # See license.py for an example of a reasonable value.
100 self
.license
= "The license for this file is unspecified."
103 # The header_tag is the name of the C preprocessor define
104 # used to prevent multiple inclusion. Typically only
105 # generated C header files need this to be set. Setting it
106 # causes code to be generated automatically in printHeader
109 self
.header_tag
= None
112 # List of file-private defines that must be undefined at the
113 # end of the file. This can be used in header files to define
114 # names for use in the file, then undefine them at the end of
121 def Print(self
, api
):
128 def printHeader(self
):
129 """Print the header associated with all files and call the printRealHeader method."""
131 print '/* DO NOT EDIT - This file generated automatically by %s script */' \
135 print ' * ' + self
.license
.replace('\n', '\n * ')
139 print '#if !defined( %s )' % (self
.header_tag
)
140 print '# define %s' % (self
.header_tag
)
142 self
.printRealHeader();
146 def printFooter(self
):
147 """Print the header associated with all files and call the printRealFooter method."""
149 self
.printRealFooter()
153 for u
in self
.undef_list
:
154 print "# undef %s" % (u
)
158 print '#endif /* !defined( %s ) */' % (self
.header_tag
)
161 def printRealHeader(self
):
162 """Print the "real" header for the created file.
164 In the base class, this function is empty. All derived
165 classes should over-ride this function."""
169 def printRealFooter(self
):
170 """Print the "real" footer for the created file.
172 In the base class, this function is empty. All derived
173 classes should over-ride this function."""
178 """Conditionally define `PURE' function attribute.
180 Conditionally defines a preprocessor macro `PURE' that wraps
181 GCC's `pure' function attribute. The conditional code can be
182 easilly adapted to other compilers that support a similar
185 The name is also added to the file's undef_list.
187 self
.undef_list
.append("PURE")
188 print """# if defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
189 # define PURE __attribute__((pure))
196 def printFastcall(self
):
197 """Conditionally define `FASTCALL' function attribute.
199 Conditionally defines a preprocessor macro `FASTCALL' that
200 wraps GCC's `fastcall' function attribute. The conditional
201 code can be easilly adapted to other compilers that support a
204 The name is also added to the file's undef_list.
207 self
.undef_list
.append("FASTCALL")
208 print """# if defined(__i386__) && defined(__GNUC__) && !defined(__CYGWIN__) && !defined(__MINGW32__)
209 # define FASTCALL __attribute__((fastcall))
216 def printVisibility(self
, S
, s
):
217 """Conditionally define visibility function attribute.
219 Conditionally defines a preprocessor macro name S that wraps
220 GCC's visibility function attribute. The visibility used is
221 the parameter s. The conditional code can be easilly adapted
222 to other compilers that support a similar feature.
224 The name is also added to the file's undef_list.
227 self
.undef_list
.append(S
)
228 print """# if (defined(__GNUC__) && !defined(__CYGWIN__) && !defined(__MINGW32__)) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590) && defined(__ELF__))
229 # define %s __attribute__((visibility("%s")))
232 # endif""" % (S
, s
, S
)
236 def printNoinline(self
):
237 """Conditionally define `NOINLINE' function attribute.
239 Conditionally defines a preprocessor macro `NOINLINE' that
240 wraps GCC's `noinline' function attribute. The conditional
241 code can be easilly adapted to other compilers that support a
244 The name is also added to the file's undef_list.
247 self
.undef_list
.append("NOINLINE")
248 print """# if defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
249 # define NOINLINE __attribute__((noinline))
256 def real_function_name(element
):
257 name
= element
.nsProp( "name", None )
258 alias
= element
.nsProp( "alias", None )
266 def real_category_name(c
):
267 if re
.compile("[1-9][0-9]*[.][0-9]+").match(c
):
268 return "GL_VERSION_" + c
.replace(".", "_")
273 def classify_category(name
, number
):
274 """Based on the category name and number, select a numerical class for it.
276 Categories are divided into four classes numbered 0 through 3. The
279 0. Core GL versions, sorted by version number.
280 1. ARB extensions, sorted by extension number.
281 2. Non-ARB extensions, sorted by extension number.
282 3. Un-numbered extensions, sorted by extension name.
286 core_version
= float(name
)
290 if core_version
> 0.0:
293 elif name
.startswith("GL_ARB_") or name
.startswith("GLX_ARB_") or name
.startswith("WGL_ARB_"):
305 return [cat_type
, key
]
308 def create_parameter_string(parameters
, include_names
):
309 """Create a parameter string from a list of gl_parameters."""
317 list.append( p
.string() )
319 list.append( p
.type_string() )
321 if len(list) == 0: list = ["void"]
323 return string
.join(list, ", ")
326 class gl_item(object):
327 def __init__(self
, element
, context
):
328 self
.context
= context
329 self
.name
= element
.nsProp( "name", None )
330 self
.category
= real_category_name( element
.parent
.nsProp( "name", None ) )
334 class gl_type( gl_item
):
335 def __init__(self
, element
, context
):
336 gl_item
.__init
__(self
, element
, context
)
337 self
.size
= int( element
.nsProp( "size", None ), 0 )
339 te
= typeexpr
.type_expression( None )
340 tn
= typeexpr
.type_node()
341 tn
.size
= int( element
.nsProp( "size", None ), 0 )
342 tn
.integer
= not is_attr_true( element
, "float" )
343 tn
.unsigned
= is_attr_true( element
, "unsigned" )
344 tn
.pointer
= is_attr_true( element
, "pointer" )
345 tn
.name
= "GL" + self
.name
346 te
.set_base_type_node( tn
)
352 def get_type_expression(self
):
353 return self
.type_expr
356 class gl_enum( gl_item
):
357 def __init__(self
, element
, context
):
358 gl_item
.__init
__(self
, element
, context
)
359 self
.value
= int( element
.nsProp( "value", None ), 0 )
361 temp
= element
.nsProp( "count", None )
362 if not temp
or temp
== "?":
363 self
.default_count
= -1
368 raise RuntimeError('Invalid count value "%s" for enum "%s" in function "%s" when an integer was expected.' % (temp
, self
.name
, n
))
370 self
.default_count
= c
376 """Calculate a 'priority' for this enum name.
378 When an enum is looked up by number, there may be many
379 possible names, but only one is the 'prefered' name. The
380 priority is used to select which name is the 'best'.
382 Highest precedence is given to core GL name. ARB extension
383 names have the next highest, followed by EXT extension names.
384 Vendor extension names are the lowest.
387 if self
.name
.endswith( "_BIT" ):
392 if self
.category
.startswith( "GL_VERSION_" ):
394 elif self
.category
.startswith( "GL_ARB_" ):
396 elif self
.category
.startswith( "GL_EXT_" ):
401 return priority
+ bias
405 class gl_parameter(object):
406 def __init__(self
, element
, context
):
407 self
.name
= element
.nsProp( "name", None )
409 ts
= element
.nsProp( "type", None )
410 self
.type_expr
= typeexpr
.type_expression( ts
, context
)
412 temp
= element
.nsProp( "variable_param", None )
414 self
.count_parameter_list
= temp
.split( ' ' )
416 self
.count_parameter_list
= []
418 # The count tag can be either a numeric string or the name of
419 # a variable. If it is the name of a variable, the int(c)
420 # statement will throw an exception, and the except block will
423 c
= element
.nsProp( "count", None )
433 self
.count_scale
= int(element
.nsProp( "count_scale", None ))
435 elements
= (count
* self
.count_scale
)
439 #if ts == "GLdouble":
440 # print '/* stack size -> %s = %u (before)*/' % (self.name, self.type_expr.get_stack_size())
441 # print '/* # elements = %u */' % (elements)
442 self
.type_expr
.set_elements( elements
)
443 #if ts == "GLdouble":
444 # print '/* stack size -> %s = %u (after) */' % (self.name, self.type_expr.get_stack_size())
446 self
.is_client_only
= is_attr_true( element
, 'client_only' )
447 self
.is_counter
= is_attr_true( element
, 'counter' )
448 self
.is_output
= is_attr_true( element
, 'output' )
451 # Pixel data has special parameters.
453 self
.width
= element
.nsProp('img_width', None)
454 self
.height
= element
.nsProp('img_height', None)
455 self
.depth
= element
.nsProp('img_depth', None)
456 self
.extent
= element
.nsProp('img_extent', None)
458 self
.img_xoff
= element
.nsProp('img_xoff', None)
459 self
.img_yoff
= element
.nsProp('img_yoff', None)
460 self
.img_zoff
= element
.nsProp('img_zoff', None)
461 self
.img_woff
= element
.nsProp('img_woff', None)
463 self
.img_format
= element
.nsProp('img_format', None)
464 self
.img_type
= element
.nsProp('img_type', None)
465 self
.img_target
= element
.nsProp('img_target', None)
467 self
.img_pad_dimensions
= is_attr_true( element
, 'img_pad_dimensions' )
468 self
.img_null_flag
= is_attr_true( element
, 'img_null_flag' )
469 self
.img_send_null
= is_attr_true( element
, 'img_send_null' )
471 self
.is_padding
= is_attr_true( element
, 'padding' )
475 def compatible(self
, other
):
480 return self
.is_pointer()
483 def is_pointer(self
):
484 return self
.type_expr
.is_pointer()
494 def is_variable_length(self
):
495 return len(self
.count_parameter_list
) or self
.counter
499 count
= self
.type_expr
.get_element_count()
501 if (self
.size() / count
) == 8:
511 return self
.type_expr
.original_string
+ " " + self
.name
514 def type_string(self
):
515 return self
.type_expr
.original_string
518 def get_base_type_string(self
):
519 return self
.type_expr
.get_base_name()
522 def get_dimensions(self
):
524 return [ 0, "0", "0", "0", "0" ]
544 return [ dim
, w
, h
, d
, e
]
547 def get_stack_size(self
):
548 return self
.type_expr
.get_stack_size()
555 return self
.type_expr
.get_element_size()
558 def get_element_count(self
):
559 c
= self
.type_expr
.get_element_count()
566 def size_string(self
, use_parens
= 1):
568 if self
.counter
or self
.count_parameter_list
:
569 list = [ "compsize" ]
571 if self
.counter
and self
.count_parameter_list
:
572 list.append( self
.counter
)
574 list = [ self
.counter
]
577 list.append( str(s
) )
579 if len(list) > 1 and use_parens
:
580 return "(%s)" % (string
.join(list, " * "))
582 return string
.join(list, " * ")
584 elif self
.is_image():
590 def format_string(self
):
591 if self
.type_expr
.original_string
== "GLenum":
594 return self
.type_expr
.format_string()
597 # Regular expression used to parse "mesa_name" attributes. A
598 # mesa_name attribute describes how to adjust a GL function name
599 # suffix to obtain the name of the function in Mesa that implements
600 # the functionality. The attribute string consists of a part preceded
601 # by a "-", indicating the suffix to remove, and a part preceded by a
602 # "+" indicating the suffix to add. Either part is optional.
606 # <function name="EnableIndexedEXT" mesa_name="-EXT">...</function>
607 # <function name="IsProgramNV" mesa_name="-NV+ARB">...</function>
609 # means that EnableIndexedEXT is implemented by a Mesa function called
610 # _mesa_EnableIndexed, and IsProgramNV is implemented by a Mesa function
611 # called _mesa_IsProgramARB.
613 # Note: the prefix "_mesa_" is handled separately, by the "exec"
615 name_modification_regexp
= re
.compile(
616 r
'^(-(?P<minus>[a-zA-Z0-9_]+))?(\+(?P<plus>[a-zA-Z0-9_]+))?$')
619 # Interpret a "mesa_name" attribute (see above) to determine the
620 # appropriate suffix for the Mesa function implementing a piece of GL
621 # functionality, and return the properly suffixed name.
622 def interpret_name_modification(name
, mod
):
623 m
= name_modification_regexp
.match(mod
)
625 raise Exception('Unintelligible mesa_name property: {0!r}'.format(mod
))
628 if not new_name
.endswith(m
.group('minus')):
630 'Cannot subtract suffix {0!r} from function {1}'.format(
631 m
.group('minus'), name
))
632 new_name
= new_name
[:-len(m
.group('minus'))]
634 new_name
+= m
.group('plus')
638 class gl_function( gl_item
):
639 def __init__(self
, element
, context
):
640 self
.context
= context
643 self
.entry_points
= []
644 self
.return_type
= "void"
649 self
.exec_flavor
= 'mesa'
651 self
.deprecated
= None
652 self
.mesa_name
= None
654 # self.entry_point_api_map[name][api] is a decimal value
655 # indicating the earliest version of the given API in which
656 # each entry point exists. Every entry point is included in
657 # the first level of the map; the second level of the map only
658 # lists APIs which contain the entry point in at least one
659 # version. For example,
660 # self.entry_point_api_map['ClipPlanex'] == { 'es1':
662 self
.entry_point_api_map
= {}
664 # self.api_map[api] is a decimal value indicating the earliest
665 # version of the given API in which ANY alias for the function
666 # exists. The map only lists APIs which contain the function
667 # in at least one version. For example, for the ClipPlanex
668 # function, self.entry_point_api_map == { 'es1':
672 self
.assign_offset
= 0
674 self
.static_entry_points
= []
676 # Track the parameter string (for the function prototype)
677 # for each entry-point. This is done because some functions
678 # change their prototype slightly when promoted from extension
679 # to ARB extension to core. glTexImage3DEXT and glTexImage3D
680 # are good examples of this. Scripts that need to generate
681 # code for these differing aliases need to real prototype
682 # for each entry-point. Otherwise, they may generate code
683 # that won't compile.
685 self
.entry_point_parameters
= {}
687 self
.process_element( element
)
692 def process_element(self
, element
):
693 name
= element
.nsProp( "name", None )
694 alias
= element
.nsProp( "alias", None )
696 if is_attr_true(element
, "static_dispatch"):
697 self
.static_entry_points
.append(name
)
699 self
.entry_points
.append( name
)
701 self
.entry_point_api_map
[name
] = {}
702 for api
in ('es1', 'es2'):
703 version_str
= element
.nsProp(api
, None)
704 assert version_str
is not None
705 if version_str
!= 'none':
706 version_decimal
= Decimal(version_str
)
707 self
.entry_point_api_map
[name
][api
] = version_decimal
708 if api
not in self
.api_map
or \
709 version_decimal
< self
.api_map
[api
]:
710 self
.api_map
[api
] = version_decimal
712 exec_flavor
= element
.nsProp('exec', None)
714 self
.exec_flavor
= exec_flavor
716 deprecated
= element
.nsProp('deprecated', None)
717 if deprecated
!= 'none':
718 self
.deprecated
= Decimal(deprecated
)
720 if not is_attr_true(element
, 'desktop'):
728 # Only try to set the offset and mesa_name when a
729 # non-alias entry-point is being processed.
731 offset
= element
.nsProp( "offset", None )
738 if offset
== "assign":
739 self
.assign_offset
= 1
741 mesa_name
= element
.nsProp('mesa_name', None)
742 if mesa_name
is None:
743 self
.mesa_name
= name
745 self
.mesa_name
= interpret_name_modification(name
, mesa_name
)
749 self
.name
= true_name
750 elif self
.name
!= true_name
:
751 raise RuntimeError("Function true name redefined. Was %s, now %s." % (self
.name
, true_name
))
754 # There are two possible cases. The first time an entry-point
755 # with data is seen, self.initialized will be 0. On that
756 # pass, we just fill in the data. The next time an
757 # entry-point with data is seen, self.initialized will be 1.
758 # On that pass we have to make that the new values match the
759 # valuse from the previous entry-point.
763 child
= element
.children
765 if child
.type == "element":
766 if child
.name
== "return":
767 return_type
= child
.nsProp( "type", None )
768 elif child
.name
== "param":
769 param
= self
.context
.factory
.create_item( "parameter", child
, self
.context
)
770 parameters
.append( param
)
776 if self
.return_type
!= return_type
:
777 raise RuntimeError( "Return type changed in %s. Was %s, now %s." % (name
, self
.return_type
, return_type
))
779 if len(parameters
) != len(self
.parameters
):
780 raise RuntimeError( "Parameter count mismatch in %s. Was %d, now %d." % (name
, len(self
.parameters
), len(parameters
)))
782 for j
in range(0, len(parameters
)):
784 p2
= self
.parameters
[j
]
785 if not p1
.compatible( p2
):
786 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
))
789 if true_name
== name
or not self
.initialized
:
790 self
.return_type
= return_type
791 self
.parameters
= parameters
793 for param
in self
.parameters
:
795 self
.images
.append( param
)
799 self
.entry_point_parameters
[name
] = parameters
801 self
.entry_point_parameters
[name
] = []
805 def filter_entry_points(self
, entry_point_list
):
806 """Filter out entry points not in entry_point_list."""
807 if not self
.initialized
:
808 raise RuntimeError('%s is not initialized yet' % self
.name
)
811 for ent
in self
.entry_points
:
812 if ent
not in entry_point_list
:
813 if ent
in self
.static_entry_points
:
814 self
.static_entry_points
.remove(ent
)
815 self
.entry_point_parameters
.pop(ent
)
817 entry_points
.append(ent
)
820 raise RuntimeError('%s has no entry point after filtering' % self
.name
)
822 self
.entry_points
= entry_points
823 if self
.name
not in entry_points
:
824 # use the first remaining entry point
825 self
.name
= entry_points
[0]
826 self
.parameters
= self
.entry_point_parameters
[entry_points
[0]]
828 def get_images(self
):
829 """Return potentially empty list of input images."""
833 def parameterIterator(self
, name
= None):
835 return self
.entry_point_parameters
[name
].__iter
__();
837 return self
.parameters
.__iter
__();
840 def get_parameter_string(self
, entrypoint
= None):
842 params
= self
.entry_point_parameters
[ entrypoint
]
844 params
= self
.parameters
846 return create_parameter_string( params
, 1 )
848 def get_called_parameter_string(self
):
852 for p
in self
.parameterIterator():
853 p_string
= p_string
+ comma
+ p
.name
860 return (self
.offset
>= 0 and not self
.assign_offset
)
862 def is_static_entry_point(self
, name
):
863 return name
in self
.static_entry_points
865 def dispatch_name(self
):
866 if self
.name
in self
.static_entry_points
:
869 return "_dispatch_stub_%u" % (self
.offset
)
871 def static_name(self
, name
):
872 if name
in self
.static_entry_points
:
875 return "_dispatch_stub_%u" % (self
.offset
)
877 def entry_points_for_api_version(self
, api
, version
= None):
878 """Return a list of the entry point names for this function
879 which are supported in the given API (and optionally, version).
881 Use the decimal.Decimal type to precisely express non-integer
885 for entry_point
, api_to_ver
in self
.entry_point_api_map
.iteritems():
886 if api
not in api_to_ver
:
888 if version
is not None and version
< api_to_ver
[api
]:
890 result
.append(entry_point
)
894 class gl_item_factory(object):
895 """Factory to create objects derived from gl_item."""
897 def create_item(self
, item_name
, element
, context
):
898 if item_name
== "function":
899 return gl_function(element
, context
)
900 if item_name
== "type":
901 return gl_type(element
, context
)
902 elif item_name
== "enum":
903 return gl_enum(element
, context
)
904 elif item_name
== "parameter":
905 return gl_parameter(element
, context
)
906 elif item_name
== "api":
912 class gl_api(object):
913 def __init__(self
, factory
):
914 self
.functions_by_name
= {}
915 self
.enums_by_name
= {}
916 self
.types_by_name
= {}
918 self
.category_dict
= {}
919 self
.categories
= [{}, {}, {}, {}]
921 self
.factory
= factory
925 typeexpr
.create_initial_types()
928 def filter_functions(self
, entry_point_list
):
929 """Filter out entry points not in entry_point_list."""
930 functions_by_name
= {}
931 for func
in self
.functions_by_name
.itervalues():
932 entry_points
= [ent
for ent
in func
.entry_points
if ent
in entry_point_list
]
934 func
.filter_entry_points(entry_points
)
935 functions_by_name
[func
.name
] = func
937 self
.functions_by_name
= functions_by_name
939 def filter_functions_by_api(self
, api
, version
= None):
940 """Filter out entry points not in the given API (or
941 optionally, not in the given version of the given API).
943 functions_by_name
= {}
944 for func
in self
.functions_by_name
.itervalues():
945 entry_points
= func
.entry_points_for_api_version(api
, version
)
947 func
.filter_entry_points(entry_points
)
948 functions_by_name
[func
.name
] = func
950 self
.functions_by_name
= functions_by_name
952 def process_element(self
, doc
):
953 element
= doc
.children
954 while element
.type != "element" or element
.name
!= "OpenGLAPI":
955 element
= element
.next
958 self
.process_OpenGLAPI(element
)
962 def process_OpenGLAPI(self
, element
):
963 child
= element
.children
965 if child
.type == "element":
966 if child
.name
== "category":
967 self
.process_category( child
)
968 elif child
.name
== "OpenGLAPI":
969 self
.process_OpenGLAPI( child
)
976 def process_category(self
, cat
):
977 cat_name
= cat
.nsProp( "name", None )
978 cat_number
= cat
.nsProp( "number", None )
980 [cat_type
, key
] = classify_category(cat_name
, cat_number
)
981 self
.categories
[cat_type
][key
] = [cat_name
, cat_number
]
985 if child
.type == "element":
986 if child
.name
== "function":
987 func_name
= real_function_name( child
)
989 temp_name
= child
.nsProp( "name", None )
990 self
.category_dict
[ temp_name
] = [cat_name
, cat_number
]
992 if self
.functions_by_name
.has_key( func_name
):
993 func
= self
.functions_by_name
[ func_name
]
994 func
.process_element( child
)
996 func
= self
.factory
.create_item( "function", child
, self
)
997 self
.functions_by_name
[ func_name
] = func
999 if func
.offset
>= self
.next_offset
:
1000 self
.next_offset
= func
.offset
+ 1
1003 elif child
.name
== "enum":
1004 enum
= self
.factory
.create_item( "enum", child
, self
)
1005 self
.enums_by_name
[ enum
.name
] = enum
1006 elif child
.name
== "type":
1007 t
= self
.factory
.create_item( "type", child
, self
)
1008 self
.types_by_name
[ "GL" + t
.name
] = t
1016 def functionIterateByCategory(self
, cat
= None):
1017 """Iterate over functions by category.
1019 If cat is None, all known functions are iterated in category
1020 order. See classify_category for details of the ordering.
1021 Within a category, functions are sorted by name. If cat is
1022 not None, then only functions in that category are iterated.
1024 lists
= [{}, {}, {}, {}]
1026 for func
in self
.functionIterateAll():
1027 [cat_name
, cat_number
] = self
.category_dict
[func
.name
]
1029 if (cat
== None) or (cat
== cat_name
):
1030 [func_cat_type
, key
] = classify_category(cat_name
, cat_number
)
1032 if not lists
[func_cat_type
].has_key(key
):
1033 lists
[func_cat_type
][key
] = {}
1035 lists
[func_cat_type
][key
][func
.name
] = func
1039 for func_cat_type
in range(0,4):
1040 keys
= lists
[func_cat_type
].keys()
1044 names
= lists
[func_cat_type
][key
].keys()
1048 functions
.append(lists
[func_cat_type
][key
][name
])
1050 return functions
.__iter
__()
1053 def functionIterateByOffset(self
):
1055 for func
in self
.functions_by_name
.itervalues():
1056 if func
.offset
> max_offset
:
1057 max_offset
= func
.offset
1060 temp
= [None for i
in range(0, max_offset
+ 1)]
1061 for func
in self
.functions_by_name
.itervalues():
1062 if func
.offset
!= -1:
1063 temp
[ func
.offset
] = func
1067 for i
in range(0, max_offset
+ 1):
1069 list.append(temp
[i
])
1071 return list.__iter
__();
1074 def functionIterateAll(self
):
1075 return self
.functions_by_name
.itervalues()
1078 def enumIterateByName(self
):
1079 keys
= self
.enums_by_name
.keys()
1084 list.append( self
.enums_by_name
[ enum
] )
1086 return list.__iter
__()
1089 def categoryIterate(self
):
1090 """Iterate over categories.
1092 Iterate over all known categories in the order specified by
1093 classify_category. Each iterated value is a tuple of the
1094 name and number (which may be None) of the category.
1098 for cat_type
in range(0,4):
1099 keys
= self
.categories
[cat_type
].keys()
1103 list.append(self
.categories
[cat_type
][key
])
1105 return list.__iter
__()
1108 def get_category_for_name( self
, name
):
1109 if self
.category_dict
.has_key(name
):
1110 return self
.category_dict
[name
]
1112 return ["<unknown category>", None]
1115 def typeIterate(self
):
1116 return self
.types_by_name
.itervalues()
1119 def find_type( self
, type_name
):
1120 if type_name
in self
.types_by_name
:
1121 return self
.types_by_name
[ type_name
].type_expr
1123 print "Unable to find base type matching \"%s\"." % (type_name
)