17d45beb4999a6a86c06f2af18325eb6b888880d
3 # (C) Copyright IBM Corporation 2004
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:
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
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
26 # Ian Romanick <idr@us.ibm.com>
28 from xml
.sax
import saxutils
29 from xml
.sax
import make_parser
30 from xml
.sax
.handler
import feature_namespaces
35 """Generic class on which all other API entity types are based."""
42 def __init__(self
, tag_name
, name
, context
):
44 self
.category
= context
.get_category_define()
45 self
.context
= context
46 self
.tag_name
= tag_name
48 context
.append(tag_name
, self
)
51 def startElement(self
, name
, attrs
):
54 def endElement(self
, name
):
55 """Generic endElement handler.
57 Generic endElement handler. Returns 1 if the tag containing
58 the object is complete. Otherwise 0 is returned. All
59 derived class endElement handlers should call this method. If
60 the name of the ending tag is the same as the tag that
61 started this object, the object is assumed to be complete.
63 This fails if a tag can contain another tag with the same
64 name. The XML "<foo><foo/><bar/></foo>" would fail. The
65 object would end before the bar tag was processed."""
67 if name
== self
.tag_name
:
74 class glEnum( glItem
):
75 def __init__(self
, context
, name
, attrs
):
76 self
.value
= int(attrs
.get('value', "0x0000"), 0)
79 enum_name
= "GL_" + attrs
.get('name', None)
80 glItem
.__init
__(self
, name
, enum_name
, context
)
82 def startElement(self
, name
, attrs
):
84 name
= attrs
.get('name', None)
85 count
= int(attrs
.get('count', "0"), 0)
86 self
.functions
[name
] = count
91 class glType( glItem
):
92 def __init__(self
, context
, name
, attrs
):
93 self
.size
= int(attrs
.get('size', "0"))
95 type_name
= "GL" + attrs
.get('name', None)
96 glItem
.__init
__(self
, name
, type_name
, context
)
104 p_count_parameters
= None
110 def __init__(self
, t
, ts
, n
, c
, p
, is_output
):
114 self
.p_count
= int(c
)
119 if is_output
== "true":
124 if self
.p_count
> 0 or self
.counter
!= None or p
!= None :
130 self
.p_type_string
= ts
132 self
.p_count_parameters
= p
134 # If there is a * anywhere in the parameter's type, then it
137 if re
.compile("[*]").search(ts
):
138 # We could do some other validation here. For
139 # example, an output parameter should not be const,
140 # but every non-output parameter should.
144 # If a parameter is not a pointer, then there cannot
145 # be an associated count (either fixed size or
146 # variable) and the parameter cannot be an output.
148 if has_count
or self
.is_output
:
149 raise RuntimeError("Non-pointer type has count or is output.")
152 def is_variable_length_array(self
):
153 return self
.p_count_parameters
!= None
156 return self
.is_pointer
158 def count_string(self
):
159 """Return a string representing the number of items
161 Returns a string representing the number of items in a
162 parameter. For scalar types this will always be "1". For
163 vector types, it will depend on whether or not it is a
164 fixed length vector (like the parameter of glVertex3fv),
165 a counted length (like the vector parameter of
166 glDeleteTextures), or a general variable length vector."""
169 if self
.is_variable_length_array():
171 elif self
.counter
!= None:
174 return str(self
.p_count
)
179 if self
.is_variable_length_array():
181 elif self
.p_count
== 0:
182 return self
.p_type
.size
184 return self
.p_type
.size
* self
.p_count
186 class glParameterIterator
:
187 def __init__(self
, data
):
192 if self
.index
== len( self
.data
):
198 class glFunction( glItem
):
202 fn_return_type
= "void"
205 def __init__(self
, context
, name
, attrs
):
206 self
.fn_alias
= attrs
.get('alias', None)
207 self
.fn_parameters
= []
209 temp
= attrs
.get('offset', None)
210 if temp
== None or temp
== "?":
213 self
.fn_offset
= int(temp
)
215 fn_name
= attrs
.get('name', None)
216 if self
.fn_alias
!= None:
217 self
.real_name
= self
.fn_alias
219 self
.real_name
= fn_name
221 glItem
.__init
__(self
, name
, fn_name
, context
)
226 return glParameterIterator(self
.fn_parameters
)
229 def startElement(self
, name
, attrs
):
231 p_name
= attrs
.get('name', None)
232 p_type
= attrs
.get('type', None)
233 p_count
= attrs
.get('count', "0")
234 p_param
= attrs
.get('variable_param', None)
235 is_output
= attrs
.get('output', "false")
236 is_counter
= attrs
.get('counter', "false")
238 t
= self
.context
.find_type(p_type
)
240 raise RuntimeError("Unknown type '%s' in function '%s'." % (p_type
, self
.name
))
243 p
= glParameter(t
, p_type
, p_name
, p_count
, p_param
, is_output
)
245 print "Error with parameter '%s' in function '%s'." \
246 % (p_name
, self
.name
)
249 if is_counter
== "true": p
.is_counter
= 1
251 self
.add_parameter(p
)
252 elif name
== "return":
253 self
.set_return_type(attrs
.get('type', None))
256 def add_parameter(self
, p
):
257 self
.fn_parameters
.append(p
)
259 def set_return_type(self
, t
):
260 self
.fn_return_type
= t
262 def get_parameter_string(self
):
266 arg_string
= arg_string
+ comma
+ p
.p_type_string
+ " " + p
.p_name
276 """Factory to create objects derived from glItem."""
278 def create(self
, context
, name
, attrs
):
279 if name
== "function":
280 return glFunction(context
, name
, attrs
)
282 return glType(context
, name
, attrs
)
284 return glEnum(context
, name
, attrs
)
289 class FilterGLAPISpecBase(saxutils
.XMLFilterBase
):
291 license
= "The license for this file is unspecified."
296 current_object
= None
298 current_category
= ""
301 saxutils
.XMLFilterBase
.__init
__(self
)
305 self
.factory
= glItemFactory()
307 def find_type(self
,type_name
):
309 if re
.compile(t
).search(type_name
):
311 print "Unable to find base type matching \"%s\"." % (type_name
)
314 def find_function(self
,function_name
):
315 index
= self
.xref
[function_name
]
316 return self
.functions
[index
]
318 def printFunctions(self
):
319 keys
= self
.functions
.keys()
325 if self
.functions
[k
].fn_alias
== None:
327 #print 'Missing offset %d' % (prevk)
330 self
.printFunction(self
.functions
[k
])
334 if self
.functions
[k
].fn_alias
!= None:
335 self
.printFunction(self
.functions
[k
])
339 def printHeader(self
):
340 print '/* DO NOT EDIT - This file generated automatically by %s script */' \
344 print ' * ' + self
.license
.replace('\n', '\n * ')
347 self
.printRealHeader();
350 def printFooter(self
):
351 self
.printFunctions()
352 self
.printRealFooter()
355 def get_category_define(self
):
356 if re
.compile("[1-9][0-9]*[.][0-9]+").match(self
.current_category
):
357 s
= self
.current_category
358 return "GL_VERSION_" + s
.replace(".", "_")
360 return self
.current_category
363 def append(self
, object_type
, obj
):
364 if object_type
== "function":
365 # If the function is not an alias and has a negative
366 # offset, then we do not need to track it. These are
367 # functions that don't have an assigned offset
369 if obj
.fn_offset
>= 0 or obj
.fn_alias
!= None:
370 if obj
.fn_offset
>= 0:
371 index
= obj
.fn_offset
373 index
= self
.next_alias
376 self
.functions
[index
] = obj
377 self
.xref
[obj
.name
] = index
378 elif object_type
== "type":
379 self
.types
[obj
.name
] = obj
384 def startElement(self
, name
, attrs
):
385 if self
.current_object
!= None:
386 self
.current_object
.startElement(name
, attrs
)
387 elif name
== "category":
388 self
.current_category
= attrs
.get('name', "")
390 self
.current_object
= self
.factory
.create(self
, name
, attrs
)
393 def endElement(self
, name
):
394 if self
.current_object
!= None:
395 if self
.current_object
.endElement(name
):
396 self
.current_object
= None
399 def printFunction(self
,offset
):
402 def printRealHeader(self
):
405 def printRealFooter(self
):