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