blob: ee3013c855fa68147501180d3ab9cad530311189 [file] [log] [blame]
Ian Romanick66a55482005-06-21 23:42:43 +00001#!/usr/bin/env python
Ian Romanick73f59b02004-05-18 18:33:40 +00002
Ian Romanick5f1f2292005-01-07 02:39:09 +00003# (C) Copyright IBM Corporation 2004, 2005
Ian Romanick73f59b02004-05-18 18:33:40 +00004# 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
Ian Romanick66a55482005-06-21 23:42:43 +000028import libxml2
29import re, sys, string
30import typeexpr
Ian Romanick73f59b02004-05-18 18:33:40 +000031
Ian Romanick73f59b02004-05-18 18:33:40 +000032
Ian Romanick66a55482005-06-21 23:42:43 +000033def 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 doc.freeDoc()
44
45 return api
46
47
48def is_attr_true( element, name ):
Ian Romanick73b4c1b2005-04-14 23:00:34 +000049 """Read a name value from an element's attributes.
50
51 The value read from the attribute list must be either 'true' or
52 'false'. If the value is 'false', zero will be returned. If the
53 value is 'true', non-zero will be returned. An exception will be
54 raised for any other value."""
55
Ian Romanick66a55482005-06-21 23:42:43 +000056 value = element.nsProp( name, None )
Ian Romanick73b4c1b2005-04-14 23:00:34 +000057 if value == "true":
58 return 1
59 elif value == "false":
60 return 0
61 else:
62 raise RuntimeError('Invalid value "%s" for boolean "%s".' % (value, name))
63
64
Ian Romanick66a55482005-06-21 23:42:43 +000065class gl_print_base:
66 """Base class of all API pretty-printers.
Ian Romanick93d2d542005-04-18 19:42:23 +000067
Ian Romanick66a55482005-06-21 23:42:43 +000068 In the model-view-controller pattern, this is the view. Any derived
69 class will want to over-ride the printBody, printRealHader, and
70 printRealFooter methods. Some derived classes may want to over-ride
71 printHeader and printFooter, or even Print (though this is unlikely).
Ian Romanick93d2d542005-04-18 19:42:23 +000072 """
Ian Romanickd03ab102005-04-18 21:30:20 +000073
Ian Romanick73f59b02004-05-18 18:33:40 +000074 def __init__(self):
Ian Romanick66a55482005-06-21 23:42:43 +000075 # Name of the script that is generating the output file.
76 # Every derived class should set this to the name of its
77 # source file.
78
79 self.name = "a"
80
81
82 # License on the *generated* source file. This may differ
83 # from the license on the script that is generating the file.
84 # Every derived class should set this to some reasonable
85 # value.
86 #
87 # See license.py for an example of a reasonable value.
88
89 self.license = "The license for this file is unspecified."
90
91
92 # The header_tag is the name of the C preprocessor define
93 # used to prevent multiple inclusion. Typically only
94 # generated C header files need this to be set. Setting it
95 # causes code to be generated automatically in printHeader
96 # and printFooter.
97
Ian Romanick16c3c742005-01-28 19:00:54 +000098 self.header_tag = None
Ian Romanick66a55482005-06-21 23:42:43 +000099
100
101 # List of file-private defines that must be undefined at the
102 # end of the file. This can be used in header files to define
103 # names for use in the file, then undefine them at the end of
104 # the header file.
105
Ian Romanickc2803582005-02-01 00:28:47 +0000106 self.undef_list = []
Ian Romanick66a55482005-06-21 23:42:43 +0000107 return
Ian Romanick73f59b02004-05-18 18:33:40 +0000108
Ian Romanicka9d033c2004-05-19 23:33:08 +0000109
Ian Romanick66a55482005-06-21 23:42:43 +0000110 def Print(self, api):
111 self.printHeader()
112 self.printBody(api)
113 self.printFooter()
Ian Romanick73f59b02004-05-18 18:33:40 +0000114 return
115
Ian Romanicka9d033c2004-05-19 23:33:08 +0000116
Ian Romanick73f59b02004-05-18 18:33:40 +0000117 def printHeader(self):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000118 """Print the header associated with all files and call the printRealHeader method."""
119
Ian Romanick73f59b02004-05-18 18:33:40 +0000120 print '/* DO NOT EDIT - This file generated automatically by %s script */' \
121 % (self.name)
122 print ''
123 print '/*'
124 print ' * ' + self.license.replace('\n', '\n * ')
125 print ' */'
126 print ''
Ian Romanick16c3c742005-01-28 19:00:54 +0000127 if self.header_tag:
128 print '#if !defined( %s )' % (self.header_tag)
129 print '# define %s' % (self.header_tag)
130 print ''
Ian Romanick73f59b02004-05-18 18:33:40 +0000131 self.printRealHeader();
132 return
133
Ian Romanicka9d033c2004-05-19 23:33:08 +0000134
Ian Romanick73f59b02004-05-18 18:33:40 +0000135 def printFooter(self):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000136 """Print the header associated with all files and call the printRealFooter method."""
137
Ian Romanick73f59b02004-05-18 18:33:40 +0000138 self.printRealFooter()
Ian Romanick66a55482005-06-21 23:42:43 +0000139
140 if self.undef_list:
141 print ''
142 for u in self.undef_list:
143 print "# undef %s" % (u)
144
Ian Romanick16c3c742005-01-28 19:00:54 +0000145 if self.header_tag:
Ian Romanickc2803582005-02-01 00:28:47 +0000146 print ''
147 print '#endif /* !defined( %s ) */' % (self.header_tag)
Ian Romanick73f59b02004-05-18 18:33:40 +0000148
149
Ian Romanick73f59b02004-05-18 18:33:40 +0000150 def printRealHeader(self):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000151 """Print the "real" header for the created file.
152
153 In the base class, this function is empty. All derived
154 classes should over-ride this function."""
Ian Romanick73f59b02004-05-18 18:33:40 +0000155 return
156
Ian Romanicka9d033c2004-05-19 23:33:08 +0000157
Ian Romanick73f59b02004-05-18 18:33:40 +0000158 def printRealFooter(self):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000159 """Print the "real" footer for the created file.
160
161 In the base class, this function is empty. All derived
162 classes should over-ride this function."""
Ian Romanick73f59b02004-05-18 18:33:40 +0000163 return
Ian Romanick66a55482005-06-21 23:42:43 +0000164
165
166 def printPure(self):
167 """Conditionally define `PURE' function attribute.
168
169 Conditionally defines a preprocessor macro `PURE' that wraps
170 GCC's `pure' function attribute. The conditional code can be
171 easilly adapted to other compilers that support a similar
172 feature.
173
174 The name is also added to the file's undef_list.
175 """
176 self.undef_list.append("PURE")
177 print """# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
178# define PURE __attribute__((pure))
179# else
180# define PURE
181# endif"""
182 return
183
184
185 def printFastcall(self):
186 """Conditionally define `FASTCALL' function attribute.
187
188 Conditionally defines a preprocessor macro `FASTCALL' that
189 wraps GCC's `fastcall' function attribute. The conditional
190 code can be easilly adapted to other compilers that support a
191 similar feature.
192
193 The name is also added to the file's undef_list.
194 """
195
196 self.undef_list.append("FASTCALL")
197 print """# if defined(__i386__) && defined(__GNUC__)
198# define FASTCALL __attribute__((fastcall))
199# else
200# define FASTCALL
201# endif"""
202 return
203
204
205 def printVisibility(self, S, s):
206 """Conditionally define visibility function attribute.
207
208 Conditionally defines a preprocessor macro name S that wraps
209 GCC's visibility function attribute. The visibility used is
210 the parameter s. The conditional code can be easilly adapted
211 to other compilers that support a similar feature.
212
213 The name is also added to the file's undef_list.
214 """
215
216 self.undef_list.append(S)
217 print """# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
218# define %s __attribute__((visibility("%s")))
219# else
220# define %s
221# endif""" % (S, s, S)
222 return
223
224
225 def printNoinline(self):
226 """Conditionally define `NOINLINE' function attribute.
227
228 Conditionally defines a preprocessor macro `NOINLINE' that
229 wraps GCC's `noinline' function attribute. The conditional
230 code can be easilly adapted to other compilers that support a
231 similar feature.
232
233 The name is also added to the file's undef_list.
234 """
235
236 self.undef_list.append("NOINLINE")
237 print """# if defined(__GNUC__)
238# define NOINLINE __attribute__((noinline))
239# else
240# define NOINLINE
241# endif"""
242 return
243
244
245 def printHaveAlias(self):
246 """Conditionally define `HAVE_ALIAS'.
247
248 Conditionally defines a preprocessor macro `HAVE_ALIAS'. The
249 existance of this macro can be used to determine whether or
250 not GCC's alias function attribute can be used.
251
252 The name is also added to the file's undef_list.
253 """
254
255 self.undef_list.append("HAVE_ALIAS")
256 print """# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
257# define HAVE_ALIAS
258# endif"""
259 return
260
261
262def real_function_name(element):
263 name = element.nsProp( "name", None )
264 alias = element.nsProp( "alias", None )
265
266 if alias:
267 return alias
268 else:
269 return name
270
271
Ian Romanick5aafea02005-06-24 18:35:31 +0000272def real_category_name(c):
273 if re.compile("[1-9][0-9]*[.][0-9]+").match(c):
274 return "GL_VERSION_" + c.replace(".", "_")
275 else:
276 return c
277
278
279def create_parameter_string(parameters):
280 """Create a parameter string from a list of gl_parameters."""
281
282 list = []
283 for p in parameters:
284 list.append( p.string() )
285
286 if len(list) == 0: list = ["void"]
287
288 return string.join(list, ", ")
289
290
Ian Romanick66a55482005-06-21 23:42:43 +0000291class gl_item:
292 def __init__(self, element, context):
293 self.context = context
Ian Romanick66a55482005-06-21 23:42:43 +0000294 self.name = element.nsProp( "name", None )
Ian Romanick5aafea02005-06-24 18:35:31 +0000295 self.category = real_category_name( element.parent.nsProp( "name", None ) )
Ian Romanick66a55482005-06-21 23:42:43 +0000296 return
297
298
299class gl_type( gl_item ):
300 def __init__(self, element, context):
301 gl_item.__init__(self, element, context)
302 self.size = int( element.nsProp( "size", None ), 0 )
303
304 te = typeexpr.type_expression( None )
305 tn = typeexpr.type_node()
306 tn.size = int( element.nsProp( "size", None ), 0 )
307 tn.integer = not is_attr_true( element, "float" )
308 tn.unsigned = is_attr_true( element, "unsigned" )
309 tn.name = "GL" + self.name
310 te.set_base_type_node( tn )
311
312 self.type_expr = te
313 return
314
315
316 def get_type_expression(self):
317 return self.type_expr
318
319
320class gl_enum( gl_item ):
321 def __init__(self, element, context):
322 gl_item.__init__(self, element, context)
323 self.value = int( element.nsProp( "value", None ), 0 )
324
325 temp = element.nsProp( "count", None )
326 if not temp or temp == "?":
327 self.default_count = -1
328 else:
329 try:
330 c = int(temp)
331 except Exception,e:
332 raise RuntimeError('Invalid count value "%s" for enum "%s" in function "%s" when an integer was expected.' % (temp, self.name, n))
333
334 self.default_count = c
335
336 return
337
338
339 def priority(self):
340 """Calculate a 'priority' for this enum name.
341
342 When an enum is looked up by number, there may be many
343 possible names, but only one is the 'prefered' name. The
344 priority is used to select which name is the 'best'.
345
346 Highest precedence is given to core GL name. ARB extension
347 names have the next highest, followed by EXT extension names.
348 Vendor extension names are the lowest.
349 """
350
351 if self.name.endswith( "_BIT" ):
352 bias = 1
353 else:
354 bias = 0
355
356 if self.category.startswith( "GL_VERSION_" ):
357 priority = 0
358 elif self.category.startswith( "GL_ARB_" ):
359 priority = 2
360 elif self.category.startswith( "GL_EXT_" ):
361 priority = 4
362 else:
363 priority = 6
364
365 return priority + bias
366
367
368
369class gl_parameter:
370 def __init__(self, element, context):
371 self.name = element.nsProp( "name", None )
372
373 ts = element.nsProp( "type", None )
374 self.type_expr = typeexpr.type_expression( ts, context )
375
376 temp = element.nsProp( "variable_param", None )
377 if temp:
378 self.count_parameter_list = temp.split( ' ' )
379 else:
380 self.count_parameter_list = []
381
382 # The count tag can be either a numeric string or the name of
383 # a variable. If it is the name of a variable, the int(c)
384 # statement will throw an exception, and the except block will
385 # take over.
386
387 c = element.nsProp( "count", None )
388 try:
389 count = int(c)
390 self.count = count
391 self.counter = None
392 except Exception,e:
393 count = 1
394 self.count = 0
395 self.counter = c
396
397 self.count_scale = int(element.nsProp( "count_scale", None ))
398
399 elements = (count * self.count_scale)
400 if elements == 1:
401 elements = 0
402
403 #if ts == "GLdouble":
404 # print '/* stack size -> %s = %u (before)*/' % (self.name, self.type_expr.get_stack_size())
405 # print '/* # elements = %u */' % (elements)
406 self.type_expr.set_elements( elements )
407 #if ts == "GLdouble":
408 # print '/* stack size -> %s = %u (after) */' % (self.name, self.type_expr.get_stack_size())
409
410 self.is_counter = is_attr_true( element, 'counter' )
411 self.is_output = is_attr_true( element, 'output' )
412
413
414 # Pixel data has special parameters.
415
416 self.width = element.nsProp('img_width', None)
417 self.height = element.nsProp('img_height', None)
418 self.depth = element.nsProp('img_depth', None)
419 self.extent = element.nsProp('img_extent', None)
420
421 self.img_xoff = element.nsProp('img_xoff', None)
422 self.img_yoff = element.nsProp('img_yoff', None)
423 self.img_zoff = element.nsProp('img_zoff', None)
424 self.img_woff = element.nsProp('img_woff', None)
425
426 self.img_format = element.nsProp('img_format', None)
427 self.img_type = element.nsProp('img_type', None)
428 self.img_target = element.nsProp('img_target', None)
429
430 self.img_pad_dimensions = is_attr_true( element, 'img_pad_dimensions' )
431 self.img_null_flag = is_attr_true( element, 'img_null_flag' )
432 self.img_send_null = is_attr_true( element, 'img_send_null' )
433
434 return
435
436
437 def compatible(self, other):
438 return 1
439
440
441 def is_array(self):
442 return self.is_pointer()
443
444
445 def is_pointer(self):
446 return self.type_expr.is_pointer()
447
448
449 def is_image(self):
450 if self.width:
451 return 1
452 else:
453 return 0
454
455
456 def is_variable_length(self):
457 return len(self.count_parameter_list) or self.counter
458
459
460 def is_64_bit(self):
461 count = self.type_expr.get_element_count()
462 if count:
463 if (self.size() / count) == 8:
464 return 1
465 else:
466 if self.size() == 8:
467 return 1
468
469 return 0
470
471
472 def string(self):
473 return self.type_expr.original_string + " " + self.name
474
475
476 def type_string(self):
477 return self.type_expr.original_string
478
479
480 def get_base_type_string(self):
481 return self.type_expr.get_base_name()
482
483
484 def get_dimensions(self):
485 if not self.width:
486 return [ 0, "0", "0", "0", "0" ]
487
488 dim = 1
489 w = self.width
490 h = "1"
491 d = "1"
492 e = "1"
493
494 if self.height:
495 dim = 2
496 h = self.height
497
498 if self.depth:
499 dim = 3
500 d = self.depth
501
502 if self.extent:
503 dim = 4
504 e = self.extent
505
506 return [ dim, w, h, d, e ]
507
508
509 def get_stack_size(self):
510 return self.type_expr.get_stack_size()
511
512
513 def size(self):
514 if self.is_image():
515 return 0
516 else:
517 return self.type_expr.get_element_size()
518
519
520 def get_element_count(self):
521 c = self.type_expr.get_element_count()
522 if c == 0:
523 return 1
524
525 return c
526
527
528 def size_string(self, use_parens = 1):
529 s = self.size()
530 if self.counter or self.count_parameter_list:
531 list = [ "compsize" ]
532
533 if self.counter and self.count_parameter_list:
534 list.append( self.counter )
535 elif self.counter:
536 list = [ self.counter ]
537
538 if s > 1:
539 list.append( str(s) )
540
541 if len(list) > 1 and use_parens :
542 return "(%s)" % (string.join(list, " * "))
543 else:
544 return string.join(list, " * ")
545
546 elif self.is_image():
547 return "compsize"
548 else:
549 return str(s)
550
551
552 def format_string(self):
553 if self.type_expr.original_string == "GLenum":
554 return "0x%x"
555 else:
556 return self.type_expr.format_string()
557
558
559
560class gl_function( gl_item ):
561 def __init__(self, element, context):
562 self.context = context
563 self.name = None
564
565 self.entry_points = []
566 self.return_type = "void"
567 self.parameters = []
568 self.offset = -1
Ian Romanick5aafea02005-06-24 18:35:31 +0000569 self.initialized = 0
Ian Romanick66a55482005-06-21 23:42:43 +0000570 self.images = []
571
Ian Romanick5aafea02005-06-24 18:35:31 +0000572 # Track the parameter string (for the function prototype)
573 # for each entry-point. This is done because some functions
574 # change their prototype slightly when promoted from extension
575 # to ARB extension to core. glTexImage3DEXT and glTexImage3D
576 # are good examples of this. Scripts that need to generate
577 # code for these differing aliases need to real prototype
578 # for each entry-point. Otherwise, they may generate code
579 # that won't compile.
580
581 self.parameter_strings = {}
582
Ian Romanick66a55482005-06-21 23:42:43 +0000583 self.process_element( element )
584
585 return
586
587
588 def process_element(self, element):
589 name = element.nsProp( "name", None )
590 alias = element.nsProp( "alias", None )
591
592 self.entry_points.append( name )
593 if alias:
594 true_name = alias
595 else:
596 true_name = name
597
598 # Only try to set the offset when a non-alias
599 # entry-point is being processes.
600
601 offset = element.nsProp( "offset", None )
602 if offset:
603 try:
604 o = int( offset )
605 self.offset = o
606 except Exception, e:
607 self.offset = -1
608
609
610 if not self.name:
611 self.name = true_name
612 elif self.name != true_name:
613 raise RuntimeError("Function true name redefined. Was %s, now %s." % (self.name, true_name))
614
615
616 # There are two possible cases. The first time an entry-point
Ian Romanick5aafea02005-06-24 18:35:31 +0000617 # with data is seen, self.initialized will be 0. On that
Ian Romanick66a55482005-06-21 23:42:43 +0000618 # pass, we just fill in the data. The next time an
Ian Romanick5aafea02005-06-24 18:35:31 +0000619 # entry-point with data is seen, self.initialized will be 1.
Ian Romanick66a55482005-06-21 23:42:43 +0000620 # On that pass we have to make that the new values match the
621 # valuse from the previous entry-point.
622
Ian Romanick5aafea02005-06-24 18:35:31 +0000623 parameters = []
624 return_type = "void"
Ian Romanick66a55482005-06-21 23:42:43 +0000625 child = element.children
Ian Romanick5aafea02005-06-24 18:35:31 +0000626 while child:
627 if child.type == "element":
628 if child.name == "return":
629 return_type = child.nsProp( "type", None )
630 elif child.name == "param":
631 param = self.context.factory.create_item( "parameter", child, self.context)
632 parameters.append( param )
Ian Romanick66a55482005-06-21 23:42:43 +0000633
Ian Romanick5aafea02005-06-24 18:35:31 +0000634 child = child.next
Ian Romanick66a55482005-06-21 23:42:43 +0000635
Ian Romanick5aafea02005-06-24 18:35:31 +0000636
637 if self.initialized:
638 if self.return_type != return_type:
639 raise RuntimeError( "Return type changed in %s. Was %s, now %s." % (name, self.return_type, return_type))
Ian Romanick66a55482005-06-21 23:42:43 +0000640
641 if len(parameters) != len(self.parameters):
642 raise RuntimeError( "Parameter count mismatch in %s. Was %d, now %d." % (name, len(self.parameters), len(parameters)))
643
644 for j in range(0, len(parameters)):
645 p1 = parameters[j]
646 p2 = self.parameters[j]
647 if not p1.compatible( p2 ):
648 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))
649
650
Ian Romanick5aafea02005-06-24 18:35:31 +0000651 if true_name == name or not self.initialized:
652 self.return_type = return_type
653 self.parameters = parameters
Ian Romanick66a55482005-06-21 23:42:43 +0000654
Ian Romanick66a55482005-06-21 23:42:43 +0000655 for param in self.parameters:
656 if param.is_image():
657 self.images.append( param )
658
659 if element.children:
Ian Romanick5aafea02005-06-24 18:35:31 +0000660 self.initialized = 1
661 self.parameter_strings[name] = create_parameter_string(parameters)
662 else:
663 self.parameter_strings[name] = None
Ian Romanick66a55482005-06-21 23:42:43 +0000664
665 return
666
667
668 def get_images(self):
669 """Return potentially empty list of input images."""
670 return self.images
671
672
673 def parameterIterator(self):
674 return self.parameters.__iter__();
675
676
Ian Romanick5aafea02005-06-24 18:35:31 +0000677 def get_parameter_string(self, entrypoint = None):
678 if entrypoint:
679 s = self.parameter_strings[ entrypoint ]
680 if s:
681 return s
682
683 return create_parameter_string( self.parameters )
Ian Romanick66a55482005-06-21 23:42:43 +0000684
685
686class gl_item_factory:
687 """Factory to create objects derived from gl_item."""
688
689 def create_item(self, item_name, element, context):
690 if item_name == "function":
691 return gl_function(element, context)
692 if item_name == "type":
693 return gl_type(element, context)
694 elif item_name == "enum":
695 return gl_enum(element, context)
696 elif item_name == "parameter":
697 return gl_parameter(element, context)
698 elif item_name == "api":
699 return gl_api(self)
700 else:
701 return None
702
703
704class gl_api:
705 def __init__(self, factory):
706 self.functions_by_name = {}
707 self.enums_by_name = {}
708 self.types_by_name = {}
709 self.category_dict = {}
710
711 self.factory = factory
712
713 typeexpr.create_initial_types()
714 return
715
716
717 def process_element(self, doc):
718 element = doc.children
719 while element.type != "element" or element.name != "OpenGLAPI":
720 element = element.next
721
722 if element:
723 self.process_OpenGLAPI(element)
724 return
725
726
727 def process_OpenGLAPI(self, element):
728 child = element.children
729 while child:
730 if child.type == "element":
731 if child.name == "category":
732 self.process_category( child )
733 elif child.name == "OpenGLAPI":
734 self.process_OpenGLAPI( child )
735
736 child = child.next
737
738 return
739
740
741 def process_category(self, cat):
742 cat_name = cat.nsProp( "name", None )
743 cat_number = cat.nsProp( "number", None )
744
745 child = cat.children
746 while child:
747 if child.type == "element":
748 if child.name == "function":
749 func_name = real_function_name( child )
750
Ian Romanick5aafea02005-06-24 18:35:31 +0000751 temp_name = child.nsProp( "name", None )
752 self.category_dict[ temp_name ] = [cat_name, cat_number]
753
Ian Romanick66a55482005-06-21 23:42:43 +0000754 if self.functions_by_name.has_key( func_name ):
755 func = self.functions_by_name[ func_name ]
756 func.process_element( child )
757 else:
758 func = self.factory.create_item( "function", child, self )
759 self.functions_by_name[ func_name ] = func
760
Ian Romanick66a55482005-06-21 23:42:43 +0000761
762 elif child.name == "enum":
763 enum = self.factory.create_item( "enum", child, self )
764 self.enums_by_name[ enum.name ] = enum
765 elif child.name == "type":
766 t = self.factory.create_item( "type", child, self )
767 self.types_by_name[ "GL" + t.name ] = t
768
769
770 child = child.next
771
772 return
773
774
775 def functionIterateByOffset(self):
776 max_offset = -1
777 for func in self.functions_by_name.itervalues():
778 if func.offset > max_offset:
779 max_offset = func.offset
780
781
782 temp = [None for i in range(0, max_offset + 1)]
783 for func in self.functions_by_name.itervalues():
784 if func.offset != -1:
785 temp[ func.offset ] = func
786
787
788 list = []
789 for i in range(0, max_offset + 1):
790 if temp[i]:
791 list.append(temp[i])
792
793 return list.__iter__();
794
795
796 def functionIterateAll(self):
797 return self.functions_by_name.itervalues()
798
799
800 def enumIterateByName(self):
801 keys = self.enums_by_name.keys()
802 keys.sort()
803
804 list = []
805 for enum in keys:
806 list.append( self.enums_by_name[ enum ] )
807
808 return list.__iter__()
809
810
811 def get_category_for_name( self, name ):
812 if self.category_dict.has_key(name):
813 return self.category_dict[name]
814 else:
815 return ["<unknown category>", None]
816
817
818 def typeIterate(self):
819 return self.types_by_name.itervalues()
820
821
822 def find_type( self, type_name ):
823 if type_name in self.types_by_name:
824 return self.types_by_name[ type_name ].type_expr
825 else:
826 print "Unable to find base type matching \"%s\"." % (type_name)
827 return None