3 # Copyright (C) 2009 Chia-I Wu <olv@0xlab.org>
5 # Permission is hereby granted, free of charge, to any person obtaining a
6 # copy of this software and associated documentation files (the "Software"),
7 # to deal in the Software without restriction, including without limitation
8 # on the rights to use, copy, modify, merge, publish, distribute, sub
9 # license, and/or sell copies of the Software, and to permit persons to whom
10 # the Software is furnished to do so, subject to the following conditions:
12 # The above copyright notice and this permission notice (including the next
13 # paragraph) shall be included in all copies or substantial portions of the
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 # FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 # IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
28 GLAPI = "../../glapi/gen"
29 sys.path.append(GLAPI)
35 def __init__(self, api, elts=["enum", "type", "function"]):
39 def _check_enum(self, e1, e2, strict=True):
40 if e1.name != e2.name:
41 raise ValueError("%s: name mismatch" % e1.name)
42 if e1.value != e2.value:
43 raise ValueError("%s: value 0x%04x != 0x%04x"
44 % (e1.name, e1.value, e2.value))
46 def _check_type(self, t1, t2, strict=True):
47 if t1.name != t2.name:
48 raise ValueError("%s: name mismatch" % t1.name)
49 if t1.type_expr.string() != t2.type_expr.string():
50 raise ValueError("%s: type %s != %s"
51 % (t1.name, t1.type_expr.string(), t2.type_expr.string()))
53 def _check_function(self, f1, f2, strict=True):
54 if f1.name != f2.name:
55 raise ValueError("%s: name mismatch" % f1.name)
56 if f1.return_type != f2.return_type:
57 raise ValueError("%s: return type %s != %s"
58 % (f1.name, f1.return_type, f2.return_type))
59 # there might be padded parameters
60 if strict and len(f1.parameters) != len(f2.parameters):
61 raise ValueError("%s: parameter length %d != %d"
62 % (f1.name, len(f1.parameters), len(f2.parameters)))
63 if f1.assign_offset != f2.assign_offset:
64 if ((f1.assign_offset and f2.offset < 0) or
65 (f2.assign_offset and f1.offset < 0)):
66 raise ValueError("%s: assign offset %d != %d"
67 % (f1.name, f1.assign_offset, f2.assign_offset))
68 elif not f1.assign_offset:
69 if f1.offset != f2.offset:
70 raise ValueError("%s: offset %d != %d"
71 % (f1.name, f1.offset, f2.offset))
79 raise ValueError("%s: entry points %s != %s"
82 l1 = f1.static_entry_points
83 l2 = f2.static_entry_points
87 raise ValueError("%s: static entry points %s != %s"
91 for i in xrange(len(f1.parameters)):
93 p2 = f2.parameters[i + pad]
95 if not strict and p1.is_padding != p2.is_padding:
101 p2 = f2.parameters[i + pad]
103 if strict and p1.name != p2.name:
104 raise ValueError("%s: parameter %d name %s != %s"
105 % (f1.name, i, p1.name, p2.name))
106 if p1.type_expr.string() != p2.type_expr.string():
109 f1.name == "TexImage2D" and p1.name != "internalformat"):
110 raise ValueError("%s: parameter %s type %s != %s"
111 % (f1.name, p1.name, p1.type_expr.string(),
112 p2.type_expr.string()))
114 def union(self, other):
115 union = gl_XML.gl_api(None)
117 if "enum" in self.elts:
118 union.enums_by_name = other.enums_by_name.copy()
119 for key, val in self.api.enums_by_name.iteritems():
120 if key not in union.enums_by_name:
121 union.enums_by_name[key] = val
123 self._check_enum(val, other.enums_by_name[key])
125 if "type" in self.elts:
126 union.types_by_name = other.types_by_name.copy()
127 for key, val in self.api.types_by_name.iteritems():
128 if key not in union.types_by_name:
129 union.types_by_name[key] = val
131 self._check_type(val, other.types_by_name[key])
133 if "function" in self.elts:
134 union.functions_by_name = other.functions_by_name.copy()
135 for key, val in self.api.functions_by_name.iteritems():
136 if key not in union.functions_by_name:
137 union.functions_by_name[key] = val
139 self._check_function(val, other.functions_by_name[key])
143 def intersection(self, other):
144 intersection = gl_XML.gl_api(None)
146 if "enum" in self.elts:
147 for key, val in self.api.enums_by_name.iteritems():
148 if key in other.enums_by_name:
149 self._check_enum(val, other.enums_by_name[key])
150 intersection.enums_by_name[key] = val
152 if "type" in self.elts:
153 for key, val in self.api.types_by_name.iteritems():
154 if key in other.types_by_name:
155 self._check_type(val, other.types_by_name[key])
156 intersection.types_by_name[key] = val
158 if "function" in self.elts:
159 for key, val in self.api.functions_by_name.iteritems():
160 if key in other.functions_by_name:
161 self._check_function(val, other.functions_by_name[key])
162 intersection.functions_by_name[key] = val
166 def difference(self, other):
167 difference = gl_XML.gl_api(None)
169 if "enum" in self.elts:
170 for key, val in self.api.enums_by_name.iteritems():
171 if key not in other.enums_by_name:
172 difference.enums_by_name[key] = val
174 self._check_enum(val, other.enums_by_name[key])
176 if "type" in self.elts:
177 for key, val in self.api.types_by_name.iteritems():
178 if key not in other.types_by_name:
179 difference.types_by_name[key] = val
181 self._check_type(val, other.types_by_name[key])
183 if "function" in self.elts:
184 for key, val in self.api.functions_by_name.iteritems():
185 if key not in other.functions_by_name:
186 difference.functions_by_name[key] = val
188 self._check_function(val, other.functions_by_name[key], False)
192 def cmp_enum(e1, e2):
193 if e1.value < e2.value:
195 elif e1.value > e2.value:
200 def cmp_type(t1, t2):
201 return t1.size - t2.size
203 def cmp_function(f1, f2):
204 if f1.name > f2.name:
206 elif f1.name < f2.name:
211 def spaces(n, str=""):
212 spaces = n - len(str)
217 def output_enum(e, indent=0):
218 attrs = 'name="%s"' % e.name
219 if e.default_count > 0:
220 tab = spaces(37, attrs)
221 attrs += '%scount="%d"' % (tab, e.default_count)
222 tab = spaces(48, attrs)
223 val = "%04x" % e.value
224 val = "0x" + val.upper()
225 attrs += '%svalue="%s"' % (tab, val)
229 print '%s<enum %s/>' % (spaces(indent), attrs)
232 print '%s<enum %s>' % (spaces(indent), attrs)
233 for key, val in e.functions.iteritems():
234 attrs = 'name="%s"' % key
235 if val[0] != e.default_count:
236 attrs += ' count="%d"' % val[0]
238 attrs += ' mode="get"'
240 print '%s<size %s/>' % (spaces(indent * 2), attrs)
242 print '%s</enum>' % spaces(indent)
244 def output_type(t, indent=0):
245 tab = spaces(16, t.name)
246 attrs = 'name="%s"%ssize="%d"' % (t.name, tab, t.size)
247 ctype = t.type_expr.string()
248 if ctype.find("unsigned") != -1:
249 attrs += ' unsigned="true"'
250 elif ctype.find("signed") == -1:
251 attrs += ' float="true"'
252 print '%s<type %s/>' % (spaces(indent), attrs)
254 def output_function(f, indent=0):
255 attrs = 'name="%s"' % f.name
258 attrs += ' offset="assign"'
260 attrs += ' offset="%d"' % f.offset
261 print '%s<function %s>' % (spaces(indent), attrs)
263 for p in f.parameters:
264 attrs = 'name="%s" type="%s"' \
265 % (p.name, p.type_expr.original_string)
266 print '%s<param %s/>' % (spaces(indent * 2), attrs)
267 if f.return_type != "void":
268 attrs = 'type="%s"' % f.return_type
269 print '%s<return %s/>' % (spaces(indent * 2), attrs)
271 print '%s</function>' % spaces(indent)
273 def output_category(api, indent=0):
274 enums = api.enums_by_name.values()
276 types = api.types_by_name.values()
278 functions = api.functions_by_name.values()
279 functions.sort(cmp_function)
282 output_enum(e, indent)
286 output_type(t, indent)
290 output_function(f, indent)
291 if f != functions[-1]:
294 def is_api_empty(api):
295 return bool(not api.enums_by_name and
296 not api.types_by_name and
297 not api.functions_by_name)
300 print "Usage: %s [-k elts] <%s> <file1> <file2>" % (sys.argv[0], "|".join(ops))
301 print " -k elts A comma separated string of types of elements to"
302 print " skip. Possible types are enum, type, and function."
306 ops = ["union", "intersection", "difference"]
307 elts = ["enum", "type", "function"]
310 options, args = getopt.getopt(sys.argv[1:], "k:")
316 op, file1, file2 = args
321 for opt, val in options:
323 skips = val.split(",")
331 api1 = gl_XML.parse_GL_API(file1, glX_XML.glx_item_factory())
332 api2 = gl_XML.parse_GL_API(file2, glX_XML.glx_item_factory())
334 set = ApiSet(api1, elts)
335 func = getattr(set, op)
338 if not is_api_empty(result):
339 cat_name = "%s_of_%s_and_%s" \
340 % (op, os.path.basename(file1), os.path.basename(file2))
342 print '<?xml version="1.0"?>'
343 print '<!DOCTYPE OpenGLAPI SYSTEM "%s/gl_API.dtd">' % GLAPI
347 print '<category name="%s">' % (cat_name)
348 output_category(result, 4)
353 if __name__ == "__main__":