blob: 651bd7369b34581f777fb062fb44523be06252c6 [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
Ian Romanickf0ff50d2005-07-02 08:29:57 +0000279def create_parameter_string(parameters, include_names):
Ian Romanick5aafea02005-06-24 18:35:31 +0000280 """Create a parameter string from a list of gl_parameters."""
281
282 list = []
283 for p in parameters:
Ian Romanickf0ff50d2005-07-02 08:29:57 +0000284 if include_names:
285 list.append( p.string() )
286 else:
287 list.append( p.type_string() )
Ian Romanick5aafea02005-06-24 18:35:31 +0000288
289 if len(list) == 0: list = ["void"]
290
291 return string.join(list, ", ")
292
293
Ian Romanick66a55482005-06-21 23:42:43 +0000294class gl_item:
295 def __init__(self, element, context):
296 self.context = context
Ian Romanick66a55482005-06-21 23:42:43 +0000297 self.name = element.nsProp( "name", None )
Ian Romanick5aafea02005-06-24 18:35:31 +0000298 self.category = real_category_name( element.parent.nsProp( "name", None ) )
Ian Romanick66a55482005-06-21 23:42:43 +0000299 return
300
301
302class gl_type( gl_item ):
303 def __init__(self, element, context):
304 gl_item.__init__(self, element, context)
305 self.size = int( element.nsProp( "size", None ), 0 )
306
307 te = typeexpr.type_expression( None )
308 tn = typeexpr.type_node()
309 tn.size = int( element.nsProp( "size", None ), 0 )
310 tn.integer = not is_attr_true( element, "float" )
311 tn.unsigned = is_attr_true( element, "unsigned" )
312 tn.name = "GL" + self.name
313 te.set_base_type_node( tn )
314
315 self.type_expr = te
316 return
317
318
319 def get_type_expression(self):
320 return self.type_expr
321
322
323class gl_enum( gl_item ):
324 def __init__(self, element, context):
325 gl_item.__init__(self, element, context)
326 self.value = int( element.nsProp( "value", None ), 0 )
327
328 temp = element.nsProp( "count", None )
329 if not temp or temp == "?":
330 self.default_count = -1
331 else:
332 try:
333 c = int(temp)
334 except Exception,e:
335 raise RuntimeError('Invalid count value "%s" for enum "%s" in function "%s" when an integer was expected.' % (temp, self.name, n))
336
337 self.default_count = c
338
339 return
340
341
342 def priority(self):
343 """Calculate a 'priority' for this enum name.
344
345 When an enum is looked up by number, there may be many
346 possible names, but only one is the 'prefered' name. The
347 priority is used to select which name is the 'best'.
348
349 Highest precedence is given to core GL name. ARB extension
350 names have the next highest, followed by EXT extension names.
351 Vendor extension names are the lowest.
352 """
353
354 if self.name.endswith( "_BIT" ):
355 bias = 1
356 else:
357 bias = 0
358
359 if self.category.startswith( "GL_VERSION_" ):
360 priority = 0
361 elif self.category.startswith( "GL_ARB_" ):
362 priority = 2
363 elif self.category.startswith( "GL_EXT_" ):
364 priority = 4
365 else:
366 priority = 6
367
368 return priority + bias
369
370
371
372class gl_parameter:
373 def __init__(self, element, context):
374 self.name = element.nsProp( "name", None )
375
376 ts = element.nsProp( "type", None )
377 self.type_expr = typeexpr.type_expression( ts, context )
378
379 temp = element.nsProp( "variable_param", None )
380 if temp:
381 self.count_parameter_list = temp.split( ' ' )
382 else:
383 self.count_parameter_list = []
384
385 # The count tag can be either a numeric string or the name of
386 # a variable. If it is the name of a variable, the int(c)
387 # statement will throw an exception, and the except block will
388 # take over.
389
390 c = element.nsProp( "count", None )
391 try:
392 count = int(c)
393 self.count = count
394 self.counter = None
395 except Exception,e:
396 count = 1
397 self.count = 0
398 self.counter = c
399
400 self.count_scale = int(element.nsProp( "count_scale", None ))
401
402 elements = (count * self.count_scale)
403 if elements == 1:
404 elements = 0
405
406 #if ts == "GLdouble":
407 # print '/* stack size -> %s = %u (before)*/' % (self.name, self.type_expr.get_stack_size())
408 # print '/* # elements = %u */' % (elements)
409 self.type_expr.set_elements( elements )
410 #if ts == "GLdouble":
411 # print '/* stack size -> %s = %u (after) */' % (self.name, self.type_expr.get_stack_size())
412
413 self.is_counter = is_attr_true( element, 'counter' )
414 self.is_output = is_attr_true( element, 'output' )
415
416
417 # Pixel data has special parameters.
418
419 self.width = element.nsProp('img_width', None)
420 self.height = element.nsProp('img_height', None)
421 self.depth = element.nsProp('img_depth', None)
422 self.extent = element.nsProp('img_extent', None)
423
424 self.img_xoff = element.nsProp('img_xoff', None)
425 self.img_yoff = element.nsProp('img_yoff', None)
426 self.img_zoff = element.nsProp('img_zoff', None)
427 self.img_woff = element.nsProp('img_woff', None)
428
429 self.img_format = element.nsProp('img_format', None)
430 self.img_type = element.nsProp('img_type', None)
431 self.img_target = element.nsProp('img_target', None)
432
433 self.img_pad_dimensions = is_attr_true( element, 'img_pad_dimensions' )
434 self.img_null_flag = is_attr_true( element, 'img_null_flag' )
435 self.img_send_null = is_attr_true( element, 'img_send_null' )
436
437 return
438
439
440 def compatible(self, other):
441 return 1
442
443
444 def is_array(self):
445 return self.is_pointer()
446
447
448 def is_pointer(self):
449 return self.type_expr.is_pointer()
450
451
452 def is_image(self):
453 if self.width:
454 return 1
455 else:
456 return 0
457
458
459 def is_variable_length(self):
460 return len(self.count_parameter_list) or self.counter
461
462
463 def is_64_bit(self):
464 count = self.type_expr.get_element_count()
465 if count:
466 if (self.size() / count) == 8:
467 return 1
468 else:
469 if self.size() == 8:
470 return 1
471
472 return 0
473
474
475 def string(self):
476 return self.type_expr.original_string + " " + self.name
477
478
479 def type_string(self):
480 return self.type_expr.original_string
481
482
483 def get_base_type_string(self):
484 return self.type_expr.get_base_name()
485
486
487 def get_dimensions(self):
488 if not self.width:
489 return [ 0, "0", "0", "0", "0" ]
490
491 dim = 1
492 w = self.width
493 h = "1"
494 d = "1"
495 e = "1"
496
497 if self.height:
498 dim = 2
499 h = self.height
500
501 if self.depth:
502 dim = 3
503 d = self.depth
504
505 if self.extent:
506 dim = 4
507 e = self.extent
508
509 return [ dim, w, h, d, e ]
510
511
512 def get_stack_size(self):
513 return self.type_expr.get_stack_size()
514
515
516 def size(self):
517 if self.is_image():
518 return 0
519 else:
520 return self.type_expr.get_element_size()
521
522
523 def get_element_count(self):
524 c = self.type_expr.get_element_count()
525 if c == 0:
526 return 1
527
528 return c
529
530
531 def size_string(self, use_parens = 1):
532 s = self.size()
533 if self.counter or self.count_parameter_list:
534 list = [ "compsize" ]
535
536 if self.counter and self.count_parameter_list:
537 list.append( self.counter )
538 elif self.counter:
539 list = [ self.counter ]
540
541 if s > 1:
542 list.append( str(s) )
543
544 if len(list) > 1 and use_parens :
545 return "(%s)" % (string.join(list, " * "))
546 else:
547 return string.join(list, " * ")
548
549 elif self.is_image():
550 return "compsize"
551 else:
552 return str(s)
553
554
555 def format_string(self):
556 if self.type_expr.original_string == "GLenum":
557 return "0x%x"
558 else:
559 return self.type_expr.format_string()
560
561
562
563class gl_function( gl_item ):
564 def __init__(self, element, context):
565 self.context = context
566 self.name = None
567
568 self.entry_points = []
569 self.return_type = "void"
570 self.parameters = []
571 self.offset = -1
Ian Romanick5aafea02005-06-24 18:35:31 +0000572 self.initialized = 0
Ian Romanick66a55482005-06-21 23:42:43 +0000573 self.images = []
574
Ian Romanick5aafea02005-06-24 18:35:31 +0000575 # Track the parameter string (for the function prototype)
576 # for each entry-point. This is done because some functions
577 # change their prototype slightly when promoted from extension
578 # to ARB extension to core. glTexImage3DEXT and glTexImage3D
579 # are good examples of this. Scripts that need to generate
580 # code for these differing aliases need to real prototype
581 # for each entry-point. Otherwise, they may generate code
582 # that won't compile.
583
584 self.parameter_strings = {}
585
Ian Romanick66a55482005-06-21 23:42:43 +0000586 self.process_element( element )
587
588 return
589
590
591 def process_element(self, element):
592 name = element.nsProp( "name", None )
593 alias = element.nsProp( "alias", None )
594
595 self.entry_points.append( name )
596 if alias:
597 true_name = alias
598 else:
599 true_name = name
600
601 # Only try to set the offset when a non-alias
602 # entry-point is being processes.
603
604 offset = element.nsProp( "offset", None )
605 if offset:
606 try:
607 o = int( offset )
608 self.offset = o
609 except Exception, e:
610 self.offset = -1
611
612
613 if not self.name:
614 self.name = true_name
615 elif self.name != true_name:
616 raise RuntimeError("Function true name redefined. Was %s, now %s." % (self.name, true_name))
617
618
619 # There are two possible cases. The first time an entry-point
Ian Romanick5aafea02005-06-24 18:35:31 +0000620 # with data is seen, self.initialized will be 0. On that
Ian Romanick66a55482005-06-21 23:42:43 +0000621 # pass, we just fill in the data. The next time an
Ian Romanick5aafea02005-06-24 18:35:31 +0000622 # entry-point with data is seen, self.initialized will be 1.
Ian Romanick66a55482005-06-21 23:42:43 +0000623 # On that pass we have to make that the new values match the
624 # valuse from the previous entry-point.
625
Ian Romanick5aafea02005-06-24 18:35:31 +0000626 parameters = []
627 return_type = "void"
Ian Romanick66a55482005-06-21 23:42:43 +0000628 child = element.children
Ian Romanick5aafea02005-06-24 18:35:31 +0000629 while child:
630 if child.type == "element":
631 if child.name == "return":
632 return_type = child.nsProp( "type", None )
633 elif child.name == "param":
634 param = self.context.factory.create_item( "parameter", child, self.context)
635 parameters.append( param )
Ian Romanick66a55482005-06-21 23:42:43 +0000636
Ian Romanick5aafea02005-06-24 18:35:31 +0000637 child = child.next
Ian Romanick66a55482005-06-21 23:42:43 +0000638
Ian Romanick5aafea02005-06-24 18:35:31 +0000639
640 if self.initialized:
641 if self.return_type != return_type:
642 raise RuntimeError( "Return type changed in %s. Was %s, now %s." % (name, self.return_type, return_type))
Ian Romanick66a55482005-06-21 23:42:43 +0000643
644 if len(parameters) != len(self.parameters):
645 raise RuntimeError( "Parameter count mismatch in %s. Was %d, now %d." % (name, len(self.parameters), len(parameters)))
646
647 for j in range(0, len(parameters)):
648 p1 = parameters[j]
649 p2 = self.parameters[j]
650 if not p1.compatible( p2 ):
651 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))
652
653
Ian Romanick5aafea02005-06-24 18:35:31 +0000654 if true_name == name or not self.initialized:
655 self.return_type = return_type
656 self.parameters = parameters
Ian Romanick66a55482005-06-21 23:42:43 +0000657
Ian Romanick66a55482005-06-21 23:42:43 +0000658 for param in self.parameters:
659 if param.is_image():
660 self.images.append( param )
661
662 if element.children:
Ian Romanick5aafea02005-06-24 18:35:31 +0000663 self.initialized = 1
Ian Romanickf0ff50d2005-07-02 08:29:57 +0000664 self.parameter_strings[name] = create_parameter_string(parameters, 1)
Ian Romanick5aafea02005-06-24 18:35:31 +0000665 else:
666 self.parameter_strings[name] = None
Ian Romanick66a55482005-06-21 23:42:43 +0000667
668 return
669
670
671 def get_images(self):
672 """Return potentially empty list of input images."""
673 return self.images
674
675
676 def parameterIterator(self):
677 return self.parameters.__iter__();
678
679
Ian Romanick5aafea02005-06-24 18:35:31 +0000680 def get_parameter_string(self, entrypoint = None):
681 if entrypoint:
682 s = self.parameter_strings[ entrypoint ]
683 if s:
684 return s
685
Ian Romanickf0ff50d2005-07-02 08:29:57 +0000686 return create_parameter_string( self.parameters, 1 )
Ian Romanick66a55482005-06-21 23:42:43 +0000687
688
689class gl_item_factory:
690 """Factory to create objects derived from gl_item."""
691
692 def create_item(self, item_name, element, context):
693 if item_name == "function":
694 return gl_function(element, context)
695 if item_name == "type":
696 return gl_type(element, context)
697 elif item_name == "enum":
698 return gl_enum(element, context)
699 elif item_name == "parameter":
700 return gl_parameter(element, context)
701 elif item_name == "api":
702 return gl_api(self)
703 else:
704 return None
705
706
707class gl_api:
708 def __init__(self, factory):
709 self.functions_by_name = {}
710 self.enums_by_name = {}
711 self.types_by_name = {}
712 self.category_dict = {}
713
714 self.factory = factory
715
716 typeexpr.create_initial_types()
717 return
718
719
720 def process_element(self, doc):
721 element = doc.children
722 while element.type != "element" or element.name != "OpenGLAPI":
723 element = element.next
724
725 if element:
726 self.process_OpenGLAPI(element)
727 return
728
729
730 def process_OpenGLAPI(self, element):
731 child = element.children
732 while child:
733 if child.type == "element":
734 if child.name == "category":
735 self.process_category( child )
736 elif child.name == "OpenGLAPI":
737 self.process_OpenGLAPI( child )
738
739 child = child.next
740
741 return
742
743
744 def process_category(self, cat):
745 cat_name = cat.nsProp( "name", None )
746 cat_number = cat.nsProp( "number", None )
747
748 child = cat.children
749 while child:
750 if child.type == "element":
751 if child.name == "function":
752 func_name = real_function_name( child )
753
Ian Romanick5aafea02005-06-24 18:35:31 +0000754 temp_name = child.nsProp( "name", None )
755 self.category_dict[ temp_name ] = [cat_name, cat_number]
756
Ian Romanick66a55482005-06-21 23:42:43 +0000757 if self.functions_by_name.has_key( func_name ):
758 func = self.functions_by_name[ func_name ]
759 func.process_element( child )
760 else:
761 func = self.factory.create_item( "function", child, self )
762 self.functions_by_name[ func_name ] = func
763
Ian Romanick66a55482005-06-21 23:42:43 +0000764
765 elif child.name == "enum":
766 enum = self.factory.create_item( "enum", child, self )
767 self.enums_by_name[ enum.name ] = enum
768 elif child.name == "type":
769 t = self.factory.create_item( "type", child, self )
770 self.types_by_name[ "GL" + t.name ] = t
771
772
773 child = child.next
774
775 return
776
777
778 def functionIterateByOffset(self):
779 max_offset = -1
780 for func in self.functions_by_name.itervalues():
781 if func.offset > max_offset:
782 max_offset = func.offset
783
784
785 temp = [None for i in range(0, max_offset + 1)]
786 for func in self.functions_by_name.itervalues():
787 if func.offset != -1:
788 temp[ func.offset ] = func
789
790
791 list = []
792 for i in range(0, max_offset + 1):
793 if temp[i]:
794 list.append(temp[i])
795
796 return list.__iter__();
797
798
799 def functionIterateAll(self):
800 return self.functions_by_name.itervalues()
801
802
803 def enumIterateByName(self):
804 keys = self.enums_by_name.keys()
805 keys.sort()
806
807 list = []
808 for enum in keys:
809 list.append( self.enums_by_name[ enum ] )
810
811 return list.__iter__()
812
813
814 def get_category_for_name( self, name ):
815 if self.category_dict.has_key(name):
816 return self.category_dict[name]
817 else:
818 return ["<unknown category>", None]
819
820
821 def typeIterate(self):
822 return self.types_by_name.itervalues()
823
824
825 def find_type( self, type_name ):
826 if type_name in self.types_by_name:
827 return self.types_by_name[ type_name ].type_expr
828 else:
829 print "Unable to find base type matching \"%s\"." % (type_name)
830 return None