blob: 3f87a5712a34c7f3136b86b9fed693f55980aded [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."
532 functions = {}
533 next_alias = -2
534 types = {}
535 xref = {}
536 current_object = None
537 factory = None
538 current_category = ""
539
540 def __init__(self):
541 saxutils.XMLFilterBase.__init__(self)
542 self.functions = {}
543 self.types = {}
544 self.xref = {}
545 self.factory = glItemFactory()
Ian Romanick16c3c742005-01-28 19:00:54 +0000546 self.header_tag = None
Ian Romanickc2803582005-02-01 00:28:47 +0000547 self.undef_list = []
Ian Romanick73f59b02004-05-18 18:33:40 +0000548
Ian Romanicka9d033c2004-05-19 23:33:08 +0000549
Ian Romanick73f59b02004-05-18 18:33:40 +0000550 def find_type(self,type_name):
551 for t in self.types:
552 if re.compile(t).search(type_name):
553 return self.types[t]
554 print "Unable to find base type matching \"%s\"." % (type_name)
555 return None
556
Ian Romanicka9d033c2004-05-19 23:33:08 +0000557
Ian Romanick73f59b02004-05-18 18:33:40 +0000558 def find_function(self,function_name):
559 index = self.xref[function_name]
560 return self.functions[index]
561
Ian Romanicka9d033c2004-05-19 23:33:08 +0000562
Ian Romanick38e6e092005-01-25 23:53:13 +0000563 def functionIterator(self):
564 return glFunctionIterator(self)
565
566
Ian Romanick73f59b02004-05-18 18:33:40 +0000567 def printFunctions(self):
Ian Romanick38e6e092005-01-25 23:53:13 +0000568 for f in self.functionIterator():
569 self.printFunction(f)
Ian Romanick73f59b02004-05-18 18:33:40 +0000570 return
571
Ian Romanicka9d033c2004-05-19 23:33:08 +0000572
Ian Romanick73f59b02004-05-18 18:33:40 +0000573 def printHeader(self):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000574 """Print the header associated with all files and call the printRealHeader method."""
575
Ian Romanick73f59b02004-05-18 18:33:40 +0000576 print '/* DO NOT EDIT - This file generated automatically by %s script */' \
577 % (self.name)
578 print ''
579 print '/*'
580 print ' * ' + self.license.replace('\n', '\n * ')
581 print ' */'
582 print ''
Ian Romanick16c3c742005-01-28 19:00:54 +0000583 if self.header_tag:
584 print '#if !defined( %s )' % (self.header_tag)
585 print '# define %s' % (self.header_tag)
586 print ''
Ian Romanick73f59b02004-05-18 18:33:40 +0000587 self.printRealHeader();
588 return
589
Ian Romanicka9d033c2004-05-19 23:33:08 +0000590
Ian Romanick73f59b02004-05-18 18:33:40 +0000591 def printFooter(self):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000592 """Print the header associated with all files and call the printRealFooter method."""
593
Ian Romanick73f59b02004-05-18 18:33:40 +0000594 self.printFunctions()
595 self.printRealFooter()
Ian Romanick16c3c742005-01-28 19:00:54 +0000596 if self.header_tag:
Ian Romanickc2803582005-02-01 00:28:47 +0000597 if self.undef_list:
598 print ''
599 for u in self.undef_list:
600 print "# undef %s" % (u)
601 print ''
602 print '#endif /* !defined( %s ) */' % (self.header_tag)
Ian Romanick73f59b02004-05-18 18:33:40 +0000603
604
605 def get_category_define(self):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000606 """Convert the category name to the #define that would be found in glext.h"""
607
Ian Romanick73f59b02004-05-18 18:33:40 +0000608 if re.compile("[1-9][0-9]*[.][0-9]+").match(self.current_category):
609 s = self.current_category
610 return "GL_VERSION_" + s.replace(".", "_")
611 else:
612 return self.current_category
613
614
615 def append(self, object_type, obj):
616 if object_type == "function":
617 # If the function is not an alias and has a negative
618 # offset, then we do not need to track it. These are
619 # functions that don't have an assigned offset
620
621 if obj.fn_offset >= 0 or obj.fn_alias != None:
622 if obj.fn_offset >= 0:
623 index = obj.fn_offset
624 else:
625 index = self.next_alias
626 self.next_alias -= 1
627
628 self.functions[index] = obj
629 self.xref[obj.name] = index
630 elif object_type == "type":
631 self.types[obj.name] = obj
632
633 return
634
635
636 def startElement(self, name, attrs):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000637 """Start a new element in the XML stream.
638
639 Starts a new element. There are three types of elements that
640 are specially handled by this function. When a "category"
641 element is encountered, the name of the category is saved.
642 If an element is encountered and no API object is
643 in-progress, a new object is created using the API factory.
644 Any future elements, until that API object is closed, are
645 passed to the current objects startElement method.
646
647 This paradigm was chosen becuase it allows subclasses of the
648 basic API types (i.e., glFunction, glEnum, etc.) to handle
649 additional XML data, GLX protocol information, that the base
650 classes do not know about."""
651
Ian Romanick73f59b02004-05-18 18:33:40 +0000652 if self.current_object != None:
653 self.current_object.startElement(name, attrs)
654 elif name == "category":
655 self.current_category = attrs.get('name', "")
Ian Romanick6cfd4f72005-02-08 02:11:14 +0000656 elif name == "include":
657 self.next_include = attrs.get('name', "")
Ian Romanick73f59b02004-05-18 18:33:40 +0000658 else:
659 self.current_object = self.factory.create(self, name, attrs)
660 return
661
Ian Romanicka9d033c2004-05-19 23:33:08 +0000662
Ian Romanick73f59b02004-05-18 18:33:40 +0000663 def endElement(self, name):
664 if self.current_object != None:
665 if self.current_object.endElement(name):
666 self.current_object = None
Ian Romanick6cfd4f72005-02-08 02:11:14 +0000667 elif name == "include":
668 parser = make_parser()
669 parser.setFeature(feature_namespaces, 0)
670 parser.setContentHandler(self)
671
672 f = open(self.next_include)
673 parser.parse(f)
674
Ian Romanick73f59b02004-05-18 18:33:40 +0000675 return
676
Ian Romanicka9d033c2004-05-19 23:33:08 +0000677
Ian Romanickc2803582005-02-01 00:28:47 +0000678 def printPure(self):
679 self.undef_list.append("PURE")
680 print """# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
681# define PURE __attribute__((pure))
682# else
683# define PURE
684# endif"""
685
686 def printFastcall(self):
687 self.undef_list.append("FASTCALL")
688 print """# if defined(__i386__) && defined(__GNUC__)
689# define FASTCALL __attribute__((fastcall))
690# else
691# define FASTCALL
692# endif"""
693
694 def printVisibility(self, S, s):
695 self.undef_list.append(S)
696 print """# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
697# define %s __attribute__((visibility("%s")))
698# else
699# define %s
700# endif""" % (S, s, S)
701
702 def printNoinline(self):
703 self.undef_list.append("NOINLINE")
704 print """# if defined(__GNUC__)
705# define NOINLINE __attribute__((noinline))
706# else
707# define NOINLINE
708# endif"""
709
710 def printHaveAlias(self):
711 self.undef_list.append("HAVE_ALIAS")
712 print """# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
713# define HAVE_ALIAS
714# endif"""
715
Ian Romanick73f59b02004-05-18 18:33:40 +0000716 def printFunction(self,offset):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000717 """Print a single function.
718
719 In the base class, this function is empty. All derived
720 classes should over-ride this function."""
Ian Romanick73f59b02004-05-18 18:33:40 +0000721 return
722
Ian Romanicka9d033c2004-05-19 23:33:08 +0000723
Ian Romanick73f59b02004-05-18 18:33:40 +0000724 def printRealHeader(self):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000725 """Print the "real" header for the created file.
726
727 In the base class, this function is empty. All derived
728 classes should over-ride this function."""
Ian Romanick73f59b02004-05-18 18:33:40 +0000729 return
730
Ian Romanicka9d033c2004-05-19 23:33:08 +0000731
Ian Romanick73f59b02004-05-18 18:33:40 +0000732 def printRealFooter(self):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000733 """Print the "real" footer for the created file.
734
735 In the base class, this function is empty. All derived
736 classes should over-ride this function."""
Ian Romanick73f59b02004-05-18 18:33:40 +0000737 return