blob: 38ccc53465ff69bb15c177fd4caa387e229b0bf1 [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
Ian Romanick73b4c1b2005-04-14 23:00:34 +000034def is_attr_true( attrs, name ):
35 """Read a name value from an element's attributes.
36
37 The value read from the attribute list must be either 'true' or
38 'false'. If the value is 'false', zero will be returned. If the
39 value is 'true', non-zero will be returned. An exception will be
40 raised for any other value."""
41
Ian Romanick2510ba62005-04-18 19:16:07 +000042 value = attrs.get((None, name), "false")
Ian Romanick73b4c1b2005-04-14 23:00:34 +000043 if value == "true":
44 return 1
45 elif value == "false":
46 return 0
47 else:
48 raise RuntimeError('Invalid value "%s" for boolean "%s".' % (value, name))
49
50
Ian Romanick73f59b02004-05-18 18:33:40 +000051class glItem:
52 """Generic class on which all other API entity types are based."""
53
Ian Romanick73f59b02004-05-18 18:33:40 +000054 def __init__(self, tag_name, name, context):
55 self.name = name
56 self.category = context.get_category_define()
57 self.context = context
58 self.tag_name = tag_name
59
60 context.append(tag_name, self)
61 return
62
Ian Romanick2510ba62005-04-18 19:16:07 +000063 def startElementNS(self, name, qname, attrs):
Ian Romanicka9d033c2004-05-19 23:33:08 +000064 """Generic startElement handler.
65
66 The startElement handler is called for all elements except
67 the one that starts the object. For a foo element, the
68 XML "<foo><bar/></foo>" would cause the startElement handler
69 to be called once, but the endElement handler would be called
70 twice."""
Ian Romanick73f59b02004-05-18 18:33:40 +000071 return
72
Ian Romanick2510ba62005-04-18 19:16:07 +000073 def endElementNS(self, name, qname):
Ian Romanick73f59b02004-05-18 18:33:40 +000074 """Generic endElement handler.
75
76 Generic endElement handler. Returns 1 if the tag containing
77 the object is complete. Otherwise 0 is returned. All
78 derived class endElement handlers should call this method. If
79 the name of the ending tag is the same as the tag that
80 started this object, the object is assumed to be complete.
81
82 This fails if a tag can contain another tag with the same
83 name. The XML "<foo><foo/><bar/></foo>" would fail. The
Ian Romanicka9d033c2004-05-19 23:33:08 +000084 object would end before the bar tag was processed.
85
86 The endElement handler is called for every end element
87 associated with an object, even the element that started the
88 object. See the description of startElement an example."""
Ian Romanick73f59b02004-05-18 18:33:40 +000089
Ian Romanick2510ba62005-04-18 19:16:07 +000090 if name == (None, self.tag_name):
Ian Romanick73f59b02004-05-18 18:33:40 +000091 return 1
92 else:
93 return 0
Ian Romanick73f59b02004-05-18 18:33:40 +000094
Ian Romanicka9d033c2004-05-19 23:33:08 +000095 def get_category_define(self):
96 return self.category
97
Ian Romanick73f59b02004-05-18 18:33:40 +000098
99class glEnum( glItem ):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000100 """Subclass of glItem for representing GL enumerants.
101
102 This class is not complete, and is not really used yet."""
103
Ian Romanick73f59b02004-05-18 18:33:40 +0000104 def __init__(self, context, name, attrs):
Ian Romanick2510ba62005-04-18 19:16:07 +0000105 self.value = int(attrs.get((None, 'value'), "0x0000"), 0)
Ian Romanick73f59b02004-05-18 18:33:40 +0000106
Ian Romanick2510ba62005-04-18 19:16:07 +0000107 enum_name = "GL_" + attrs.get((None, 'name'), None)
Ian Romanick73f59b02004-05-18 18:33:40 +0000108 glItem.__init__(self, name, enum_name, context)
109
Ian Romanick2510ba62005-04-18 19:16:07 +0000110 temp = attrs.get((None, 'count'), None)
Ian Romanick80a939c2005-03-17 21:48:37 +0000111 self.default_count = 0
112 if temp == "?":
113 self.default_count = -1
114 elif temp:
Ian Romanick85f0fa32005-01-25 01:20:11 +0000115 try:
116 c = int(temp)
117 except Exception,e:
118 raise RuntimeError('Invalid count value "%s" for enum "%s" in function "%s" when an integer was expected.' % (temp, self.name, n))
119
120 self.default_count = c
121 return
122
Ian Romanick73f59b02004-05-18 18:33:40 +0000123
Ian Romanick5ff2b942005-01-24 21:29:13 +0000124 def process_attributes(self, attrs):
Ian Romanick2510ba62005-04-18 19:16:07 +0000125 name = attrs.get((None, 'name'), None)
Ian Romanick5ff2b942005-01-24 21:29:13 +0000126
Ian Romanick2510ba62005-04-18 19:16:07 +0000127 temp = attrs.get((None, 'count'), None)
Ian Romanick85f0fa32005-01-25 01:20:11 +0000128 if temp == None:
129 c = self.default_count
130 else:
131 try:
132 c = int(temp)
133 except Exception,e:
134 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 +0000135
Ian Romanick2510ba62005-04-18 19:16:07 +0000136 mode_str = attrs.get((None, 'mode'), "set")
Ian Romanick85f0fa32005-01-25 01:20:11 +0000137 if mode_str == "set":
138 mode = 1
139 elif mode_str == "get":
140 mode = 0
141 else:
142 raise RuntimeError("Invalid mode '%s' for function '%s' in enum '%s'." % (mode_str, self.context.name, self.name))
143
144 return [name, c, mode]
Ian Romanick73f59b02004-05-18 18:33:40 +0000145
146
147class glType( glItem ):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000148 """Subclass of glItem for representing GL types."""
149
Ian Romanick73f59b02004-05-18 18:33:40 +0000150 def __init__(self, context, name, attrs):
Ian Romanick2510ba62005-04-18 19:16:07 +0000151 self.size = int(attrs.get((None, 'size'), "0"))
152 self.glx_name = attrs.get((None, 'glx_name'), "")
Ian Romanick73f59b02004-05-18 18:33:40 +0000153
Ian Romanick2510ba62005-04-18 19:16:07 +0000154 type_name = "GL" + attrs.get((None, 'name'), None)
Ian Romanick73f59b02004-05-18 18:33:40 +0000155 glItem.__init__(self, name, type_name, context)
156
157
Ian Romanicka9d033c2004-05-19 23:33:08 +0000158class glParameter( glItem ):
159 """Parameter of a glFunction."""
Ian Romanick73f59b02004-05-18 18:33:40 +0000160 p_type = None
161 p_type_string = ""
Ian Romanick73f59b02004-05-18 18:33:40 +0000162 p_count = 0
Ian Romanick73f59b02004-05-18 18:33:40 +0000163 counter = None
164 is_output = 0
165 is_counter = 0
166 is_pointer = 0
167
Ian Romanicka9d033c2004-05-19 23:33:08 +0000168 def __init__(self, context, name, attrs):
Ian Romanick2510ba62005-04-18 19:16:07 +0000169 p_name = attrs.get((None, 'name'), None)
170 self.p_type_string = attrs.get((None, 'type'), None)
Ian Romanick73f59b02004-05-18 18:33:40 +0000171
Ian Romanick2510ba62005-04-18 19:16:07 +0000172 temp = attrs.get((None, 'variable_param'), None)
Ian Romanick3fec8c22005-02-02 00:54:45 +0000173 if temp:
Ian Romanick067e7882005-04-14 23:03:44 +0000174 self.count_parameter_list = temp.split( ' ' )
Ian Romanickba09c192005-02-01 00:13:04 +0000175 else:
176 self.count_parameter_list = []
177
Ian Romanicka9d033c2004-05-19 23:33:08 +0000178 self.p_type = context.context.find_type(self.p_type_string)
179 if self.p_type == None:
180 raise RuntimeError("Unknown type '%s' in function '%s'." % (self.p_type_string, context.name))
181
182
183 # The count tag can be either a numeric string or the name of
184 # a variable. If it is the name of a variable, the int(c)
185 # statement will throw an exception, and the except block will
186 # take over.
187
Ian Romanick2510ba62005-04-18 19:16:07 +0000188 c = attrs.get((None, 'count'), "0")
Ian Romanick73f59b02004-05-18 18:33:40 +0000189 try:
190 self.p_count = int(c)
Ian Romanicka9d033c2004-05-19 23:33:08 +0000191 self.counter = None
Ian Romanick73f59b02004-05-18 18:33:40 +0000192 except Exception,e:
193 self.p_count = 0
194 self.counter = c
195
Ian Romanick2510ba62005-04-18 19:16:07 +0000196 self.count_scale = int(attrs.get((None, 'count_scale'), "1"))
197
Ian Romanick73b4c1b2005-04-14 23:00:34 +0000198 self.is_counter = is_attr_true( attrs, 'counter' )
199 self.is_output = is_attr_true( attrs, 'output' )
Ian Romanicka9d033c2004-05-19 23:33:08 +0000200
Ian Romanick73f59b02004-05-18 18:33:40 +0000201
Ian Romanick5f1f2292005-01-07 02:39:09 +0000202 # Pixel data has special parameters.
203
Ian Romanick2510ba62005-04-18 19:16:07 +0000204 self.width = attrs.get((None, 'img_width'), None)
205 self.height = attrs.get((None, 'img_height'), None)
206 self.depth = attrs.get((None, 'img_depth'), None)
207 self.extent = attrs.get((None, 'img_extent'), None)
Ian Romanick5f1f2292005-01-07 02:39:09 +0000208
Ian Romanick2510ba62005-04-18 19:16:07 +0000209 self.img_xoff = attrs.get((None, 'img_xoff'), None)
210 self.img_yoff = attrs.get((None, 'img_yoff'), None)
211 self.img_zoff = attrs.get((None, 'img_zoff'), None)
212 self.img_woff = attrs.get((None, 'img_woff'), None)
Ian Romanick5f1f2292005-01-07 02:39:09 +0000213
Ian Romanick2510ba62005-04-18 19:16:07 +0000214 self.img_format = attrs.get((None, 'img_format'), None)
215 self.img_type = attrs.get((None, 'img_type'), None)
216 self.img_target = attrs.get((None, 'img_target'), None)
Ian Romanick5f1f2292005-01-07 02:39:09 +0000217
Ian Romanick73b4c1b2005-04-14 23:00:34 +0000218 self.img_pad_dimensions = is_attr_true( attrs, 'img_pad_dimensions' )
219 self.img_null_flag = is_attr_true( attrs, 'img_null_flag' )
220 self.img_send_null = is_attr_true( attrs, 'img_send_null' )
Ian Romanick5f1f2292005-01-07 02:39:09 +0000221
Ian Romanick3fec8c22005-02-02 00:54:45 +0000222 if self.p_count > 0 or self.counter or self.count_parameter_list:
Ian Romanick73f59b02004-05-18 18:33:40 +0000223 has_count = 1
224 else:
225 has_count = 0
226
Ian Romanicka9d033c2004-05-19 23:33:08 +0000227
Ian Romanick73f59b02004-05-18 18:33:40 +0000228 # If there is a * anywhere in the parameter's type, then it
229 # is a pointer.
230
Ian Romanicka9d033c2004-05-19 23:33:08 +0000231 if re.compile("[*]").search(self.p_type_string):
Ian Romanick73f59b02004-05-18 18:33:40 +0000232 # We could do some other validation here. For
233 # example, an output parameter should not be const,
234 # but every non-output parameter should.
235
236 self.is_pointer = 1;
237 else:
238 # If a parameter is not a pointer, then there cannot
239 # be an associated count (either fixed size or
240 # variable) and the parameter cannot be an output.
241
242 if has_count or self.is_output:
243 raise RuntimeError("Non-pointer type has count or is output.")
244 self.is_pointer = 0;
245
Ian Romanicka9d033c2004-05-19 23:33:08 +0000246 glItem.__init__(self, name, p_name, context)
247 return
248
249
Ian Romanick73f59b02004-05-18 18:33:40 +0000250 def is_variable_length_array(self):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000251 """Determine if a parameter is a variable length array.
252
253 A parameter is considered to be a variable length array if
254 its size depends on the value of another parameter that is
255 an enumerant. The params parameter to glTexEnviv is an
256 example of a variable length array parameter. Arrays whose
257 size depends on a count variable, such as the lists parameter
258 to glCallLists, are not variable length arrays in this
259 sense."""
260
Ian Romanick3fec8c22005-02-02 00:54:45 +0000261 return self.count_parameter_list or self.counter or self.width
Ian Romanick73f59b02004-05-18 18:33:40 +0000262
Ian Romanicka9d033c2004-05-19 23:33:08 +0000263
Ian Romanick73f59b02004-05-18 18:33:40 +0000264 def is_array(self):
265 return self.is_pointer
266
Ian Romanicka9d033c2004-05-19 23:33:08 +0000267
Ian Romanick73f59b02004-05-18 18:33:40 +0000268 def count_string(self):
269 """Return a string representing the number of items
270
271 Returns a string representing the number of items in a
272 parameter. For scalar types this will always be "1". For
273 vector types, it will depend on whether or not it is a
274 fixed length vector (like the parameter of glVertex3fv),
275 a counted length (like the vector parameter of
276 glDeleteTextures), or a general variable length vector."""
277
278 if self.is_array():
Ian Romanick3fec8c22005-02-02 00:54:45 +0000279 if self.count_parameter_list:
Ian Romanick73f59b02004-05-18 18:33:40 +0000280 return "compsize"
281 elif self.counter != None:
282 return self.counter
283 else:
284 return str(self.p_count)
285 else:
286 return "1"
287
Ian Romanicka9d033c2004-05-19 23:33:08 +0000288
Ian Romanick73f59b02004-05-18 18:33:40 +0000289 def size(self):
Ian Romanick3fec8c22005-02-02 00:54:45 +0000290 if self.count_parameter_list or self.counter or self.width or self.is_output:
Ian Romanick73f59b02004-05-18 18:33:40 +0000291 return 0
292 elif self.p_count == 0:
293 return self.p_type.size
294 else:
Ian Romanick0bd53732005-03-06 08:55:39 +0000295 return self.p_type.size * self.p_count * self.count_scale
Ian Romanick73f59b02004-05-18 18:33:40 +0000296
Ian Romanick4f0a75e2004-12-01 00:29:48 +0000297 def size_string(self):
298 s = self.size()
299 if s == 0:
300 a_prod = "compsize"
301 b_prod = self.p_type.size
302
Ian Romanickba09c192005-02-01 00:13:04 +0000303 # Handle functions like glCompressedTexImage2D that
304 # have a counted 'void *' parameter.
305
306 if b_prod == 0: b_prod = 1
307
Ian Romanick3fec8c22005-02-02 00:54:45 +0000308 if not self.count_parameter_list and self.counter != None:
Ian Romanick0bd53732005-03-06 08:55:39 +0000309 if self.count_scale > 1:
310 a_prod = '(%s * %u)' % (self.counter, self.count_scale)
311 else:
312 a_prod = self.counter
Ian Romanick3fec8c22005-02-02 00:54:45 +0000313 elif self.count_parameter_list and self.counter == None:
Ian Romanick4f0a75e2004-12-01 00:29:48 +0000314 pass
Ian Romanick3fec8c22005-02-02 00:54:45 +0000315 elif self.count_parameter_list and self.counter != None:
Ian Romanick0bd53732005-03-06 08:55:39 +0000316 if self.count_scale > 1:
317 b_prod = '(%s * %u)' % (self.counter, self.count_scale)
318 else:
319 b_prod = self.counter
Ian Romanick5f1f2292005-01-07 02:39:09 +0000320 elif self.width:
321 return "compsize"
Ian Romanick4f0a75e2004-12-01 00:29:48 +0000322 else:
323 raise RuntimeError("Parameter '%s' to function '%s' has size 0." % (self.name, self.context.name))
324
325 return "(%s * %s)" % (a_prod, b_prod)
326 else:
327 return str(s)
328
Ian Romanicka9d033c2004-05-19 23:33:08 +0000329
Ian Romanick73f59b02004-05-18 18:33:40 +0000330class glParameterIterator:
Ian Romanicka9d033c2004-05-19 23:33:08 +0000331 """Class to iterate over a list of glParameters.
332
Ian Romanick1d270842004-12-21 21:26:36 +0000333 Objects of this class are returned by the parameterIterator method of
334 the glFunction class. They are used to iterate over the list of
Ian Romanicka9d033c2004-05-19 23:33:08 +0000335 parameters to the function."""
336
Ian Romanick73f59b02004-05-18 18:33:40 +0000337 def __init__(self, data):
338 self.data = data
339 self.index = 0
Ian Romanick1d270842004-12-21 21:26:36 +0000340
341 def __iter__(self):
342 return self
343
Ian Romanick73f59b02004-05-18 18:33:40 +0000344 def next(self):
345 if self.index == len( self.data ):
346 raise StopIteration
347 i = self.index
348 self.index += 1
349 return self.data[i]
350
Ian Romanicka9d033c2004-05-19 23:33:08 +0000351
Ian Romanick73f59b02004-05-18 18:33:40 +0000352class glFunction( glItem ):
Ian Romanick73f59b02004-05-18 18:33:40 +0000353 def __init__(self, context, name, attrs):
Ian Romanick2510ba62005-04-18 19:16:07 +0000354 self.fn_alias = attrs.get((None, 'alias'), None)
Ian Romanick73f59b02004-05-18 18:33:40 +0000355 self.fn_parameters = []
Ian Romanick5f1f2292005-01-07 02:39:09 +0000356 self.image = None
Ian Romanickba09c192005-02-01 00:13:04 +0000357 self.count_parameter_list = []
Ian Romanick3fec8c22005-02-02 00:54:45 +0000358 self.fn_return_type = "void"
Ian Romanick73f59b02004-05-18 18:33:40 +0000359
Ian Romanick2510ba62005-04-18 19:16:07 +0000360 temp = attrs.get((None, 'offset'), None)
Ian Romanick73f59b02004-05-18 18:33:40 +0000361 if temp == None or temp == "?":
362 self.fn_offset = -1
363 else:
364 self.fn_offset = int(temp)
365
Ian Romanick2510ba62005-04-18 19:16:07 +0000366 fn_name = attrs.get((None, 'name'), None)
Ian Romanick73f59b02004-05-18 18:33:40 +0000367 if self.fn_alias != None:
368 self.real_name = self.fn_alias
369 else:
370 self.real_name = fn_name
371
Ian Romanickce77d372005-03-03 21:21:59 +0000372 self.parameters_by_name = {}
373 self.variable_length_parameters = []
374
Ian Romanick73f59b02004-05-18 18:33:40 +0000375 glItem.__init__(self, name, fn_name, context)
376 return
377
378
Ian Romanick1d270842004-12-21 21:26:36 +0000379 def parameterIterator(self):
Ian Romanick73f59b02004-05-18 18:33:40 +0000380 return glParameterIterator(self.fn_parameters)
381
382
Ian Romanick2510ba62005-04-18 19:16:07 +0000383 def startElementNS(self, name, qname, attrs):
384 [uri, true_name] = name
385 if true_name == "param":
Ian Romanick73f59b02004-05-18 18:33:40 +0000386 try:
Ian Romanick2510ba62005-04-18 19:16:07 +0000387 self.context.factory.create(self, true_name, attrs)
Ian Romanick73f59b02004-05-18 18:33:40 +0000388 except RuntimeError:
389 print "Error with parameter '%s' in function '%s'." \
Ian Romanick2510ba62005-04-18 19:16:07 +0000390 % (attrs.get((None, 'name'),'(unknown)'), self.name)
Ian Romanick73f59b02004-05-18 18:33:40 +0000391 raise
Ian Romanick2510ba62005-04-18 19:16:07 +0000392 elif true_name == "return":
393 self.set_return_type(attrs.get((None, 'type'), None))
Ian Romanick73f59b02004-05-18 18:33:40 +0000394
395
Ian Romanick2510ba62005-04-18 19:16:07 +0000396 def endElementNS(self, name, qname):
Ian Romanickce77d372005-03-03 21:21:59 +0000397 """Handle the end of a <function> element.
398
399 At the end of a <function> element, there is some semantic
400 checking that can be done. This prevents some possible
401 exceptions from being thrown elsewhere in the code.
402 """
403
Ian Romanick2510ba62005-04-18 19:16:07 +0000404 [uri, true_name] = name
405 if true_name == "function":
Ian Romanickce77d372005-03-03 21:21:59 +0000406 for p in self.variable_length_parameters:
407 if p.counter:
408 counter = self.parameters_by_name[ p.counter ]
409 if not self.parameters_by_name.has_key( p.counter ):
410 raise RuntimeError("Parameter '%s' of function '%s' has counter '%s', but function has no such parameter." % (p.name, self.name, p.counter))
411 elif not self.parameters_by_name[ p.counter ].is_counter:
412 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))
413
414 for n in p.count_parameter_list:
415 if not self.parameters_by_name.has_key( n ):
416 raise RuntimeError("Parameter '%s' of function '%s' has size parameter '%s', but function has no such parameter." % (p.name, self.name, n))
417
418 return 1
419 else:
420 return 0
421
422
Ian Romanicka9d033c2004-05-19 23:33:08 +0000423 def append(self, tag_name, p):
424 if tag_name != "param":
425 raise RuntimeError("Trying to append '%s' to parameter list of function '%s'." % (tag_name, self.name))
426
Ian Romanick5f1f2292005-01-07 02:39:09 +0000427 if p.width:
428 self.image = p
429
Ian Romanick73f59b02004-05-18 18:33:40 +0000430 self.fn_parameters.append(p)
Ian Romanickba09c192005-02-01 00:13:04 +0000431 if p.count_parameter_list != []:
432 self.count_parameter_list.extend( p.count_parameter_list )
Ian Romanick73f59b02004-05-18 18:33:40 +0000433
Ian Romanickce77d372005-03-03 21:21:59 +0000434 if p.is_variable_length_array():
435 self.variable_length_parameters.append(p)
436
437 self.parameters_by_name[ p.name ] = p
438
Ian Romanicka9d033c2004-05-19 23:33:08 +0000439
Ian Romanick73f59b02004-05-18 18:33:40 +0000440 def set_return_type(self, t):
441 self.fn_return_type = t
442
Ian Romanicka9d033c2004-05-19 23:33:08 +0000443
Ian Romanick73f59b02004-05-18 18:33:40 +0000444 def get_parameter_string(self):
445 arg_string = ""
446 comma = ""
Ian Romanick1d270842004-12-21 21:26:36 +0000447 for p in glFunction.parameterIterator(self):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000448 arg_string = arg_string + comma + p.p_type_string + " " + p.name
Ian Romanick73f59b02004-05-18 18:33:40 +0000449 comma = ", "
450
451 if arg_string == "":
452 arg_string = "void"
453
454 return arg_string
455
456
457class glItemFactory:
458 """Factory to create objects derived from glItem."""
459
460 def create(self, context, name, attrs):
461 if name == "function":
462 return glFunction(context, name, attrs)
463 elif name == "type":
464 return glType(context, name, attrs)
465 elif name == "enum":
466 return glEnum(context, name, attrs)
Ian Romanick4f0a75e2004-12-01 00:29:48 +0000467 elif name == "param":
468 return glParameter(context, name, attrs)
Ian Romanick73f59b02004-05-18 18:33:40 +0000469 else:
470 return None
471
472
Ian Romanick38e6e092005-01-25 23:53:13 +0000473class glFunctionIterator:
474 """Class to iterate over a list of glFunctions
475
476 Objects of this classare returned by
477 FilterGLAPISpecBase::functionIterator. This default version
478 iterates over the functions in order of dispatch table offset. All
479 of the "true" functions are iterated first, followed by the alias
480 functions."""
481
482 def __init__(self, context):
483 self.context = context
484 self.keys = context.functions.keys()
485 self.keys.sort()
486
487 self.prevk = -1
488 self.direction = 1
489
490 for self.index in range(0, len(self.keys)):
491 if self.keys[ self.index ] >= 0: break
492
493 if self.index == len(self.keys):
494 self.direction = -1
495 self.index -= 1
496
497 self.split = self.index - 1
498 return
499
500
501 def __iter__(self):
502 return self
503
504
505 def next(self):
506 if self.index < 0:
507 raise StopIteration
508
509 k = self.keys[ self.index ]
510
511 #if self.context.functions[k].fn_alias == None:
512 # if k != self.prevk + 1:
513 # print 'Missing offset %d' % (prevk)
514 # self.prevk = int(k)
515
516 self.index += self.direction
517
518 if self.index == len(self.keys):
519 self.index = self.split
520 self.direction = -1
521
522 return self.context.functions[k]
523
524
Ian Romanick73f59b02004-05-18 18:33:40 +0000525class FilterGLAPISpecBase(saxutils.XMLFilterBase):
526 name = "a"
527 license = "The license for this file is unspecified."
Ian Romanick73f59b02004-05-18 18:33:40 +0000528 next_alias = -2
Ian Romanick73f59b02004-05-18 18:33:40 +0000529 current_object = None
Ian Romanick73f59b02004-05-18 18:33:40 +0000530
531 def __init__(self):
532 saxutils.XMLFilterBase.__init__(self)
533 self.functions = {}
534 self.types = {}
Ian Romanick6af6a692005-03-17 20:56:13 +0000535 self.functions_by_name = {}
Ian Romanick73f59b02004-05-18 18:33:40 +0000536 self.factory = glItemFactory()
Ian Romanick16c3c742005-01-28 19:00:54 +0000537 self.header_tag = None
Ian Romanickc2803582005-02-01 00:28:47 +0000538 self.undef_list = []
Ian Romanick6af6a692005-03-17 20:56:13 +0000539 self.current_category = ""
Ian Romanick73f59b02004-05-18 18:33:40 +0000540
Ian Romanicka9d033c2004-05-19 23:33:08 +0000541
Ian Romanick73f59b02004-05-18 18:33:40 +0000542 def find_type(self,type_name):
543 for t in self.types:
544 if re.compile(t).search(type_name):
545 return self.types[t]
546 print "Unable to find base type matching \"%s\"." % (type_name)
547 return None
548
Ian Romanicka9d033c2004-05-19 23:33:08 +0000549
Ian Romanick73f59b02004-05-18 18:33:40 +0000550 def find_function(self,function_name):
Ian Romanick6af6a692005-03-17 20:56:13 +0000551 return self.functions_by_name[function_name]
Ian Romanick73f59b02004-05-18 18:33:40 +0000552
Ian Romanicka9d033c2004-05-19 23:33:08 +0000553
Ian Romanick38e6e092005-01-25 23:53:13 +0000554 def functionIterator(self):
555 return glFunctionIterator(self)
556
557
Ian Romanick73f59b02004-05-18 18:33:40 +0000558 def printFunctions(self):
Ian Romanick38e6e092005-01-25 23:53:13 +0000559 for f in self.functionIterator():
560 self.printFunction(f)
Ian Romanick73f59b02004-05-18 18:33:40 +0000561 return
562
Ian Romanicka9d033c2004-05-19 23:33:08 +0000563
Ian Romanick73f59b02004-05-18 18:33:40 +0000564 def printHeader(self):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000565 """Print the header associated with all files and call the printRealHeader method."""
566
Ian Romanick73f59b02004-05-18 18:33:40 +0000567 print '/* DO NOT EDIT - This file generated automatically by %s script */' \
568 % (self.name)
569 print ''
570 print '/*'
571 print ' * ' + self.license.replace('\n', '\n * ')
572 print ' */'
573 print ''
Ian Romanick16c3c742005-01-28 19:00:54 +0000574 if self.header_tag:
575 print '#if !defined( %s )' % (self.header_tag)
576 print '# define %s' % (self.header_tag)
577 print ''
Ian Romanick73f59b02004-05-18 18:33:40 +0000578 self.printRealHeader();
579 return
580
Ian Romanicka9d033c2004-05-19 23:33:08 +0000581
Ian Romanick73f59b02004-05-18 18:33:40 +0000582 def printFooter(self):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000583 """Print the header associated with all files and call the printRealFooter method."""
584
Ian Romanick73f59b02004-05-18 18:33:40 +0000585 self.printFunctions()
586 self.printRealFooter()
Ian Romanick16c3c742005-01-28 19:00:54 +0000587 if self.header_tag:
Ian Romanickc2803582005-02-01 00:28:47 +0000588 if self.undef_list:
589 print ''
590 for u in self.undef_list:
591 print "# undef %s" % (u)
592 print ''
593 print '#endif /* !defined( %s ) */' % (self.header_tag)
Ian Romanick73f59b02004-05-18 18:33:40 +0000594
595
596 def get_category_define(self):
Ian Romanicka9d033c2004-05-19 23:33:08 +0000597 """Convert the category name to the #define that would be found in glext.h"""
598
Ian Romanick73f59b02004-05-18 18:33:40 +0000599 if re.compile("[1-9][0-9]*[.][0-9]+").match(self.current_category):
600 s = self.current_category
601 return "GL_VERSION_" + s.replace(".", "_")
602 else:
603 return self.current_category
604
605
606 def append(self, object_type, obj):
607 if object_type == "function":
608 # If the function is not an alias and has a negative
609 # offset, then we do not need to track it. These are
610 # functions that don't have an assigned offset
611
Ian Romanick2510ba62005-04-18 19:16:07 +0000612 if not self.functions_by_name.has_key(obj.name):
613 self.functions_by_name[obj.name] = obj
Ian Romanick73f59b02004-05-18 18:33:40 +0000614
Ian Romanick2510ba62005-04-18 19:16:07 +0000615 if obj.fn_offset >= 0 or obj.fn_alias != None:
616 if obj.fn_offset >= 0:
617 index = obj.fn_offset
618 else:
619 index = self.next_alias
620 self.next_alias -= 1
Ian Romanick6af6a692005-03-17 20:56:13 +0000621
Ian Romanick2510ba62005-04-18 19:16:07 +0000622 self.functions[index] = obj
623 else:
624 # We should do some checking here to make
625 # sure the functions are an identical match.
626 pass
Ian Romanick6af6a692005-03-17 20:56:13 +0000627
Ian Romanick73f59b02004-05-18 18:33:40 +0000628 elif object_type == "type":
629 self.types[obj.name] = obj
630
631 return
632
633
Ian Romanick2510ba62005-04-18 19:16:07 +0000634 def startElementNS(self, name, qname, 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 Romanick2510ba62005-04-18 19:16:07 +0000650 [uri, true_name] = name
651 if uri is None:
652 if self.current_object != None:
653 self.current_object.startElementNS(name, qname, attrs)
654 elif true_name == "category":
655 self.current_category = attrs.get((None, 'name'), "")
656 elif true_name == "include":
657 self.next_include = attrs.get((None, 'name'), "")
658 else:
659 self.current_object = self.factory.create(self, true_name, attrs)
Ian Romanick73f59b02004-05-18 18:33:40 +0000660 return
661
Ian Romanicka9d033c2004-05-19 23:33:08 +0000662
Ian Romanick2510ba62005-04-18 19:16:07 +0000663 def endElementNS(self, name, qname):
Ian Romanick73f59b02004-05-18 18:33:40 +0000664 if self.current_object != None:
Ian Romanick2510ba62005-04-18 19:16:07 +0000665 if self.current_object.endElementNS(name, qname):
Ian Romanick73f59b02004-05-18 18:33:40 +0000666 self.current_object = None
Ian Romanick6cfd4f72005-02-08 02:11:14 +0000667 elif name == "include":
668 parser = make_parser()
Ian Romanick2510ba62005-04-18 19:16:07 +0000669 parser.setFeature(feature_namespaces, 1)
Ian Romanick6cfd4f72005-02-08 02:11:14 +0000670 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