Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1901 | serge | 1 | #!/usr/bin/python |
2 | # |
||
3 | # Copyright (C) 2009 Chia-I Wu |
||
4 | # |
||
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: |
||
11 | # |
||
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 |
||
14 | # Software. |
||
15 | # |
||
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 |
||
22 | # IN THE SOFTWARE. |
||
23 | |||
24 | import sys |
||
25 | import os.path |
||
26 | import getopt |
||
27 | |||
28 | GLAPI = "../../glapi/gen" |
||
29 | sys.path.append(GLAPI) |
||
30 | |||
31 | import gl_XML |
||
32 | import glX_XML |
||
33 | |||
34 | class ApiSet(object): |
||
35 | def __init__(self, api, elts=["enum", "type", "function"]): |
||
36 | self.api = api |
||
37 | self.elts = elts |
||
38 | |||
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)) |
||
45 | |||
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())) |
||
52 | |||
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)) |
||
72 | |||
73 | if strict: |
||
74 | l1 = f1.entry_points |
||
75 | l2 = f2.entry_points |
||
76 | l1.sort() |
||
77 | l2.sort() |
||
78 | if l1 != l2: |
||
79 | raise ValueError("%s: entry points %s != %s" |
||
80 | % (f1.name, l1, l2)) |
||
81 | |||
82 | l1 = f1.static_entry_points |
||
83 | l2 = f2.static_entry_points |
||
84 | l1.sort() |
||
85 | l2.sort() |
||
86 | if l1 != l2: |
||
87 | raise ValueError("%s: static entry points %s != %s" |
||
88 | % (f1.name, l1, l2)) |
||
89 | |||
90 | pad = 0 |
||
91 | for i in xrange(len(f1.parameters)): |
||
92 | p1 = f1.parameters[i] |
||
93 | p2 = f2.parameters[i + pad] |
||
94 | |||
95 | if not strict and p1.is_padding != p2.is_padding: |
||
96 | if p1.is_padding: |
||
97 | pad -= 1 |
||
98 | continue |
||
99 | else: |
||
100 | pad += 1 |
||
101 | p2 = f2.parameters[i + pad] |
||
102 | |||
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(): |
||
107 | if (strict or |
||
108 | # special case |
||
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())) |
||
113 | |||
114 | def union(self, other): |
||
115 | union = gl_XML.gl_api(None) |
||
116 | |||
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 |
||
122 | else: |
||
123 | self._check_enum(val, other.enums_by_name[key]) |
||
124 | |||
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 |
||
130 | else: |
||
131 | self._check_type(val, other.types_by_name[key]) |
||
132 | |||
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 |
||
138 | else: |
||
139 | self._check_function(val, other.functions_by_name[key]) |
||
140 | |||
141 | return union |
||
142 | |||
143 | def intersection(self, other): |
||
144 | intersection = gl_XML.gl_api(None) |
||
145 | |||
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 |
||
151 | |||
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 |
||
157 | |||
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 |
||
163 | |||
164 | return intersection |
||
165 | |||
166 | def difference(self, other): |
||
167 | difference = gl_XML.gl_api(None) |
||
168 | |||
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 |
||
173 | else: |
||
174 | self._check_enum(val, other.enums_by_name[key]) |
||
175 | |||
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 |
||
180 | else: |
||
181 | self._check_type(val, other.types_by_name[key]) |
||
182 | |||
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 |
||
187 | else: |
||
188 | self._check_function(val, other.functions_by_name[key], False) |
||
189 | |||
190 | return difference |
||
191 | |||
192 | def cmp_enum(e1, e2): |
||
193 | if e1.value < e2.value: |
||
194 | return -1 |
||
195 | elif e1.value > e2.value: |
||
196 | return 1 |
||
197 | else: |
||
198 | return 0 |
||
199 | |||
200 | def cmp_type(t1, t2): |
||
201 | return t1.size - t2.size |
||
202 | |||
203 | def cmp_function(f1, f2): |
||
204 | if f1.name > f2.name: |
||
205 | return 1 |
||
206 | elif f1.name < f2.name: |
||
207 | return -1 |
||
208 | else: |
||
209 | return 0 |
||
210 | |||
211 | def spaces(n, str=""): |
||
212 | spaces = n - len(str) |
||
213 | if spaces < 1: |
||
214 | spaces = 1 |
||
215 | return " " * spaces |
||
216 | |||
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) |
||
226 | |||
227 | # no child |
||
228 | if not e.functions: |
||
229 | print '%s |
||
230 | return |
||
231 | |||
232 | print '%s |
||
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] |
||
237 | if not val[1]: |
||
238 | attrs += ' mode="get"' |
||
239 | |||
240 | print '%s |
||
241 | |||
242 | print '%s' % spaces(indent) |
||
243 | |||
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 |
||
253 | |||
254 | def output_function(f, indent=0): |
||
255 | attrs = 'name="%s"' % f.name |
||
256 | if f.offset > 0: |
||
257 | if f.assign_offset: |
||
258 | attrs += ' offset="assign"' |
||
259 | else: |
||
260 | attrs += ' offset="%d"' % f.offset |
||
261 | print '%s |
||
262 | |||
263 | for p in f.parameters: |
||
264 | attrs = 'name="%s" type="%s"' \ |
||
265 | % (p.name, p.type_expr.original_string) |
||
266 | print '%s' % (spaces(indent * 2), attrs) |
||
267 | if f.return_type != "void": |
||
268 | attrs = 'type="%s"' % f.return_type |
||
269 | print '%s |
||
270 | |||
271 | print '%s' % spaces(indent) |
||
272 | |||
273 | def output_category(api, indent=0): |
||
274 | enums = api.enums_by_name.values() |
||
275 | enums.sort(cmp_enum) |
||
276 | types = api.types_by_name.values() |
||
277 | types.sort(cmp_type) |
||
278 | functions = api.functions_by_name.values() |
||
279 | functions.sort(cmp_function) |
||
280 | |||
281 | for e in enums: |
||
282 | output_enum(e, indent) |
||
283 | if enums and types: |
||
284 | |||
285 | for t in types: |
||
286 | output_type(t, indent) |
||
287 | if enums or types: |
||
288 | |||
289 | for f in functions: |
||
290 | output_function(f, indent) |
||
291 | if f != functions[-1]: |
||
292 | |||
293 | |||
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) |
||
298 | |||
299 | def show_usage(ops): |
||
300 | print "Usage: %s [-k elts] <%s> |
||
301 | print " -k elts A comma separated string of types of elements to" |
||
302 | print " skip. Possible types are enum, type, and function." |
||
303 | sys.exit(1) |
||
304 | |||
305 | def main(): |
||
306 | ops = ["union", "intersection", "difference"] |
||
307 | elts = ["enum", "type", "function"] |
||
308 | |||
309 | try: |
||
310 | options, args = getopt.getopt(sys.argv[1:], "k:") |
||
311 | except Exception, e: |
||
312 | show_usage(ops) |
||
313 | |||
314 | if len(args) != 3: |
||
315 | show_usage(ops) |
||
316 | op, file1, file2 = args |
||
317 | if op not in ops: |
||
318 | show_usage(ops) |
||
319 | |||
320 | skips = [] |
||
321 | for opt, val in options: |
||
322 | if opt == "-k": |
||
323 | skips = val.split(",") |
||
324 | |||
325 | for elt in skips: |
||
326 | try: |
||
327 | elts.remove(elt) |
||
328 | except ValueError: |
||
329 | show_usage(ops) |
||
330 | |||
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()) |
||
333 | |||
334 | set = ApiSet(api1, elts) |
||
335 | func = getattr(set, op) |
||
336 | result = func(api2) |
||
337 | |||
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)) |
||
341 | |||
342 | print '' |
||
343 | print '' % GLAPI |
||
344 | |||
345 | print ' |
||
346 | |||
347 | print ' |
||
348 | output_category(result, 4) |
||
349 | print '' |
||
350 | |||
351 | print '' |
||
352 | |||
353 | if __name__ == "__main__": |
||
354 | main()!DOCTYPE>?xml>%s>>>>>> |