glapi: use new-style Python classes.
[mesa.git] / src / mapi / glapi / gen / gl_XML.py
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
28 import libxml2
29 import re, sys, string
30 import typeexpr
31
32
33 def 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
58 def 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
75 class gl_print_base(object):
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
255 def 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
265 def 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
272 def 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
307 def 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
325 class gl_item(object):
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
333 class 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.pointer = is_attr_true( element, "pointer" )
344 tn.name = "GL" + self.name
345 te.set_base_type_node( tn )
346
347 self.type_expr = te
348 return
349
350
351 def get_type_expression(self):
352 return self.type_expr
353
354
355 class gl_enum( gl_item ):
356 def __init__(self, element, context):
357 gl_item.__init__(self, element, context)
358 self.value = int( element.nsProp( "value", None ), 0 )
359
360 temp = element.nsProp( "count", None )
361 if not temp or temp == "?":
362 self.default_count = -1
363 else:
364 try:
365 c = int(temp)
366 except Exception,e:
367 raise RuntimeError('Invalid count value "%s" for enum "%s" in function "%s" when an integer was expected.' % (temp, self.name, n))
368
369 self.default_count = c
370
371 return
372
373
374 def priority(self):
375 """Calculate a 'priority' for this enum name.
376
377 When an enum is looked up by number, there may be many
378 possible names, but only one is the 'prefered' name. The
379 priority is used to select which name is the 'best'.
380
381 Highest precedence is given to core GL name. ARB extension
382 names have the next highest, followed by EXT extension names.
383 Vendor extension names are the lowest.
384 """
385
386 if self.name.endswith( "_BIT" ):
387 bias = 1
388 else:
389 bias = 0
390
391 if self.category.startswith( "GL_VERSION_" ):
392 priority = 0
393 elif self.category.startswith( "GL_ARB_" ):
394 priority = 2
395 elif self.category.startswith( "GL_EXT_" ):
396 priority = 4
397 else:
398 priority = 6
399
400 return priority + bias
401
402
403
404 class gl_parameter(object):
405 def __init__(self, element, context):
406 self.name = element.nsProp( "name", None )
407
408 ts = element.nsProp( "type", None )
409 self.type_expr = typeexpr.type_expression( ts, context )
410
411 temp = element.nsProp( "variable_param", None )
412 if temp:
413 self.count_parameter_list = temp.split( ' ' )
414 else:
415 self.count_parameter_list = []
416
417 # The count tag can be either a numeric string or the name of
418 # a variable. If it is the name of a variable, the int(c)
419 # statement will throw an exception, and the except block will
420 # take over.
421
422 c = element.nsProp( "count", None )
423 try:
424 count = int(c)
425 self.count = count
426 self.counter = None
427 except Exception,e:
428 count = 1
429 self.count = 0
430 self.counter = c
431
432 self.count_scale = int(element.nsProp( "count_scale", None ))
433
434 elements = (count * self.count_scale)
435 if elements == 1:
436 elements = 0
437
438 #if ts == "GLdouble":
439 # print '/* stack size -> %s = %u (before)*/' % (self.name, self.type_expr.get_stack_size())
440 # print '/* # elements = %u */' % (elements)
441 self.type_expr.set_elements( elements )
442 #if ts == "GLdouble":
443 # print '/* stack size -> %s = %u (after) */' % (self.name, self.type_expr.get_stack_size())
444
445 self.is_client_only = is_attr_true( element, 'client_only' )
446 self.is_counter = is_attr_true( element, 'counter' )
447 self.is_output = is_attr_true( element, 'output' )
448
449
450 # Pixel data has special parameters.
451
452 self.width = element.nsProp('img_width', None)
453 self.height = element.nsProp('img_height', None)
454 self.depth = element.nsProp('img_depth', None)
455 self.extent = element.nsProp('img_extent', None)
456
457 self.img_xoff = element.nsProp('img_xoff', None)
458 self.img_yoff = element.nsProp('img_yoff', None)
459 self.img_zoff = element.nsProp('img_zoff', None)
460 self.img_woff = element.nsProp('img_woff', None)
461
462 self.img_format = element.nsProp('img_format', None)
463 self.img_type = element.nsProp('img_type', None)
464 self.img_target = element.nsProp('img_target', None)
465
466 self.img_pad_dimensions = is_attr_true( element, 'img_pad_dimensions' )
467 self.img_null_flag = is_attr_true( element, 'img_null_flag' )
468 self.img_send_null = is_attr_true( element, 'img_send_null' )
469
470 self.is_padding = is_attr_true( element, 'padding' )
471 return
472
473
474 def compatible(self, other):
475 return 1
476
477
478 def is_array(self):
479 return self.is_pointer()
480
481
482 def is_pointer(self):
483 return self.type_expr.is_pointer()
484
485
486 def is_image(self):
487 if self.width:
488 return 1
489 else:
490 return 0
491
492
493 def is_variable_length(self):
494 return len(self.count_parameter_list) or self.counter
495
496
497 def is_64_bit(self):
498 count = self.type_expr.get_element_count()
499 if count:
500 if (self.size() / count) == 8:
501 return 1
502 else:
503 if self.size() == 8:
504 return 1
505
506 return 0
507
508
509 def string(self):
510 return self.type_expr.original_string + " " + self.name
511
512
513 def type_string(self):
514 return self.type_expr.original_string
515
516
517 def get_base_type_string(self):
518 return self.type_expr.get_base_name()
519
520
521 def get_dimensions(self):
522 if not self.width:
523 return [ 0, "0", "0", "0", "0" ]
524
525 dim = 1
526 w = self.width
527 h = "1"
528 d = "1"
529 e = "1"
530
531 if self.height:
532 dim = 2
533 h = self.height
534
535 if self.depth:
536 dim = 3
537 d = self.depth
538
539 if self.extent:
540 dim = 4
541 e = self.extent
542
543 return [ dim, w, h, d, e ]
544
545
546 def get_stack_size(self):
547 return self.type_expr.get_stack_size()
548
549
550 def size(self):
551 if self.is_image():
552 return 0
553 else:
554 return self.type_expr.get_element_size()
555
556
557 def get_element_count(self):
558 c = self.type_expr.get_element_count()
559 if c == 0:
560 return 1
561
562 return c
563
564
565 def size_string(self, use_parens = 1):
566 s = self.size()
567 if self.counter or self.count_parameter_list:
568 list = [ "compsize" ]
569
570 if self.counter and self.count_parameter_list:
571 list.append( self.counter )
572 elif self.counter:
573 list = [ self.counter ]
574
575 if s > 1:
576 list.append( str(s) )
577
578 if len(list) > 1 and use_parens :
579 return "(%s)" % (string.join(list, " * "))
580 else:
581 return string.join(list, " * ")
582
583 elif self.is_image():
584 return "compsize"
585 else:
586 return str(s)
587
588
589 def format_string(self):
590 if self.type_expr.original_string == "GLenum":
591 return "0x%x"
592 else:
593 return self.type_expr.format_string()
594
595
596
597 class gl_function( gl_item ):
598 def __init__(self, element, context):
599 self.context = context
600 self.name = None
601
602 self.entry_points = []
603 self.return_type = "void"
604 self.parameters = []
605 self.offset = -1
606 self.initialized = 0
607 self.images = []
608
609 self.assign_offset = 0
610
611 self.static_entry_points = []
612
613 # Track the parameter string (for the function prototype)
614 # for each entry-point. This is done because some functions
615 # change their prototype slightly when promoted from extension
616 # to ARB extension to core. glTexImage3DEXT and glTexImage3D
617 # are good examples of this. Scripts that need to generate
618 # code for these differing aliases need to real prototype
619 # for each entry-point. Otherwise, they may generate code
620 # that won't compile.
621
622 self.entry_point_parameters = {}
623
624 self.process_element( element )
625
626 return
627
628
629 def process_element(self, element):
630 name = element.nsProp( "name", None )
631 alias = element.nsProp( "alias", None )
632
633 if is_attr_true(element, "static_dispatch"):
634 self.static_entry_points.append(name)
635
636 self.entry_points.append( name )
637 if alias:
638 true_name = alias
639 else:
640 true_name = name
641
642 # Only try to set the offset when a non-alias
643 # entry-point is being processes.
644
645 offset = element.nsProp( "offset", None )
646 if offset:
647 try:
648 o = int( offset )
649 self.offset = o
650 except Exception, e:
651 self.offset = -1
652 if offset == "assign":
653 self.assign_offset = 1
654
655
656 if not self.name:
657 self.name = true_name
658 elif self.name != true_name:
659 raise RuntimeError("Function true name redefined. Was %s, now %s." % (self.name, true_name))
660
661
662 # There are two possible cases. The first time an entry-point
663 # with data is seen, self.initialized will be 0. On that
664 # pass, we just fill in the data. The next time an
665 # entry-point with data is seen, self.initialized will be 1.
666 # On that pass we have to make that the new values match the
667 # valuse from the previous entry-point.
668
669 parameters = []
670 return_type = "void"
671 child = element.children
672 while child:
673 if child.type == "element":
674 if child.name == "return":
675 return_type = child.nsProp( "type", None )
676 elif child.name == "param":
677 param = self.context.factory.create_item( "parameter", child, self.context)
678 parameters.append( param )
679
680 child = child.next
681
682
683 if self.initialized:
684 if self.return_type != return_type:
685 raise RuntimeError( "Return type changed in %s. Was %s, now %s." % (name, self.return_type, return_type))
686
687 if len(parameters) != len(self.parameters):
688 raise RuntimeError( "Parameter count mismatch in %s. Was %d, now %d." % (name, len(self.parameters), len(parameters)))
689
690 for j in range(0, len(parameters)):
691 p1 = parameters[j]
692 p2 = self.parameters[j]
693 if not p1.compatible( p2 ):
694 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))
695
696
697 if true_name == name or not self.initialized:
698 self.return_type = return_type
699 self.parameters = parameters
700
701 for param in self.parameters:
702 if param.is_image():
703 self.images.append( param )
704
705 if element.children:
706 self.initialized = 1
707 self.entry_point_parameters[name] = parameters
708 else:
709 self.entry_point_parameters[name] = []
710
711 return
712
713 def filter_entry_points(self, entry_point_list):
714 """Filter out entry points not in entry_point_list."""
715 if not self.initialized:
716 raise RuntimeError('%s is not initialized yet' % self.name)
717
718 entry_points = []
719 for ent in self.entry_points:
720 if ent not in entry_point_list:
721 if ent in self.static_entry_points:
722 self.static_entry_points.remove(ent)
723 self.entry_point_parameters.pop(ent)
724 else:
725 entry_points.append(ent)
726
727 if not entry_points:
728 raise RuntimeError('%s has no entry point after filtering' % self.name)
729
730 self.entry_points = entry_points
731 if self.name not in entry_points:
732 # use the first remaining entry point
733 self.name = entry_points[0]
734 self.parameters = self.entry_point_parameters[entry_points[0]]
735
736 def get_images(self):
737 """Return potentially empty list of input images."""
738 return self.images
739
740
741 def parameterIterator(self):
742 return self.parameters.__iter__();
743
744
745 def get_parameter_string(self, entrypoint = None):
746 if entrypoint:
747 params = self.entry_point_parameters[ entrypoint ]
748 else:
749 params = self.parameters
750
751 return create_parameter_string( params, 1 )
752
753 def get_called_parameter_string(self):
754 p_string = ""
755 comma = ""
756
757 for p in self.parameterIterator():
758 p_string = p_string + comma + p.name
759 comma = ", "
760
761 return p_string
762
763
764 def is_abi(self):
765 return (self.offset >= 0 and not self.assign_offset)
766
767 def is_static_entry_point(self, name):
768 return name in self.static_entry_points
769
770 def dispatch_name(self):
771 if self.name in self.static_entry_points:
772 return self.name
773 else:
774 return "_dispatch_stub_%u" % (self.offset)
775
776 def static_name(self, name):
777 if name in self.static_entry_points:
778 return name
779 else:
780 return "_dispatch_stub_%u" % (self.offset)
781
782
783 class gl_item_factory(object):
784 """Factory to create objects derived from gl_item."""
785
786 def create_item(self, item_name, element, context):
787 if item_name == "function":
788 return gl_function(element, context)
789 if item_name == "type":
790 return gl_type(element, context)
791 elif item_name == "enum":
792 return gl_enum(element, context)
793 elif item_name == "parameter":
794 return gl_parameter(element, context)
795 elif item_name == "api":
796 return gl_api(self)
797 else:
798 return None
799
800
801 class gl_api(object):
802 def __init__(self, factory):
803 self.functions_by_name = {}
804 self.enums_by_name = {}
805 self.types_by_name = {}
806
807 self.category_dict = {}
808 self.categories = [{}, {}, {}, {}]
809
810 self.factory = factory
811
812 self.next_offset = 0
813
814 typeexpr.create_initial_types()
815 return
816
817 def filter_functions(self, entry_point_list):
818 """Filter out entry points not in entry_point_list."""
819 functions_by_name = {}
820 for func in self.functions_by_name.itervalues():
821 entry_points = [ent for ent in func.entry_points if ent in entry_point_list]
822 if entry_points:
823 func.filter_entry_points(entry_points)
824 functions_by_name[func.name] = func
825
826 self.functions_by_name = functions_by_name
827
828 def process_element(self, doc):
829 element = doc.children
830 while element.type != "element" or element.name != "OpenGLAPI":
831 element = element.next
832
833 if element:
834 self.process_OpenGLAPI(element)
835 return
836
837
838 def process_OpenGLAPI(self, element):
839 child = element.children
840 while child:
841 if child.type == "element":
842 if child.name == "category":
843 self.process_category( child )
844 elif child.name == "OpenGLAPI":
845 self.process_OpenGLAPI( child )
846
847 child = child.next
848
849 return
850
851
852 def process_category(self, cat):
853 cat_name = cat.nsProp( "name", None )
854 cat_number = cat.nsProp( "number", None )
855
856 [cat_type, key] = classify_category(cat_name, cat_number)
857 self.categories[cat_type][key] = [cat_name, cat_number]
858
859 child = cat.children
860 while child:
861 if child.type == "element":
862 if child.name == "function":
863 func_name = real_function_name( child )
864
865 temp_name = child.nsProp( "name", None )
866 self.category_dict[ temp_name ] = [cat_name, cat_number]
867
868 if self.functions_by_name.has_key( func_name ):
869 func = self.functions_by_name[ func_name ]
870 func.process_element( child )
871 else:
872 func = self.factory.create_item( "function", child, self )
873 self.functions_by_name[ func_name ] = func
874
875 if func.offset >= self.next_offset:
876 self.next_offset = func.offset + 1
877
878
879 elif child.name == "enum":
880 enum = self.factory.create_item( "enum", child, self )
881 self.enums_by_name[ enum.name ] = enum
882 elif child.name == "type":
883 t = self.factory.create_item( "type", child, self )
884 self.types_by_name[ "GL" + t.name ] = t
885
886
887 child = child.next
888
889 return
890
891
892 def functionIterateByCategory(self, cat = None):
893 """Iterate over functions by category.
894
895 If cat is None, all known functions are iterated in category
896 order. See classify_category for details of the ordering.
897 Within a category, functions are sorted by name. If cat is
898 not None, then only functions in that category are iterated.
899 """
900 lists = [{}, {}, {}, {}]
901
902 for func in self.functionIterateAll():
903 [cat_name, cat_number] = self.category_dict[func.name]
904
905 if (cat == None) or (cat == cat_name):
906 [func_cat_type, key] = classify_category(cat_name, cat_number)
907
908 if not lists[func_cat_type].has_key(key):
909 lists[func_cat_type][key] = {}
910
911 lists[func_cat_type][key][func.name] = func
912
913
914 functions = []
915 for func_cat_type in range(0,4):
916 keys = lists[func_cat_type].keys()
917 keys.sort()
918
919 for key in keys:
920 names = lists[func_cat_type][key].keys()
921 names.sort()
922
923 for name in names:
924 functions.append(lists[func_cat_type][key][name])
925
926 return functions.__iter__()
927
928
929 def functionIterateByOffset(self):
930 max_offset = -1
931 for func in self.functions_by_name.itervalues():
932 if func.offset > max_offset:
933 max_offset = func.offset
934
935
936 temp = [None for i in range(0, max_offset + 1)]
937 for func in self.functions_by_name.itervalues():
938 if func.offset != -1:
939 temp[ func.offset ] = func
940
941
942 list = []
943 for i in range(0, max_offset + 1):
944 if temp[i]:
945 list.append(temp[i])
946
947 return list.__iter__();
948
949
950 def functionIterateAll(self):
951 return self.functions_by_name.itervalues()
952
953
954 def enumIterateByName(self):
955 keys = self.enums_by_name.keys()
956 keys.sort()
957
958 list = []
959 for enum in keys:
960 list.append( self.enums_by_name[ enum ] )
961
962 return list.__iter__()
963
964
965 def categoryIterate(self):
966 """Iterate over categories.
967
968 Iterate over all known categories in the order specified by
969 classify_category. Each iterated value is a tuple of the
970 name and number (which may be None) of the category.
971 """
972
973 list = []
974 for cat_type in range(0,4):
975 keys = self.categories[cat_type].keys()
976 keys.sort()
977
978 for key in keys:
979 list.append(self.categories[cat_type][key])
980
981 return list.__iter__()
982
983
984 def get_category_for_name( self, name ):
985 if self.category_dict.has_key(name):
986 return self.category_dict[name]
987 else:
988 return ["<unknown category>", None]
989
990
991 def typeIterate(self):
992 return self.types_by_name.itervalues()
993
994
995 def find_type( self, type_name ):
996 if type_name in self.types_by_name:
997 return self.types_by_name[ type_name ].type_expr
998 else:
999 print "Unable to find base type matching \"%s\"." % (type_name)
1000 return None