blob: 0cea26877711f9b20f91480dd006943b20e3f949 [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")
Brian Paulc8f86102005-10-20 21:12:35 +0000197 # I've removed the previous code for __attribute__((fastcall))
198 # because it breaks server-side GLX. (BrianP)
199 print "#define FASTCALL"
Ian Romanick66a55482005-06-21 23:42:43 +0000200 return
201
202
203 def printVisibility(self, S, s):
204 """Conditionally define visibility function attribute.
205
206 Conditionally defines a preprocessor macro name S that wraps
207 GCC's visibility function attribute. The visibility used is
208 the parameter s. The conditional code can be easilly adapted
209 to other compilers that support a similar feature.
210
211 The name is also added to the file's undef_list.
212 """
213
214 self.undef_list.append(S)
Adam Jacksonca1ac982005-08-26 17:50:39 +0000215 print """# if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(__ELF__)
Ian Romanick66a55482005-06-21 23:42:43 +0000216# define %s __attribute__((visibility("%s")))
217# else
218# define %s
219# endif""" % (S, s, S)
220 return
221
222
223 def printNoinline(self):
224 """Conditionally define `NOINLINE' function attribute.
225
226 Conditionally defines a preprocessor macro `NOINLINE' that
227 wraps GCC's `noinline' function attribute. The conditional
228 code can be easilly adapted to other compilers that support a
229 similar feature.
230
231 The name is also added to the file's undef_list.
232 """
233
234 self.undef_list.append("NOINLINE")
235 print """# if defined(__GNUC__)
236# define NOINLINE __attribute__((noinline))
237# else
238# define NOINLINE
239# endif"""
240 return
241
242
Ian Romanick66a55482005-06-21 23:42:43 +0000243def real_function_name(element):
244 name = element.nsProp( "name", None )
245 alias = element.nsProp( "alias", None )
246
247 if alias:
248 return alias
249 else:
250 return name
251
252
Ian Romanick5aafea02005-06-24 18:35:31 +0000253def real_category_name(c):
254 if re.compile("[1-9][0-9]*[.][0-9]+").match(c):
255 return "GL_VERSION_" + c.replace(".", "_")
256 else:
257 return c
258
259
Ian Romanickf0ff50d2005-07-02 08:29:57 +0000260def create_parameter_string(parameters, include_names):
Ian Romanick5aafea02005-06-24 18:35:31 +0000261 """Create a parameter string from a list of gl_parameters."""
262
263 list = []
264 for p in parameters:
Ian Romanickf0ff50d2005-07-02 08:29:57 +0000265 if include_names:
266 list.append( p.string() )
267 else:
268 list.append( p.type_string() )
Ian Romanick5aafea02005-06-24 18:35:31 +0000269
270 if len(list) == 0: list = ["void"]
271
272 return string.join(list, ", ")
273
274
Ian Romanick66a55482005-06-21 23:42:43 +0000275class gl_item:
276 def __init__(self, element, context):
277 self.context = context
Ian Romanick66a55482005-06-21 23:42:43 +0000278 self.name = element.nsProp( "name", None )
Ian Romanick5aafea02005-06-24 18:35:31 +0000279 self.category = real_category_name( element.parent.nsProp( "name", None ) )
Ian Romanick66a55482005-06-21 23:42:43 +0000280 return
281
282
283class gl_type( gl_item ):
284 def __init__(self, element, context):
285 gl_item.__init__(self, element, context)
286 self.size = int( element.nsProp( "size", None ), 0 )
287
288 te = typeexpr.type_expression( None )
289 tn = typeexpr.type_node()
290 tn.size = int( element.nsProp( "size", None ), 0 )
291 tn.integer = not is_attr_true( element, "float" )
292 tn.unsigned = is_attr_true( element, "unsigned" )
293 tn.name = "GL" + self.name
294 te.set_base_type_node( tn )
295
296 self.type_expr = te
297 return
298
299
300 def get_type_expression(self):
301 return self.type_expr
302
303
304class gl_enum( gl_item ):
305 def __init__(self, element, context):
306 gl_item.__init__(self, element, context)
307 self.value = int( element.nsProp( "value", None ), 0 )
308
309 temp = element.nsProp( "count", None )
310 if not temp or temp == "?":
311 self.default_count = -1
312 else:
313 try:
314 c = int(temp)
315 except Exception,e:
316 raise RuntimeError('Invalid count value "%s" for enum "%s" in function "%s" when an integer was expected.' % (temp, self.name, n))
317
318 self.default_count = c
319
320 return
321
322
323 def priority(self):
324 """Calculate a 'priority' for this enum name.
325
326 When an enum is looked up by number, there may be many
327 possible names, but only one is the 'prefered' name. The
328 priority is used to select which name is the 'best'.
329
330 Highest precedence is given to core GL name. ARB extension
331 names have the next highest, followed by EXT extension names.
332 Vendor extension names are the lowest.
333 """
334
335 if self.name.endswith( "_BIT" ):
336 bias = 1
337 else:
338 bias = 0
339
340 if self.category.startswith( "GL_VERSION_" ):
341 priority = 0
342 elif self.category.startswith( "GL_ARB_" ):
343 priority = 2
344 elif self.category.startswith( "GL_EXT_" ):
345 priority = 4
346 else:
347 priority = 6
348
349 return priority + bias
350
351
352
353class gl_parameter:
354 def __init__(self, element, context):
355 self.name = element.nsProp( "name", None )
356
357 ts = element.nsProp( "type", None )
358 self.type_expr = typeexpr.type_expression( ts, context )
359
360 temp = element.nsProp( "variable_param", None )
361 if temp:
362 self.count_parameter_list = temp.split( ' ' )
363 else:
364 self.count_parameter_list = []
365
366 # The count tag can be either a numeric string or the name of
367 # a variable. If it is the name of a variable, the int(c)
368 # statement will throw an exception, and the except block will
369 # take over.
370
371 c = element.nsProp( "count", None )
372 try:
373 count = int(c)
374 self.count = count
375 self.counter = None
376 except Exception,e:
377 count = 1
378 self.count = 0
379 self.counter = c
380
381 self.count_scale = int(element.nsProp( "count_scale", None ))
382
383 elements = (count * self.count_scale)
384 if elements == 1:
385 elements = 0
386
387 #if ts == "GLdouble":
388 # print '/* stack size -> %s = %u (before)*/' % (self.name, self.type_expr.get_stack_size())
389 # print '/* # elements = %u */' % (elements)
390 self.type_expr.set_elements( elements )
391 #if ts == "GLdouble":
392 # print '/* stack size -> %s = %u (after) */' % (self.name, self.type_expr.get_stack_size())
393
394 self.is_counter = is_attr_true( element, 'counter' )
395 self.is_output = is_attr_true( element, 'output' )
396
397
398 # Pixel data has special parameters.
399
400 self.width = element.nsProp('img_width', None)
401 self.height = element.nsProp('img_height', None)
402 self.depth = element.nsProp('img_depth', None)
403 self.extent = element.nsProp('img_extent', None)
404
405 self.img_xoff = element.nsProp('img_xoff', None)
406 self.img_yoff = element.nsProp('img_yoff', None)
407 self.img_zoff = element.nsProp('img_zoff', None)
408 self.img_woff = element.nsProp('img_woff', None)
409
410 self.img_format = element.nsProp('img_format', None)
411 self.img_type = element.nsProp('img_type', None)
412 self.img_target = element.nsProp('img_target', None)
413
414 self.img_pad_dimensions = is_attr_true( element, 'img_pad_dimensions' )
415 self.img_null_flag = is_attr_true( element, 'img_null_flag' )
416 self.img_send_null = is_attr_true( element, 'img_send_null' )
417
418 return
419
420
421 def compatible(self, other):
422 return 1
423
424
425 def is_array(self):
426 return self.is_pointer()
427
428
429 def is_pointer(self):
430 return self.type_expr.is_pointer()
431
432
433 def is_image(self):
434 if self.width:
435 return 1
436 else:
437 return 0
438
439
440 def is_variable_length(self):
441 return len(self.count_parameter_list) or self.counter
442
443
444 def is_64_bit(self):
445 count = self.type_expr.get_element_count()
446 if count:
447 if (self.size() / count) == 8:
448 return 1
449 else:
450 if self.size() == 8:
451 return 1
452
453 return 0
454
455
456 def string(self):
457 return self.type_expr.original_string + " " + self.name
458
459
460 def type_string(self):
461 return self.type_expr.original_string
462
463
464 def get_base_type_string(self):
465 return self.type_expr.get_base_name()
466
467
468 def get_dimensions(self):
469 if not self.width:
470 return [ 0, "0", "0", "0", "0" ]
471
472 dim = 1
473 w = self.width
474 h = "1"
475 d = "1"
476 e = "1"
477
478 if self.height:
479 dim = 2
480 h = self.height
481
482 if self.depth:
483 dim = 3
484 d = self.depth
485
486 if self.extent:
487 dim = 4
488 e = self.extent
489
490 return [ dim, w, h, d, e ]
491
492
493 def get_stack_size(self):
494 return self.type_expr.get_stack_size()
495
496
497 def size(self):
498 if self.is_image():
499 return 0
500 else:
501 return self.type_expr.get_element_size()
502
503
504 def get_element_count(self):
505 c = self.type_expr.get_element_count()
506 if c == 0:
507 return 1
508
509 return c
510
511
512 def size_string(self, use_parens = 1):
513 s = self.size()
514 if self.counter or self.count_parameter_list:
515 list = [ "compsize" ]
516
517 if self.counter and self.count_parameter_list:
518 list.append( self.counter )
519 elif self.counter:
520 list = [ self.counter ]
521
522 if s > 1:
523 list.append( str(s) )
524
525 if len(list) > 1 and use_parens :
526 return "(%s)" % (string.join(list, " * "))
527 else:
528 return string.join(list, " * ")
529
530 elif self.is_image():
531 return "compsize"
532 else:
533 return str(s)
534
535
536 def format_string(self):
537 if self.type_expr.original_string == "GLenum":
538 return "0x%x"
539 else:
540 return self.type_expr.format_string()
541
542
543
544class gl_function( gl_item ):
545 def __init__(self, element, context):
546 self.context = context
547 self.name = None
548
549 self.entry_points = []
550 self.return_type = "void"
551 self.parameters = []
552 self.offset = -1
Ian Romanick5aafea02005-06-24 18:35:31 +0000553 self.initialized = 0
Ian Romanick66a55482005-06-21 23:42:43 +0000554 self.images = []
555
Ian Romanick5aafea02005-06-24 18:35:31 +0000556 # Track the parameter string (for the function prototype)
557 # for each entry-point. This is done because some functions
558 # change their prototype slightly when promoted from extension
559 # to ARB extension to core. glTexImage3DEXT and glTexImage3D
560 # are good examples of this. Scripts that need to generate
561 # code for these differing aliases need to real prototype
562 # for each entry-point. Otherwise, they may generate code
563 # that won't compile.
564
565 self.parameter_strings = {}
566
Ian Romanick66a55482005-06-21 23:42:43 +0000567 self.process_element( element )
568
569 return
570
571
572 def process_element(self, element):
573 name = element.nsProp( "name", None )
574 alias = element.nsProp( "alias", None )
575
576 self.entry_points.append( name )
577 if alias:
578 true_name = alias
579 else:
580 true_name = name
581
582 # Only try to set the offset when a non-alias
583 # entry-point is being processes.
584
585 offset = element.nsProp( "offset", None )
586 if offset:
587 try:
588 o = int( offset )
589 self.offset = o
590 except Exception, e:
591 self.offset = -1
592
593
594 if not self.name:
595 self.name = true_name
596 elif self.name != true_name:
597 raise RuntimeError("Function true name redefined. Was %s, now %s." % (self.name, true_name))
598
599
600 # There are two possible cases. The first time an entry-point
Ian Romanick5aafea02005-06-24 18:35:31 +0000601 # with data is seen, self.initialized will be 0. On that
Ian Romanick66a55482005-06-21 23:42:43 +0000602 # pass, we just fill in the data. The next time an
Ian Romanick5aafea02005-06-24 18:35:31 +0000603 # entry-point with data is seen, self.initialized will be 1.
Ian Romanick66a55482005-06-21 23:42:43 +0000604 # On that pass we have to make that the new values match the
605 # valuse from the previous entry-point.
606
Ian Romanick5aafea02005-06-24 18:35:31 +0000607 parameters = []
608 return_type = "void"
Ian Romanick66a55482005-06-21 23:42:43 +0000609 child = element.children
Ian Romanick5aafea02005-06-24 18:35:31 +0000610 while child:
611 if child.type == "element":
612 if child.name == "return":
613 return_type = child.nsProp( "type", None )
614 elif child.name == "param":
615 param = self.context.factory.create_item( "parameter", child, self.context)
616 parameters.append( param )
Ian Romanick66a55482005-06-21 23:42:43 +0000617
Ian Romanick5aafea02005-06-24 18:35:31 +0000618 child = child.next
Ian Romanick66a55482005-06-21 23:42:43 +0000619
Ian Romanick5aafea02005-06-24 18:35:31 +0000620
621 if self.initialized:
622 if self.return_type != return_type:
623 raise RuntimeError( "Return type changed in %s. Was %s, now %s." % (name, self.return_type, return_type))
Ian Romanick66a55482005-06-21 23:42:43 +0000624
625 if len(parameters) != len(self.parameters):
626 raise RuntimeError( "Parameter count mismatch in %s. Was %d, now %d." % (name, len(self.parameters), len(parameters)))
627
628 for j in range(0, len(parameters)):
629 p1 = parameters[j]
630 p2 = self.parameters[j]
631 if not p1.compatible( p2 ):
632 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))
633
634
Ian Romanick5aafea02005-06-24 18:35:31 +0000635 if true_name == name or not self.initialized:
636 self.return_type = return_type
637 self.parameters = parameters
Ian Romanick66a55482005-06-21 23:42:43 +0000638
Ian Romanick66a55482005-06-21 23:42:43 +0000639 for param in self.parameters:
640 if param.is_image():
641 self.images.append( param )
642
643 if element.children:
Ian Romanick5aafea02005-06-24 18:35:31 +0000644 self.initialized = 1
Ian Romanickf0ff50d2005-07-02 08:29:57 +0000645 self.parameter_strings[name] = create_parameter_string(parameters, 1)
Ian Romanick5aafea02005-06-24 18:35:31 +0000646 else:
647 self.parameter_strings[name] = None
Ian Romanick66a55482005-06-21 23:42:43 +0000648
649 return
650
651
652 def get_images(self):
653 """Return potentially empty list of input images."""
654 return self.images
655
656
657 def parameterIterator(self):
658 return self.parameters.__iter__();
659
660
Ian Romanick5aafea02005-06-24 18:35:31 +0000661 def get_parameter_string(self, entrypoint = None):
662 if entrypoint:
663 s = self.parameter_strings[ entrypoint ]
664 if s:
665 return s
666
Ian Romanickf0ff50d2005-07-02 08:29:57 +0000667 return create_parameter_string( self.parameters, 1 )
Ian Romanick66a55482005-06-21 23:42:43 +0000668
669
670class gl_item_factory:
671 """Factory to create objects derived from gl_item."""
672
673 def create_item(self, item_name, element, context):
674 if item_name == "function":
675 return gl_function(element, context)
676 if item_name == "type":
677 return gl_type(element, context)
678 elif item_name == "enum":
679 return gl_enum(element, context)
680 elif item_name == "parameter":
681 return gl_parameter(element, context)
682 elif item_name == "api":
683 return gl_api(self)
684 else:
685 return None
686
687
688class gl_api:
689 def __init__(self, factory):
690 self.functions_by_name = {}
691 self.enums_by_name = {}
692 self.types_by_name = {}
693 self.category_dict = {}
694
695 self.factory = factory
696
697 typeexpr.create_initial_types()
698 return
699
700
701 def process_element(self, doc):
702 element = doc.children
703 while element.type != "element" or element.name != "OpenGLAPI":
704 element = element.next
705
706 if element:
707 self.process_OpenGLAPI(element)
708 return
709
710
711 def process_OpenGLAPI(self, element):
712 child = element.children
713 while child:
714 if child.type == "element":
715 if child.name == "category":
716 self.process_category( child )
717 elif child.name == "OpenGLAPI":
718 self.process_OpenGLAPI( child )
719
720 child = child.next
721
722 return
723
724
725 def process_category(self, cat):
726 cat_name = cat.nsProp( "name", None )
727 cat_number = cat.nsProp( "number", None )
728
729 child = cat.children
730 while child:
731 if child.type == "element":
732 if child.name == "function":
733 func_name = real_function_name( child )
734
Ian Romanick5aafea02005-06-24 18:35:31 +0000735 temp_name = child.nsProp( "name", None )
736 self.category_dict[ temp_name ] = [cat_name, cat_number]
737
Ian Romanick66a55482005-06-21 23:42:43 +0000738 if self.functions_by_name.has_key( func_name ):
739 func = self.functions_by_name[ func_name ]
740 func.process_element( child )
741 else:
742 func = self.factory.create_item( "function", child, self )
743 self.functions_by_name[ func_name ] = func
744
Ian Romanick66a55482005-06-21 23:42:43 +0000745
746 elif child.name == "enum":
747 enum = self.factory.create_item( "enum", child, self )
748 self.enums_by_name[ enum.name ] = enum
749 elif child.name == "type":
750 t = self.factory.create_item( "type", child, self )
751 self.types_by_name[ "GL" + t.name ] = t
752
753
754 child = child.next
755
756 return
757
758
759 def functionIterateByOffset(self):
760 max_offset = -1
761 for func in self.functions_by_name.itervalues():
762 if func.offset > max_offset:
763 max_offset = func.offset
764
765
766 temp = [None for i in range(0, max_offset + 1)]
767 for func in self.functions_by_name.itervalues():
768 if func.offset != -1:
769 temp[ func.offset ] = func
770
771
772 list = []
773 for i in range(0, max_offset + 1):
774 if temp[i]:
775 list.append(temp[i])
776
777 return list.__iter__();
778
779
780 def functionIterateAll(self):
781 return self.functions_by_name.itervalues()
782
783
784 def enumIterateByName(self):
785 keys = self.enums_by_name.keys()
786 keys.sort()
787
788 list = []
789 for enum in keys:
790 list.append( self.enums_by_name[ enum ] )
791
792 return list.__iter__()
793
794
795 def get_category_for_name( self, name ):
796 if self.category_dict.has_key(name):
797 return self.category_dict[name]
798 else:
799 return ["<unknown category>", None]
800
801
802 def typeIterate(self):
803 return self.types_by_name.itervalues()
804
805
806 def find_type( self, type_name ):
807 if type_name in self.types_by_name:
808 return self.types_by_name[ type_name ].type_expr
809 else:
810 print "Unable to find base type matching \"%s\"." % (type_name)
811 return None