Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mapi / glapi / gen-es / gl_compare.py
1 #!/usr/bin/python
2 #
3 # Copyright (C) 2009 Chia-I Wu <olv@0xlab.org>
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<enum %s/>' % (spaces(indent), attrs)
230         return
231
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]
237         if not val[1]:
238             attrs += ' mode="get"'
239
240         print '%s<size %s/>' % (spaces(indent * 2), attrs)
241
242     print '%s</enum>' % 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<type %s/>' % (spaces(indent), attrs)
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<function %s>' % (spaces(indent), attrs)
262
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)
270
271     print '%s</function>' % 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         print
285     for t in types:
286         output_type(t, indent)
287     if enums or types:
288         print
289     for f in functions:
290         output_function(f, indent)
291         if f != functions[-1]:
292             print
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> <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."
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 '<?xml version="1.0"?>'
343         print '<!DOCTYPE OpenGLAPI SYSTEM "%s/gl_API.dtd">' % GLAPI
344         print
345         print '<OpenGLAPI>'
346         print
347         print '<category name="%s">' % (cat_name)
348         output_category(result, 4)
349         print '</category>'
350         print
351         print '</OpenGLAPI>'
352
353 if __name__ == "__main__":
354     main()