blob: 1c4e734f85fd72ef84b28a4077394a41fbdf1ef2 [file] [log] [blame]
Ian Romanick73f59b02004-05-18 18:33:40 +00001#!/usr/bin/python2
2
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
28from xml.sax import saxutils
29from xml.sax import make_parser
30from xml.sax.handler import feature_namespaces
31
Brian Paul98fa2bf2004-10-28 21:11:02 +000032import re
Ian Romanick73f59b02004-05-18 18:33:40 +000033
34class glItem:
35 """Generic class on which all other API entity types are based."""
36
Ian Romanick73f59b02004-05-18 18:33:40 +000037 def __init__(self, tag_name, name, context):
38 self.name = name
39 self.category = context.get_category_define()
40 self.context = context
41 self.tag_name = tag_name
42
43 context.append(tag_name, self)
44 return
45
46 def startElement(self, name, attrs):
Ian Romanicka9d033c2004-05-19 23:33:08 +000047 """Generic startElement handler.
48
49 The startElement handler is called for all elements except
50 the one that starts the object. For a foo element, the
51 XML "<foo><bar/></foo>" would cause the startElement handler
52 to be called once, but the endElement handler would be called
53 twice."""
Ian Romanick73f59b02004-05-18 18:33:40 +000054 return
55
56 def endElement(self, name):
57 """Generic endElement handler.
58
59 Generic endElement handler. Returns 1 if the tag containing
60 the object is complete. Otherwise 0 is returned. All
61 derived class endElement handlers should call this method. If
62 the name of the ending tag is the same as the tag that
63 started this object, the object is assumed to be complete.
64
65 This fails if a tag can contain another tag with the same
66 name. The XML "<foo><foo/><bar/></foo>" would fail. The
Ian Romanicka9d033c2004-05-19 23:33:08 +000067 object would end before the bar tag was processed.
68
69 The endElement handler is called for every end element
70 associated with an object, even the element that started the
71 object. See the description of startElement an example."""
Ian Romanick73f59b02004-05-18 18:33:40 +000072
73 if name == self.tag_name:
74 return 1
75 else:
76 return 0
Ian Romanick73f59b02004-05-18 18:33:40 +000077
Ian Romanicka9d033c2004-05-19 23:33:08 +000078 def get_category_define(self):
79 return self.category
80
Ian Romanick73f59b02004-05-18 18:33:40 +000081
82class glEnum( glItem ):
Ian Romanicka9d033c2004-05-19 23:33:08 +000083 """Subclass of glItem for representing GL enumerants.
84
85 This class is not complete, and is not really used yet."""
86
Ian Romanick73f59b02004-05-18 18:33:40 +000087 def __init__(self, context, name, attrs):
88 self.value = int(attrs.get('value', "0x0000"), 0)
Ian Romanick73f59b02004-05-18 18:33:40 +000089
90 enum_name = "GL_" + attrs.get('name', None)
91 glItem.__init__(self, name, enum_name, context)
92
Ian Romanick85f0fa32005-01-25 01:20:11 +000093 temp = attrs.get('count', None)
94 if temp == None:
95 self.default_count = 0
96 else:
97 try:
98 c = int(temp)
99 except Exception,e:
100 raise RuntimeError('Invalid count value "%s" for enum "%s" in function "%s" when an integer was expected.' % (temp, self.name, n))
101
102 self.default_count = c
103 return
104
Ian Romanick73f59b02004-05-18 18:33:40 +0000105
Ian Romanick5ff2b942005-01-24 21:29:13 +0000106 def process_attributes(self, attrs):
107 name = attrs.get('name', None)
108
109 temp = attrs.get('count', None)
Ian Romanick85f0fa32005-01-25 01:20:11 +0000110 if temp == None:
111 c = self.default_count
112 else:
113 try:
114 c = int(temp)
115 except Exception,e:
116 raise RuntimeError('Invalid count value "%s" for enum "%s" in function "%s" when an integer was expected.' % (temp, self.name, n))
Ian Romanick5ff2b942005-01-24 21:29:13 +0000117
Ian Romanick85f0fa32005-01-25 01:20:11 +0000118 mode_str = attrs.get('mode', "set")
119 if mode_str == "set":
120 mode = 1
121 elif mode_str == "get":
122 mode = 0
123 else:
124 raise RuntimeError("Invalid mode '%s' for function '%s' in enum '%s'." % (mode_str, self.context.name, self.name))
125
126 return [name, c, mode]
Ian Romanick73f59b02004-05-18 18:33:40 +0000127
128
129class glType( glItem ):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000130 """Subclass of glItem for representing GL types."""
131
Ian Romanick73f59b02004-05-18 18:33:40 +0000132 def __init__(self, context, name, attrs):
133 self.size = int(attrs.get('size', "0"))
Ian Romanicka285acb2005-01-07 03:22:56 +0000134 self.glx_name = attrs.get('glx_name', "")
Ian Romanick73f59b02004-05-18 18:33:40 +0000135
136 type_name = "GL" + attrs.get('name', None)
137 glItem.__init__(self, name, type_name, context)
138
139
Ian Romanicka9d033c2004-05-19 23:33:08 +0000140class glParameter( glItem ):
141 """Parameter of a glFunction."""
Ian Romanick73f59b02004-05-18 18:33:40 +0000142 p_type = None
143 p_type_string = ""
Ian Romanick73f59b02004-05-18 18:33:40 +0000144 p_count = 0
Ian Romanick73f59b02004-05-18 18:33:40 +0000145 counter = None
146 is_output = 0
147 is_counter = 0
148 is_pointer = 0
149
Ian Romanicka9d033c2004-05-19 23:33:08 +0000150 def __init__(self, context, name, attrs):
151 p_name = attrs.get('name', None)
152 self.p_type_string = attrs.get('type', None)
Ian Romanick73f59b02004-05-18 18:33:40 +0000153
Ian Romanick3fec8c22005-02-02 00:54:45 +0000154 temp = attrs.get('variable_param', None)
155 if temp:
156 self.count_parameter_list = temp.replace( ' ', '' ).split( ',' )
Ian Romanickba09c192005-02-01 00:13:04 +0000157 else:
158 self.count_parameter_list = []
159
Ian Romanicka9d033c2004-05-19 23:33:08 +0000160 self.p_type = context.context.find_type(self.p_type_string)
161 if self.p_type == None:
162 raise RuntimeError("Unknown type '%s' in function '%s'." % (self.p_type_string, context.name))
163
164
165 # The count tag can be either a numeric string or the name of
166 # a variable. If it is the name of a variable, the int(c)
167 # statement will throw an exception, and the except block will
168 # take over.
169
170 c = attrs.get('count', "0")
Ian Romanick73f59b02004-05-18 18:33:40 +0000171 try:
172 self.p_count = int(c)
Ian Romanicka9d033c2004-05-19 23:33:08 +0000173 self.counter = None
Ian Romanick73f59b02004-05-18 18:33:40 +0000174 except Exception,e:
175 self.p_count = 0
176 self.counter = c
177
Ian Romanick0bd53732005-03-06 08:55:39 +0000178 self.count_scale = int(attrs.get('count_scale', "1"))
179
Ian Romanicka9d033c2004-05-19 23:33:08 +0000180 if attrs.get('counter', "false") == "true":
181 self.is_counter = 1
182 else:
183 self.is_counter = 0
184
185 if attrs.get('output', "false") == "true":
Ian Romanick73f59b02004-05-18 18:33:40 +0000186 self.is_output = 1
187 else:
188 self.is_output = 0
189
Ian Romanick5f1f2292005-01-07 02:39:09 +0000190
191 # Pixel data has special parameters.
192
193 self.width = attrs.get('img_width', None)
194 self.height = attrs.get('img_height', None)
195 self.depth = attrs.get('img_depth', None)
196 self.extent = attrs.get('img_extent', None)
197
198 self.img_xoff = attrs.get('img_xoff', None)
199 self.img_yoff = attrs.get('img_yoff', None)
200 self.img_zoff = attrs.get('img_zoff', None)
201 self.img_woff = attrs.get('img_woff', None)
202
203 self.img_format = attrs.get('img_format', None)
204 self.img_type = attrs.get('img_type', None)
205 self.img_target = attrs.get('img_target', None)
206
207 pad = attrs.get('img_pad_dimensions', "false")
208 if pad == "true":
209 self.img_pad_dimensions = 1
210 else:
211 self.img_pad_dimensions = 0
212
213
214 null_flag = attrs.get('img_null_flag', "false")
215 if null_flag == "true":
216 self.img_null_flag = 1
217 else:
218 self.img_null_flag = 0
219
220 send_null = attrs.get('img_send_null', "false")
221 if send_null == "true":
222 self.img_send_null = 1
223 else:
224 self.img_send_null = 0
225
226
227
Ian Romanick3fec8c22005-02-02 00:54:45 +0000228 if self.p_count > 0 or self.counter or self.count_parameter_list:
Ian Romanick73f59b02004-05-18 18:33:40 +0000229 has_count = 1
230 else:
231 has_count = 0
232
Ian Romanicka9d033c2004-05-19 23:33:08 +0000233
Ian Romanick73f59b02004-05-18 18:33:40 +0000234 # If there is a * anywhere in the parameter's type, then it
235 # is a pointer.
236
Ian Romanicka9d033c2004-05-19 23:33:08 +0000237 if re.compile("[*]").search(self.p_type_string):
Ian Romanick73f59b02004-05-18 18:33:40 +0000238 # We could do some other validation here. For
239 # example, an output parameter should not be const,
240 # but every non-output parameter should.
241
242 self.is_pointer = 1;
243 else:
244 # If a parameter is not a pointer, then there cannot
245 # be an associated count (either fixed size or
246 # variable) and the parameter cannot be an output.
247
248 if has_count or self.is_output:
249 raise RuntimeError("Non-pointer type has count or is output.")
250 self.is_pointer = 0;
251
Ian Romanicka9d033c2004-05-19 23:33:08 +0000252 glItem.__init__(self, name, p_name, context)
253 return
254
255
Ian Romanick73f59b02004-05-18 18:33:40 +0000256 def is_variable_length_array(self):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000257 """Determine if a parameter is a variable length array.
258
259 A parameter is considered to be a variable length array if
260 its size depends on the value of another parameter that is
261 an enumerant. The params parameter to glTexEnviv is an
262 example of a variable length array parameter. Arrays whose
263 size depends on a count variable, such as the lists parameter
264 to glCallLists, are not variable length arrays in this
265 sense."""
266
Ian Romanick3fec8c22005-02-02 00:54:45 +0000267 return self.count_parameter_list or self.counter or self.width
Ian Romanick73f59b02004-05-18 18:33:40 +0000268
Ian Romanicka9d033c2004-05-19 23:33:08 +0000269
Ian Romanick73f59b02004-05-18 18:33:40 +0000270 def is_array(self):
271 return self.is_pointer
272
Ian Romanicka9d033c2004-05-19 23:33:08 +0000273
Ian Romanick73f59b02004-05-18 18:33:40 +0000274 def count_string(self):
275 """Return a string representing the number of items
276
277 Returns a string representing the number of items in a
278 parameter. For scalar types this will always be "1". For
279 vector types, it will depend on whether or not it is a
280 fixed length vector (like the parameter of glVertex3fv),
281 a counted length (like the vector parameter of
282 glDeleteTextures), or a general variable length vector."""
283
284 if self.is_array():
Ian Romanick3fec8c22005-02-02 00:54:45 +0000285 if self.count_parameter_list:
Ian Romanick73f59b02004-05-18 18:33:40 +0000286 return "compsize"
287 elif self.counter != None:
288 return self.counter
289 else:
290 return str(self.p_count)
291 else:
292 return "1"
293
Ian Romanicka9d033c2004-05-19 23:33:08 +0000294
Ian Romanick73f59b02004-05-18 18:33:40 +0000295 def size(self):
Ian Romanick3fec8c22005-02-02 00:54:45 +0000296 if self.count_parameter_list or self.counter or self.width or self.is_output:
Ian Romanick73f59b02004-05-18 18:33:40 +0000297 return 0
298 elif self.p_count == 0:
299 return self.p_type.size
300 else:
Ian Romanick0bd53732005-03-06 08:55:39 +0000301 return self.p_type.size * self.p_count * self.count_scale
Ian Romanick73f59b02004-05-18 18:33:40 +0000302
Ian Romanick4f0a75e2004-12-01 00:29:48 +0000303 def size_string(self):
304 s = self.size()
305 if s == 0:
306 a_prod = "compsize"
307 b_prod = self.p_type.size
308
Ian Romanickba09c192005-02-01 00:13:04 +0000309 # Handle functions like glCompressedTexImage2D that
310 # have a counted 'void *' parameter.
311
312 if b_prod == 0: b_prod = 1
313
Ian Romanick3fec8c22005-02-02 00:54:45 +0000314 if not self.count_parameter_list and self.counter != None:
Ian Romanick0bd53732005-03-06 08:55:39 +0000315 if self.count_scale > 1:
316 a_prod = '(%s * %u)' % (self.counter, self.count_scale)
317 else:
318 a_prod = self.counter
Ian Romanick3fec8c22005-02-02 00:54:45 +0000319 elif self.count_parameter_list and self.counter == None:
Ian Romanick4f0a75e2004-12-01 00:29:48 +0000320 pass
Ian Romanick3fec8c22005-02-02 00:54:45 +0000321 elif self.count_parameter_list and self.counter != None:
Ian Romanick0bd53732005-03-06 08:55:39 +0000322 if self.count_scale > 1:
323 b_prod = '(%s * %u)' % (self.counter, self.count_scale)
324 else:
325 b_prod = self.counter
Ian Romanick5f1f2292005-01-07 02:39:09 +0000326 elif self.width:
327 return "compsize"
Ian Romanick4f0a75e2004-12-01 00:29:48 +0000328 else:
329 raise RuntimeError("Parameter '%s' to function '%s' has size 0." % (self.name, self.context.name))
330
331 return "(%s * %s)" % (a_prod, b_prod)
332 else:
333 return str(s)
334
Ian Romanicka9d033c2004-05-19 23:33:08 +0000335
Ian Romanick73f59b02004-05-18 18:33:40 +0000336class glParameterIterator:
Ian Romanicka9d033c2004-05-19 23:33:08 +0000337 """Class to iterate over a list of glParameters.
338
Ian Romanick1d270842004-12-21 21:26:36 +0000339 Objects of this class are returned by the parameterIterator method of
340 the glFunction class. They are used to iterate over the list of
Ian Romanicka9d033c2004-05-19 23:33:08 +0000341 parameters to the function."""
342
Ian Romanick73f59b02004-05-18 18:33:40 +0000343 def __init__(self, data):
344 self.data = data
345 self.index = 0
Ian Romanick1d270842004-12-21 21:26:36 +0000346
347 def __iter__(self):
348 return self
349
Ian Romanick73f59b02004-05-18 18:33:40 +0000350 def next(self):
351 if self.index == len( self.data ):
352 raise StopIteration
353 i = self.index
354 self.index += 1
355 return self.data[i]
356
Ian Romanicka9d033c2004-05-19 23:33:08 +0000357
Ian Romanick73f59b02004-05-18 18:33:40 +0000358class glFunction( glItem ):
Ian Romanick73f59b02004-05-18 18:33:40 +0000359 def __init__(self, context, name, attrs):
360 self.fn_alias = attrs.get('alias', None)
361 self.fn_parameters = []
Ian Romanick5f1f2292005-01-07 02:39:09 +0000362 self.image = None
Ian Romanickba09c192005-02-01 00:13:04 +0000363 self.count_parameter_list = []
Ian Romanick3fec8c22005-02-02 00:54:45 +0000364 self.fn_return_type = "void"
Ian Romanick73f59b02004-05-18 18:33:40 +0000365
366 temp = attrs.get('offset', None)
367 if temp == None or temp == "?":
368 self.fn_offset = -1
369 else:
370 self.fn_offset = int(temp)
371
372 fn_name = attrs.get('name', None)
373 if self.fn_alias != None:
374 self.real_name = self.fn_alias
375 else:
376 self.real_name = fn_name
377
Ian Romanickce77d372005-03-03 21:21:59 +0000378 self.parameters_by_name = {}
379 self.variable_length_parameters = []
380
Ian Romanick73f59b02004-05-18 18:33:40 +0000381 glItem.__init__(self, name, fn_name, context)
382 return
383
384
Ian Romanick1d270842004-12-21 21:26:36 +0000385 def parameterIterator(self):
Ian Romanick73f59b02004-05-18 18:33:40 +0000386 return glParameterIterator(self.fn_parameters)
387
388
389 def startElement(self, name, attrs):
390 if name == "param":
Ian Romanick73f59b02004-05-18 18:33:40 +0000391 try:
Ian Romanick4f0a75e2004-12-01 00:29:48 +0000392 self.context.factory.create(self, name, attrs)
Ian Romanick73f59b02004-05-18 18:33:40 +0000393 except RuntimeError:
394 print "Error with parameter '%s' in function '%s'." \
Ian Romanicka9d033c2004-05-19 23:33:08 +0000395 % (attrs.get('name','(unknown)'), self.name)
Ian Romanick73f59b02004-05-18 18:33:40 +0000396 raise
Ian Romanick73f59b02004-05-18 18:33:40 +0000397 elif name == "return":
398 self.set_return_type(attrs.get('type', None))
399
400
Ian Romanickce77d372005-03-03 21:21:59 +0000401 def endElement(self, name):
402 """Handle the end of a <function> element.
403
404 At the end of a <function> element, there is some semantic
405 checking that can be done. This prevents some possible
406 exceptions from being thrown elsewhere in the code.
407 """
408
409 if name == "function":
410 for p in self.variable_length_parameters:
411 if p.counter:
412 counter = self.parameters_by_name[ p.counter ]
413 if not self.parameters_by_name.has_key( p.counter ):
414 raise RuntimeError("Parameter '%s' of function '%s' has counter '%s', but function has no such parameter." % (p.name, self.name, p.counter))
415 elif not self.parameters_by_name[ p.counter ].is_counter:
416 raise RuntimeError("Parameter '%s' of function '%s' has counter '%s', but '%s' is not marked as a counter." % (p.name, self.name, p.counter, p.counter))
417
418 for n in p.count_parameter_list:
419 if not self.parameters_by_name.has_key( n ):
420 raise RuntimeError("Parameter '%s' of function '%s' has size parameter '%s', but function has no such parameter." % (p.name, self.name, n))
421
422 return 1
423 else:
424 return 0
425
426
Ian Romanicka9d033c2004-05-19 23:33:08 +0000427 def append(self, tag_name, p):
428 if tag_name != "param":
429 raise RuntimeError("Trying to append '%s' to parameter list of function '%s'." % (tag_name, self.name))
430
Ian Romanick5f1f2292005-01-07 02:39:09 +0000431 if p.width:
432 self.image = p
433
Ian Romanick73f59b02004-05-18 18:33:40 +0000434 self.fn_parameters.append(p)
Ian Romanickba09c192005-02-01 00:13:04 +0000435 if p.count_parameter_list != []:
436 self.count_parameter_list.extend( p.count_parameter_list )
Ian Romanick73f59b02004-05-18 18:33:40 +0000437
Ian Romanickce77d372005-03-03 21:21:59 +0000438 if p.is_variable_length_array():
439 self.variable_length_parameters.append(p)
440
441 self.parameters_by_name[ p.name ] = p
442
Ian Romanicka9d033c2004-05-19 23:33:08 +0000443
Ian Romanick73f59b02004-05-18 18:33:40 +0000444 def set_return_type(self, t):
445 self.fn_return_type = t
446
Ian Romanicka9d033c2004-05-19 23:33:08 +0000447
Ian Romanick73f59b02004-05-18 18:33:40 +0000448 def get_parameter_string(self):
449 arg_string = ""
450 comma = ""
Ian Romanick1d270842004-12-21 21:26:36 +0000451 for p in glFunction.parameterIterator(self):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000452 arg_string = arg_string + comma + p.p_type_string + " " + p.name
Ian Romanick73f59b02004-05-18 18:33:40 +0000453 comma = ", "
454
455 if arg_string == "":
456 arg_string = "void"
457
458 return arg_string
459
460
461class glItemFactory:
462 """Factory to create objects derived from glItem."""
463
464 def create(self, context, name, attrs):
465 if name == "function":
466 return glFunction(context, name, attrs)
467 elif name == "type":
468 return glType(context, name, attrs)
469 elif name == "enum":
470 return glEnum(context, name, attrs)
Ian Romanick4f0a75e2004-12-01 00:29:48 +0000471 elif name == "param":
472 return glParameter(context, name, attrs)
Ian Romanick73f59b02004-05-18 18:33:40 +0000473 else:
474 return None
475
476
Ian Romanick38e6e092005-01-25 23:53:13 +0000477class glFunctionIterator:
478 """Class to iterate over a list of glFunctions
479
480 Objects of this classare returned by
481 FilterGLAPISpecBase::functionIterator. This default version
482 iterates over the functions in order of dispatch table offset. All
483 of the "true" functions are iterated first, followed by the alias
484 functions."""
485
486 def __init__(self, context):
487 self.context = context
488 self.keys = context.functions.keys()
489 self.keys.sort()
490
491 self.prevk = -1
492 self.direction = 1
493
494 for self.index in range(0, len(self.keys)):
495 if self.keys[ self.index ] >= 0: break
496
497 if self.index == len(self.keys):
498 self.direction = -1
499 self.index -= 1
500
501 self.split = self.index - 1
502 return
503
504
505 def __iter__(self):
506 return self
507
508
509 def next(self):
510 if self.index < 0:
511 raise StopIteration
512
513 k = self.keys[ self.index ]
514
515 #if self.context.functions[k].fn_alias == None:
516 # if k != self.prevk + 1:
517 # print 'Missing offset %d' % (prevk)
518 # self.prevk = int(k)
519
520 self.index += self.direction
521
522 if self.index == len(self.keys):
523 self.index = self.split
524 self.direction = -1
525
526 return self.context.functions[k]
527
528
Ian Romanick73f59b02004-05-18 18:33:40 +0000529class FilterGLAPISpecBase(saxutils.XMLFilterBase):
530 name = "a"
531 license = "The license for this file is unspecified."
Ian Romanick73f59b02004-05-18 18:33:40 +0000532 next_alias = -2
Ian Romanick73f59b02004-05-18 18:33:40 +0000533 current_object = None
Ian Romanick73f59b02004-05-18 18:33:40 +0000534
535 def __init__(self):
536 saxutils.XMLFilterBase.__init__(self)
537 self.functions = {}
538 self.types = {}
Ian Romanick6af6a692005-03-17 20:56:13 +0000539 self.functions_by_name = {}
Ian Romanick73f59b02004-05-18 18:33:40 +0000540 self.factory = glItemFactory()
Ian Romanick16c3c742005-01-28 19:00:54 +0000541 self.header_tag = None
Ian Romanickc2803582005-02-01 00:28:47 +0000542 self.undef_list = []
Ian Romanick6af6a692005-03-17 20:56:13 +0000543 self.current_category = ""
Ian Romanick73f59b02004-05-18 18:33:40 +0000544
Ian Romanicka9d033c2004-05-19 23:33:08 +0000545
Ian Romanick73f59b02004-05-18 18:33:40 +0000546 def find_type(self,type_name):
547 for t in self.types:
548 if re.compile(t).search(type_name):
549 return self.types[t]
550 print "Unable to find base type matching \"%s\"." % (type_name)
551 return None
552
Ian Romanicka9d033c2004-05-19 23:33:08 +0000553
Ian Romanick73f59b02004-05-18 18:33:40 +0000554 def find_function(self,function_name):
Ian Romanick6af6a692005-03-17 20:56:13 +0000555 return self.functions_by_name[function_name]
Ian Romanick73f59b02004-05-18 18:33:40 +0000556
Ian Romanicka9d033c2004-05-19 23:33:08 +0000557
Ian Romanick38e6e092005-01-25 23:53:13 +0000558 def functionIterator(self):
559 return glFunctionIterator(self)
560
561
Ian Romanick73f59b02004-05-18 18:33:40 +0000562 def printFunctions(self):
Ian Romanick38e6e092005-01-25 23:53:13 +0000563 for f in self.functionIterator():
564 self.printFunction(f)
Ian Romanick73f59b02004-05-18 18:33:40 +0000565 return
566
Ian Romanicka9d033c2004-05-19 23:33:08 +0000567
Ian Romanick73f59b02004-05-18 18:33:40 +0000568 def printHeader(self):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000569 """Print the header associated with all files and call the printRealHeader method."""
570
Ian Romanick73f59b02004-05-18 18:33:40 +0000571 print '/* DO NOT EDIT - This file generated automatically by %s script */' \
572 % (self.name)
573 print ''
574 print '/*'
575 print ' * ' + self.license.replace('\n', '\n * ')
576 print ' */'
577 print ''
Ian Romanick16c3c742005-01-28 19:00:54 +0000578 if self.header_tag:
579 print '#if !defined( %s )' % (self.header_tag)
580 print '# define %s' % (self.header_tag)
581 print ''
Ian Romanick73f59b02004-05-18 18:33:40 +0000582 self.printRealHeader();
583 return
584
Ian Romanicka9d033c2004-05-19 23:33:08 +0000585
Ian Romanick73f59b02004-05-18 18:33:40 +0000586 def printFooter(self):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000587 """Print the header associated with all files and call the printRealFooter method."""
588
Ian Romanick73f59b02004-05-18 18:33:40 +0000589 self.printFunctions()
590 self.printRealFooter()
Ian Romanick16c3c742005-01-28 19:00:54 +0000591 if self.header_tag:
Ian Romanickc2803582005-02-01 00:28:47 +0000592 if self.undef_list:
593 print ''
594 for u in self.undef_list:
595 print "# undef %s" % (u)
596 print ''
597 print '#endif /* !defined( %s ) */' % (self.header_tag)
Ian Romanick73f59b02004-05-18 18:33:40 +0000598
599
600 def get_category_define(self):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000601 """Convert the category name to the #define that would be found in glext.h"""
602
Ian Romanick73f59b02004-05-18 18:33:40 +0000603 if re.compile("[1-9][0-9]*[.][0-9]+").match(self.current_category):
604 s = self.current_category
605 return "GL_VERSION_" + s.replace(".", "_")
606 else:
607 return self.current_category
608
609
610 def append(self, object_type, obj):
611 if object_type == "function":
612 # If the function is not an alias and has a negative
613 # offset, then we do not need to track it. These are
614 # functions that don't have an assigned offset
615
616 if obj.fn_offset >= 0 or obj.fn_alias != None:
617 if obj.fn_offset >= 0:
618 index = obj.fn_offset
619 else:
620 index = self.next_alias
621 self.next_alias -= 1
622
623 self.functions[index] = obj
Ian Romanick6af6a692005-03-17 20:56:13 +0000624
625 self.functions_by_name[obj.name] = obj
626
Ian Romanick73f59b02004-05-18 18:33:40 +0000627 elif object_type == "type":
628 self.types[obj.name] = obj
629
630 return
631
632
633 def startElement(self, name, attrs):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000634 """Start a new element in the XML stream.
635
636 Starts a new element. There are three types of elements that
637 are specially handled by this function. When a "category"
638 element is encountered, the name of the category is saved.
639 If an element is encountered and no API object is
640 in-progress, a new object is created using the API factory.
641 Any future elements, until that API object is closed, are
642 passed to the current objects startElement method.
643
644 This paradigm was chosen becuase it allows subclasses of the
645 basic API types (i.e., glFunction, glEnum, etc.) to handle
646 additional XML data, GLX protocol information, that the base
647 classes do not know about."""
648
Ian Romanick73f59b02004-05-18 18:33:40 +0000649 if self.current_object != None:
650 self.current_object.startElement(name, attrs)
651 elif name == "category":
652 self.current_category = attrs.get('name', "")
Ian Romanick6cfd4f72005-02-08 02:11:14 +0000653 elif name == "include":
654 self.next_include = attrs.get('name', "")
Ian Romanick73f59b02004-05-18 18:33:40 +0000655 else:
656 self.current_object = self.factory.create(self, name, attrs)
657 return
658
Ian Romanicka9d033c2004-05-19 23:33:08 +0000659
Ian Romanick73f59b02004-05-18 18:33:40 +0000660 def endElement(self, name):
661 if self.current_object != None:
662 if self.current_object.endElement(name):
663 self.current_object = None
Ian Romanick6cfd4f72005-02-08 02:11:14 +0000664 elif name == "include":
665 parser = make_parser()
666 parser.setFeature(feature_namespaces, 0)
667 parser.setContentHandler(self)
668
669 f = open(self.next_include)
670 parser.parse(f)
671
Ian Romanick73f59b02004-05-18 18:33:40 +0000672 return
673
Ian Romanicka9d033c2004-05-19 23:33:08 +0000674
Ian Romanickc2803582005-02-01 00:28:47 +0000675 def printPure(self):
676 self.undef_list.append("PURE")
677 print """# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
678# define PURE __attribute__((pure))
679# else
680# define PURE
681# endif"""
682
683 def printFastcall(self):
684 self.undef_list.append("FASTCALL")
685 print """# if defined(__i386__) && defined(__GNUC__)
686# define FASTCALL __attribute__((fastcall))
687# else
688# define FASTCALL
689# endif"""
690
691 def printVisibility(self, S, s):
692 self.undef_list.append(S)
693 print """# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
694# define %s __attribute__((visibility("%s")))
695# else
696# define %s
697# endif""" % (S, s, S)
698
699 def printNoinline(self):
700 self.undef_list.append("NOINLINE")
701 print """# if defined(__GNUC__)
702# define NOINLINE __attribute__((noinline))
703# else
704# define NOINLINE
705# endif"""
706
707 def printHaveAlias(self):
708 self.undef_list.append("HAVE_ALIAS")
709 print """# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
710# define HAVE_ALIAS
711# endif"""
712
Ian Romanick73f59b02004-05-18 18:33:40 +0000713 def printFunction(self,offset):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000714 """Print a single function.
715
716 In the base class, this function is empty. All derived
717 classes should over-ride this function."""
Ian Romanick73f59b02004-05-18 18:33:40 +0000718 return
719
Ian Romanicka9d033c2004-05-19 23:33:08 +0000720
Ian Romanick73f59b02004-05-18 18:33:40 +0000721 def printRealHeader(self):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000722 """Print the "real" header for the created file.
723
724 In the base class, this function is empty. All derived
725 classes should over-ride this function."""
Ian Romanick73f59b02004-05-18 18:33:40 +0000726 return
727
Ian Romanicka9d033c2004-05-19 23:33:08 +0000728
Ian Romanick73f59b02004-05-18 18:33:40 +0000729 def printRealFooter(self):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000730 """Print the "real" footer for the created file.
731
732 In the base class, this function is empty. All derived
733 classes should over-ride this function."""
Ian Romanick73f59b02004-05-18 18:33:40 +0000734 return