Subversion Repositories Kolibri OS

Rev

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' % (spaces(indent), attrs)
230
        return
231
 
232
    print '%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' % (spaces(indent * 2), attrs)
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' % (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' % (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' % (spaces(indent * 2), attrs)
267
    if f.return_type != "void":
268
        attrs = 'type="%s"' % f.return_type
269
        print '%s' % (spaces(indent * 2), attrs)
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
        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>  " % (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 ''
343
        print '' % GLAPI
344
        print
345
        print ''
346
        print
347
        print '' % (cat_name)
348
        output_category(result, 4)
349
        print ''
350
        print
351
        print ''
352
 
353
if __name__ == "__main__":
354
    main()