blob: 04890af3e543a05a5059187976233da2b1a6ed9f [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)
Ian Romanick80a939c2005-03-17 21:48:37 +000094 self.default_count = 0
95 if temp == "?":
96 self.default_count = -1
97 elif temp:
Ian Romanick85f0fa32005-01-25 01:20:11 +000098 try:
99 c = int(temp)
100 except Exception,e:
101 raise RuntimeError('Invalid count value "%s" for enum "%s" in function "%s" when an integer was expected.' % (temp, self.name, n))
102
103 self.default_count = c
104 return
105
Ian Romanick73f59b02004-05-18 18:33:40 +0000106
Ian Romanick5ff2b942005-01-24 21:29:13 +0000107 def process_attributes(self, attrs):
108 name = attrs.get('name', None)
109
110 temp = attrs.get('count', None)
Ian Romanick85f0fa32005-01-25 01:20:11 +0000111 if temp == None:
112 c = self.default_count
113 else:
114 try:
115 c = int(temp)
116 except Exception,e:
117 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 +0000118
Ian Romanick85f0fa32005-01-25 01:20:11 +0000119 mode_str = attrs.get('mode', "set")
120 if mode_str == "set":
121 mode = 1
122 elif mode_str == "get":
123 mode = 0
124 else:
125 raise RuntimeError("Invalid mode '%s' for function '%s' in enum '%s'." % (mode_str, self.context.name, self.name))
126
127 return [name, c, mode]
Ian Romanick73f59b02004-05-18 18:33:40 +0000128
129
130class glType( glItem ):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000131 """Subclass of glItem for representing GL types."""
132
Ian Romanick73f59b02004-05-18 18:33:40 +0000133 def __init__(self, context, name, attrs):
134 self.size = int(attrs.get('size', "0"))
Ian Romanicka285acb2005-01-07 03:22:56 +0000135 self.glx_name = attrs.get('glx_name', "")
Ian Romanick73f59b02004-05-18 18:33:40 +0000136
137 type_name = "GL" + attrs.get('name', None)
138 glItem.__init__(self, name, type_name, context)
139
140
Ian Romanicka9d033c2004-05-19 23:33:08 +0000141class glParameter( glItem ):
142 """Parameter of a glFunction."""
Ian Romanick73f59b02004-05-18 18:33:40 +0000143 p_type = None
144 p_type_string = ""
Ian Romanick73f59b02004-05-18 18:33:40 +0000145 p_count = 0
Ian Romanick73f59b02004-05-18 18:33:40 +0000146 counter = None
147 is_output = 0
148 is_counter = 0
149 is_pointer = 0
150
Ian Romanicka9d033c2004-05-19 23:33:08 +0000151 def __init__(self, context, name, attrs):
152 p_name = attrs.get('name', None)
153 self.p_type_string = attrs.get('type', None)
Ian Romanick73f59b02004-05-18 18:33:40 +0000154
Ian Romanick3fec8c22005-02-02 00:54:45 +0000155 temp = attrs.get('variable_param', None)
156 if temp:
157 self.count_parameter_list = temp.replace( ' ', '' ).split( ',' )
Ian Romanickba09c192005-02-01 00:13:04 +0000158 else:
159 self.count_parameter_list = []
160
Ian Romanicka9d033c2004-05-19 23:33:08 +0000161 self.p_type = context.context.find_type(self.p_type_string)
162 if self.p_type == None:
163 raise RuntimeError("Unknown type '%s' in function '%s'." % (self.p_type_string, context.name))
164
165
166 # The count tag can be either a numeric string or the name of
167 # a variable. If it is the name of a variable, the int(c)
168 # statement will throw an exception, and the except block will
169 # take over.
170
171 c = attrs.get('count', "0")
Ian Romanick73f59b02004-05-18 18:33:40 +0000172 try:
173 self.p_count = int(c)
Ian Romanicka9d033c2004-05-19 23:33:08 +0000174 self.counter = None
Ian Romanick73f59b02004-05-18 18:33:40 +0000175 except Exception,e:
176 self.p_count = 0
177 self.counter = c
178
Ian Romanick0bd53732005-03-06 08:55:39 +0000179 self.count_scale = int(attrs.get('count_scale', "1"))
180
Ian Romanicka9d033c2004-05-19 23:33:08 +0000181 if attrs.get('counter', "false") == "true":
182 self.is_counter = 1
183 else:
184 self.is_counter = 0
185
186 if attrs.get('output', "false") == "true":
Ian Romanick73f59b02004-05-18 18:33:40 +0000187 self.is_output = 1
188 else:
189 self.is_output = 0
190
Ian Romanick5f1f2292005-01-07 02:39:09 +0000191
192 # Pixel data has special parameters.
193
194 self.width = attrs.get('img_width', None)
195 self.height = attrs.get('img_height', None)
196 self.depth = attrs.get('img_depth', None)
197 self.extent = attrs.get('img_extent', None)
198
199 self.img_xoff = attrs.get('img_xoff', None)
200 self.img_yoff = attrs.get('img_yoff', None)
201 self.img_zoff = attrs.get('img_zoff', None)
202 self.img_woff = attrs.get('img_woff', None)
203
204 self.img_format = attrs.get('img_format', None)
205 self.img_type = attrs.get('img_type', None)
206 self.img_target = attrs.get('img_target', None)
207
208 pad = attrs.get('img_pad_dimensions', "false")
209 if pad == "true":
210 self.img_pad_dimensions = 1
211 else:
212 self.img_pad_dimensions = 0
213
214
215 null_flag = attrs.get('img_null_flag', "false")
216 if null_flag == "true":
217 self.img_null_flag = 1
218 else:
219 self.img_null_flag = 0
220
221 send_null = attrs.get('img_send_null', "false")
222 if send_null == "true":
223 self.img_send_null = 1
224 else:
225 self.img_send_null = 0
226
227
228
Ian Romanick3fec8c22005-02-02 00:54:45 +0000229 if self.p_count > 0 or self.counter or self.count_parameter_list:
Ian Romanick73f59b02004-05-18 18:33:40 +0000230 has_count = 1
231 else:
232 has_count = 0
233
Ian Romanicka9d033c2004-05-19 23:33:08 +0000234
Ian Romanick73f59b02004-05-18 18:33:40 +0000235 # If there is a * anywhere in the parameter's type, then it
236 # is a pointer.
237
Ian Romanicka9d033c2004-05-19 23:33:08 +0000238 if re.compile("[*]").search(self.p_type_string):
Ian Romanick73f59b02004-05-18 18:33:40 +0000239 # We could do some other validation here. For
240 # example, an output parameter should not be const,
241 # but every non-output parameter should.
242
243 self.is_pointer = 1;
244 else:
245 # If a parameter is not a pointer, then there cannot
246 # be an associated count (either fixed size or
247 # variable) and the parameter cannot be an output.
248
249 if has_count or self.is_output:
250 raise RuntimeError("Non-pointer type has count or is output.")
251 self.is_pointer = 0;
252
Ian Romanicka9d033c2004-05-19 23:33:08 +0000253 glItem.__init__(self, name, p_name, context)
254 return
255
256
Ian Romanick73f59b02004-05-18 18:33:40 +0000257 def is_variable_length_array(self):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000258 """Determine if a parameter is a variable length array.
259
260 A parameter is considered to be a variable length array if
261 its size depends on the value of another parameter that is
262 an enumerant. The params parameter to glTexEnviv is an
263 example of a variable length array parameter. Arrays whose
264 size depends on a count variable, such as the lists parameter
265 to glCallLists, are not variable length arrays in this
266 sense."""
267
Ian Romanick3fec8c22005-02-02 00:54:45 +0000268 return self.count_parameter_list or self.counter or self.width
Ian Romanick73f59b02004-05-18 18:33:40 +0000269
Ian Romanicka9d033c2004-05-19 23:33:08 +0000270
Ian Romanick73f59b02004-05-18 18:33:40 +0000271 def is_array(self):
272 return self.is_pointer
273
Ian Romanicka9d033c2004-05-19 23:33:08 +0000274
Ian Romanick73f59b02004-05-18 18:33:40 +0000275 def count_string(self):
276 """Return a string representing the number of items
277
278 Returns a string representing the number of items in a
279 parameter. For scalar types this will always be "1". For
280 vector types, it will depend on whether or not it is a
281 fixed length vector (like the parameter of glVertex3fv),
282 a counted length (like the vector parameter of
283 glDeleteTextures), or a general variable length vector."""
284
285 if self.is_array():
Ian Romanick3fec8c22005-02-02 00:54:45 +0000286 if self.count_parameter_list:
Ian Romanick73f59b02004-05-18 18:33:40 +0000287 return "compsize"
288 elif self.counter != None:
289 return self.counter
290 else:
291 return str(self.p_count)
292 else:
293 return "1"
294
Ian Romanicka9d033c2004-05-19 23:33:08 +0000295
Ian Romanick73f59b02004-05-18 18:33:40 +0000296 def size(self):
Ian Romanick3fec8c22005-02-02 00:54:45 +0000297 if self.count_parameter_list or self.counter or self.width or self.is_output:
Ian Romanick73f59b02004-05-18 18:33:40 +0000298 return 0
299 elif self.p_count == 0:
300 return self.p_type.size
301 else:
Ian Romanick0bd53732005-03-06 08:55:39 +0000302 return self.p_type.size * self.p_count * self.count_scale
Ian Romanick73f59b02004-05-18 18:33:40 +0000303
Ian Romanick4f0a75e2004-12-01 00:29:48 +0000304 def size_string(self):
305 s = self.size()
306 if s == 0:
307 a_prod = "compsize"
308 b_prod = self.p_type.size
309
Ian Romanickba09c192005-02-01 00:13:04 +0000310 # Handle functions like glCompressedTexImage2D that
311 # have a counted 'void *' parameter.
312
313 if b_prod == 0: b_prod = 1
314
Ian Romanick3fec8c22005-02-02 00:54:45 +0000315 if not self.count_parameter_list and self.counter != None:
Ian Romanick0bd53732005-03-06 08:55:39 +0000316 if self.count_scale > 1:
317 a_prod = '(%s * %u)' % (self.counter, self.count_scale)
318 else:
319 a_prod = self.counter
Ian Romanick3fec8c22005-02-02 00:54:45 +0000320 elif self.count_parameter_list and self.counter == None:
Ian Romanick4f0a75e2004-12-01 00:29:48 +0000321 pass
Ian Romanick3fec8c22005-02-02 00:54:45 +0000322 elif self.count_parameter_list and self.counter != None:
Ian Romanick0bd53732005-03-06 08:55:39 +0000323 if self.count_scale > 1:
324 b_prod = '(%s * %u)' % (self.counter, self.count_scale)
325 else:
326 b_prod = self.counter
Ian Romanick5f1f2292005-01-07 02:39:09 +0000327 elif self.width:
328 return "compsize"
Ian Romanick4f0a75e2004-12-01 00:29:48 +0000329 else:
330 raise RuntimeError("Parameter '%s' to function '%s' has size 0." % (self.name, self.context.name))
331
332 return "(%s * %s)" % (a_prod, b_prod)
333 else:
334 return str(s)
335
Ian Romanicka9d033c2004-05-19 23:33:08 +0000336
Ian Romanick73f59b02004-05-18 18:33:40 +0000337class glParameterIterator:
Ian Romanicka9d033c2004-05-19 23:33:08 +0000338 """Class to iterate over a list of glParameters.
339
Ian Romanick1d270842004-12-21 21:26:36 +0000340 Objects of this class are returned by the parameterIterator method of
341 the glFunction class. They are used to iterate over the list of
Ian Romanicka9d033c2004-05-19 23:33:08 +0000342 parameters to the function."""
343
Ian Romanick73f59b02004-05-18 18:33:40 +0000344 def __init__(self, data):
345 self.data = data
346 self.index = 0
Ian Romanick1d270842004-12-21 21:26:36 +0000347
348 def __iter__(self):
349 return self
350
Ian Romanick73f59b02004-05-18 18:33:40 +0000351 def next(self):
352 if self.index == len( self.data ):
353 raise StopIteration
354 i = self.index
355 self.index += 1
356 return self.data[i]
357
Ian Romanicka9d033c2004-05-19 23:33:08 +0000358
Ian Romanick73f59b02004-05-18 18:33:40 +0000359class glFunction( glItem ):
Ian Romanick73f59b02004-05-18 18:33:40 +0000360 def __init__(self, context, name, attrs):
361 self.fn_alias = attrs.get('alias', None)
362 self.fn_parameters = []
Ian Romanick5f1f2292005-01-07 02:39:09 +0000363 self.image = None
Ian Romanickba09c192005-02-01 00:13:04 +0000364 self.count_parameter_list = []
Ian Romanick3fec8c22005-02-02 00:54:45 +0000365 self.fn_return_type = "void"
Ian Romanick73f59b02004-05-18 18:33:40 +0000366
367 temp = attrs.get('offset', None)
368 if temp == None or temp == "?":
369 self.fn_offset = -1
370 else:
371 self.fn_offset = int(temp)
372
373 fn_name = attrs.get('name', None)
374 if self.fn_alias != None:
375 self.real_name = self.fn_alias
376 else:
377 self.real_name = fn_name
378
Ian Romanickce77d372005-03-03 21:21:59 +0000379 self.parameters_by_name = {}
380 self.variable_length_parameters = []
381
Ian Romanick73f59b02004-05-18 18:33:40 +0000382 glItem.__init__(self, name, fn_name, context)
383 return
384
385
Ian Romanick1d270842004-12-21 21:26:36 +0000386 def parameterIterator(self):
Ian Romanick73f59b02004-05-18 18:33:40 +0000387 return glParameterIterator(self.fn_parameters)
388
389
390 def startElement(self, name, attrs):
391 if name == "param":
Ian Romanick73f59b02004-05-18 18:33:40 +0000392 try:
Ian Romanick4f0a75e2004-12-01 00:29:48 +0000393 self.context.factory.create(self, name, attrs)
Ian Romanick73f59b02004-05-18 18:33:40 +0000394 except RuntimeError:
395 print "Error with parameter '%s' in function '%s'." \
Ian Romanicka9d033c2004-05-19 23:33:08 +0000396 % (attrs.get('name','(unknown)'), self.name)
Ian Romanick73f59b02004-05-18 18:33:40 +0000397 raise
Ian Romanick73f59b02004-05-18 18:33:40 +0000398 elif name == "return":
399 self.set_return_type(attrs.get('type', None))
400
401
Ian Romanickce77d372005-03-03 21:21:59 +0000402 def endElement(self, name):
403 """Handle the end of a <function> element.
404
405 At the end of a <function> element, there is some semantic
406 checking that can be done. This prevents some possible
407 exceptions from being thrown elsewhere in the code.
408 """
409
410 if name == "function":
411 for p in self.variable_length_parameters:
412 if p.counter:
413 counter = self.parameters_by_name[ p.counter ]
414 if not self.parameters_by_name.has_key( p.counter ):
415 raise RuntimeError("Parameter '%s' of function '%s' has counter '%s', but function has no such parameter." % (p.name, self.name, p.counter))
416 elif not self.parameters_by_name[ p.counter ].is_counter:
417 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))
418
419 for n in p.count_parameter_list:
420 if not self.parameters_by_name.has_key( n ):
421 raise RuntimeError("Parameter '%s' of function '%s' has size parameter '%s', but function has no such parameter." % (p.name, self.name, n))
422
423 return 1
424 else:
425 return 0
426
427
Ian Romanicka9d033c2004-05-19 23:33:08 +0000428 def append(self, tag_name, p):
429 if tag_name != "param":
430 raise RuntimeError("Trying to append '%s' to parameter list of function '%s'." % (tag_name, self.name))
431
Ian Romanick5f1f2292005-01-07 02:39:09 +0000432 if p.width:
433 self.image = p
434
Ian Romanick73f59b02004-05-18 18:33:40 +0000435 self.fn_parameters.append(p)
Ian Romanickba09c192005-02-01 00:13:04 +0000436 if p.count_parameter_list != []:
437 self.count_parameter_list.extend( p.count_parameter_list )
Ian Romanick73f59b02004-05-18 18:33:40 +0000438
Ian Romanickce77d372005-03-03 21:21:59 +0000439 if p.is_variable_length_array():
440 self.variable_length_parameters.append(p)
441
442 self.parameters_by_name[ p.name ] = p
443
Ian Romanicka9d033c2004-05-19 23:33:08 +0000444
Ian Romanick73f59b02004-05-18 18:33:40 +0000445 def set_return_type(self, t):
446 self.fn_return_type = t
447
Ian Romanicka9d033c2004-05-19 23:33:08 +0000448
Ian Romanick73f59b02004-05-18 18:33:40 +0000449 def get_parameter_string(self):
450 arg_string = ""
451 comma = ""
Ian Romanick1d270842004-12-21 21:26:36 +0000452 for p in glFunction.parameterIterator(self):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000453 arg_string = arg_string + comma + p.p_type_string + " " + p.name
Ian Romanick73f59b02004-05-18 18:33:40 +0000454 comma = ", "
455
456 if arg_string == "":
457 arg_string = "void"
458
459 return arg_string
460
461
462class glItemFactory:
463 """Factory to create objects derived from glItem."""
464
465 def create(self, context, name, attrs):
466 if name == "function":
467 return glFunction(context, name, attrs)
468 elif name == "type":
469 return glType(context, name, attrs)
470 elif name == "enum":
471 return glEnum(context, name, attrs)
Ian Romanick4f0a75e2004-12-01 00:29:48 +0000472 elif name == "param":
473 return glParameter(context, name, attrs)
Ian Romanick73f59b02004-05-18 18:33:40 +0000474 else:
475 return None
476
477
Ian Romanick38e6e092005-01-25 23:53:13 +0000478class glFunctionIterator:
479 """Class to iterate over a list of glFunctions
480
481 Objects of this classare returned by
482 FilterGLAPISpecBase::functionIterator. This default version
483 iterates over the functions in order of dispatch table offset. All
484 of the "true" functions are iterated first, followed by the alias
485 functions."""
486
487 def __init__(self, context):
488 self.context = context
489 self.keys = context.functions.keys()
490 self.keys.sort()
491
492 self.prevk = -1
493 self.direction = 1
494
495 for self.index in range(0, len(self.keys)):
496 if self.keys[ self.index ] >= 0: break
497
498 if self.index == len(self.keys):
499 self.direction = -1
500 self.index -= 1
501
502 self.split = self.index - 1
503 return
504
505
506 def __iter__(self):
507 return self
508
509
510 def next(self):
511 if self.index < 0:
512 raise StopIteration
513
514 k = self.keys[ self.index ]
515
516 #if self.context.functions[k].fn_alias == None:
517 # if k != self.prevk + 1:
518 # print 'Missing offset %d' % (prevk)
519 # self.prevk = int(k)
520
521 self.index += self.direction
522
523 if self.index == len(self.keys):
524 self.index = self.split
525 self.direction = -1
526
527 return self.context.functions[k]
528
529
Ian Romanick73f59b02004-05-18 18:33:40 +0000530class FilterGLAPISpecBase(saxutils.XMLFilterBase):
531 name = "a"
532 license = "The license for this file is unspecified."
Ian Romanick73f59b02004-05-18 18:33:40 +0000533 next_alias = -2
Ian Romanick73f59b02004-05-18 18:33:40 +0000534 current_object = None
Ian Romanick73f59b02004-05-18 18:33:40 +0000535
536 def __init__(self):
537 saxutils.XMLFilterBase.__init__(self)
538 self.functions = {}
539 self.types = {}
Ian Romanick6af6a692005-03-17 20:56:13 +0000540 self.functions_by_name = {}
Ian Romanick73f59b02004-05-18 18:33:40 +0000541 self.factory = glItemFactory()
Ian Romanick16c3c742005-01-28 19:00:54 +0000542 self.header_tag = None
Ian Romanickc2803582005-02-01 00:28:47 +0000543 self.undef_list = []
Ian Romanick6af6a692005-03-17 20:56:13 +0000544 self.current_category = ""
Ian Romanick73f59b02004-05-18 18:33:40 +0000545
Ian Romanicka9d033c2004-05-19 23:33:08 +0000546
Ian Romanick73f59b02004-05-18 18:33:40 +0000547 def find_type(self,type_name):
548 for t in self.types:
549 if re.compile(t).search(type_name):
550 return self.types[t]
551 print "Unable to find base type matching \"%s\"." % (type_name)
552 return None
553
Ian Romanicka9d033c2004-05-19 23:33:08 +0000554
Ian Romanick73f59b02004-05-18 18:33:40 +0000555 def find_function(self,function_name):
Ian Romanick6af6a692005-03-17 20:56:13 +0000556 return self.functions_by_name[function_name]
Ian Romanick73f59b02004-05-18 18:33:40 +0000557
Ian Romanicka9d033c2004-05-19 23:33:08 +0000558
Ian Romanick38e6e092005-01-25 23:53:13 +0000559 def functionIterator(self):
560 return glFunctionIterator(self)
561
562
Ian Romanick73f59b02004-05-18 18:33:40 +0000563 def printFunctions(self):
Ian Romanick38e6e092005-01-25 23:53:13 +0000564 for f in self.functionIterator():
565 self.printFunction(f)
Ian Romanick73f59b02004-05-18 18:33:40 +0000566 return
567
Ian Romanicka9d033c2004-05-19 23:33:08 +0000568
Ian Romanick73f59b02004-05-18 18:33:40 +0000569 def printHeader(self):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000570 """Print the header associated with all files and call the printRealHeader method."""
571
Ian Romanick73f59b02004-05-18 18:33:40 +0000572 print '/* DO NOT EDIT - This file generated automatically by %s script */' \
573 % (self.name)
574 print ''
575 print '/*'
576 print ' * ' + self.license.replace('\n', '\n * ')
577 print ' */'
578 print ''
Ian Romanick16c3c742005-01-28 19:00:54 +0000579 if self.header_tag:
580 print '#if !defined( %s )' % (self.header_tag)
581 print '# define %s' % (self.header_tag)
582 print ''
Ian Romanick73f59b02004-05-18 18:33:40 +0000583 self.printRealHeader();
584 return
585
Ian Romanicka9d033c2004-05-19 23:33:08 +0000586
Ian Romanick73f59b02004-05-18 18:33:40 +0000587 def printFooter(self):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000588 """Print the header associated with all files and call the printRealFooter method."""
589
Ian Romanick73f59b02004-05-18 18:33:40 +0000590 self.printFunctions()
591 self.printRealFooter()
Ian Romanick16c3c742005-01-28 19:00:54 +0000592 if self.header_tag:
Ian Romanickc2803582005-02-01 00:28:47 +0000593 if self.undef_list:
594 print ''
595 for u in self.undef_list:
596 print "# undef %s" % (u)
597 print ''
598 print '#endif /* !defined( %s ) */' % (self.header_tag)
Ian Romanick73f59b02004-05-18 18:33:40 +0000599
600
601 def get_category_define(self):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000602 """Convert the category name to the #define that would be found in glext.h"""
603
Ian Romanick73f59b02004-05-18 18:33:40 +0000604 if re.compile("[1-9][0-9]*[.][0-9]+").match(self.current_category):
605 s = self.current_category
606 return "GL_VERSION_" + s.replace(".", "_")
607 else:
608 return self.current_category
609
610
611 def append(self, object_type, obj):
612 if object_type == "function":
613 # If the function is not an alias and has a negative
614 # offset, then we do not need to track it. These are
615 # functions that don't have an assigned offset
616
617 if obj.fn_offset >= 0 or obj.fn_alias != None:
618 if obj.fn_offset >= 0:
619 index = obj.fn_offset
620 else:
621 index = self.next_alias
622 self.next_alias -= 1
623
624 self.functions[index] = obj
Ian Romanick6af6a692005-03-17 20:56:13 +0000625
626 self.functions_by_name[obj.name] = obj
627
Ian Romanick73f59b02004-05-18 18:33:40 +0000628 elif object_type == "type":
629 self.types[obj.name] = obj
630
631 return
632
633
634 def startElement(self, name, attrs):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000635 """Start a new element in the XML stream.
636
637 Starts a new element. There are three types of elements that
638 are specially handled by this function. When a "category"
639 element is encountered, the name of the category is saved.
640 If an element is encountered and no API object is
641 in-progress, a new object is created using the API factory.
642 Any future elements, until that API object is closed, are
643 passed to the current objects startElement method.
644
645 This paradigm was chosen becuase it allows subclasses of the
646 basic API types (i.e., glFunction, glEnum, etc.) to handle
647 additional XML data, GLX protocol information, that the base
648 classes do not know about."""
649
Ian Romanick73f59b02004-05-18 18:33:40 +0000650 if self.current_object != None:
651 self.current_object.startElement(name, attrs)
652 elif name == "category":
653 self.current_category = attrs.get('name', "")
Ian Romanick6cfd4f72005-02-08 02:11:14 +0000654 elif name == "include":
655 self.next_include = attrs.get('name', "")
Ian Romanick73f59b02004-05-18 18:33:40 +0000656 else:
657 self.current_object = self.factory.create(self, name, attrs)
658 return
659
Ian Romanicka9d033c2004-05-19 23:33:08 +0000660
Ian Romanick73f59b02004-05-18 18:33:40 +0000661 def endElement(self, name):
662 if self.current_object != None:
663 if self.current_object.endElement(name):
664 self.current_object = None
Ian Romanick6cfd4f72005-02-08 02:11:14 +0000665 elif name == "include":
666 parser = make_parser()
667 parser.setFeature(feature_namespaces, 0)
668 parser.setContentHandler(self)
669
670 f = open(self.next_include)
671 parser.parse(f)
672
Ian Romanick73f59b02004-05-18 18:33:40 +0000673 return
674
Ian Romanicka9d033c2004-05-19 23:33:08 +0000675
Ian Romanickc2803582005-02-01 00:28:47 +0000676 def printPure(self):
677 self.undef_list.append("PURE")
678 print """# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
679# define PURE __attribute__((pure))
680# else
681# define PURE
682# endif"""
683
684 def printFastcall(self):
685 self.undef_list.append("FASTCALL")
686 print """# if defined(__i386__) && defined(__GNUC__)
687# define FASTCALL __attribute__((fastcall))
688# else
689# define FASTCALL
690# endif"""
691
692 def printVisibility(self, S, s):
693 self.undef_list.append(S)
694 print """# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
695# define %s __attribute__((visibility("%s")))
696# else
697# define %s
698# endif""" % (S, s, S)
699
700 def printNoinline(self):
701 self.undef_list.append("NOINLINE")
702 print """# if defined(__GNUC__)
703# define NOINLINE __attribute__((noinline))
704# else
705# define NOINLINE
706# endif"""
707
708 def printHaveAlias(self):
709 self.undef_list.append("HAVE_ALIAS")
710 print """# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
711# define HAVE_ALIAS
712# endif"""
713
Ian Romanick73f59b02004-05-18 18:33:40 +0000714 def printFunction(self,offset):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000715 """Print a single function.
716
717 In the base class, this function is empty. All derived
718 classes should over-ride this function."""
Ian Romanick73f59b02004-05-18 18:33:40 +0000719 return
720
Ian Romanicka9d033c2004-05-19 23:33:08 +0000721
Ian Romanick73f59b02004-05-18 18:33:40 +0000722 def printRealHeader(self):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000723 """Print the "real" header for the created file.
724
725 In the base class, this function is empty. All derived
726 classes should over-ride this function."""
Ian Romanick73f59b02004-05-18 18:33:40 +0000727 return
728
Ian Romanicka9d033c2004-05-19 23:33:08 +0000729
Ian Romanick73f59b02004-05-18 18:33:40 +0000730 def printRealFooter(self):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000731 """Print the "real" footer for the created file.
732
733 In the base class, this function is empty. All derived
734 classes should over-ride this function."""
Ian Romanick73f59b02004-05-18 18:33:40 +0000735 return