Tizen 2.0 Release
[profile/ivi/osmesa.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:
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:
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.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
354 class 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
403 class 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
596 class 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
760 class 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
778 class 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