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
Minimal apiutil.py interface for use by es_generator.py.
25
"""
26
 
27
import sys
28
import libxml2
29
 
30
import APIspec
31
 
32
__spec = {}
33
__functions = {}
34
__aliases = {}
35
 
36
def _ParseXML(filename, apiname):
37
    conversions = {
38
        # from           to
39
        'GLfloat':  [ 'GLdouble' ],
40
        'GLclampf': [ 'GLclampd' ],
41
        'GLubyte':  [ 'GLfloat', 'GLdouble' ],
42
        'GLint':    [ 'GLfloat', 'GLdouble' ],
43
        'GLfixed':  [ 'GLfloat', 'GLdouble' ],
44
        'GLclampx': [ 'GLclampf', 'GLclampd' ],
45
    }
46
 
47
    doc = libxml2.readFile(filename, None,
48
            libxml2.XML_PARSE_DTDLOAD +
49
            libxml2.XML_PARSE_DTDVALID +
50
            libxml2.XML_PARSE_NOBLANKS)
51
    spec = APIspec.Spec(doc)
52
    impl = spec.get_impl()
53
    api = spec.get_api(apiname)
54
    doc.freeDoc()
55
 
56
    __spec["impl"] = impl
57
    __spec["api"] = api
58
 
59
    for func in api.functions:
60
        alias, need_conv = impl.match(func, conversions)
61
        if not alias:
62
            # external functions are manually dispatched
63
            if not func.is_external:
64
                print >>sys.stderr, "Error: unable to dispatch %s" % func.name
65
            alias = func
66
            need_conv = False
67
 
68
        __functions[func.name] = func
69
        __aliases[func.name] = (alias, need_conv)
70
 
71
 
72
def AllSpecials(notused=None):
73
    """Return a list of all external functions in the API."""
74
    api = __spec["api"]
75
 
76
    specials = []
77
    for func in api.functions:
78
        if func.is_external:
79
            specials.append(func.name)
80
 
81
    return specials
82
 
83
 
84
def GetAllFunctions(filename, api):
85
    """Return sorted list of all functions in the API."""
86
    if not __spec:
87
        _ParseXML(filename, api)
88
 
89
    api = __spec["api"]
90
    names = []
91
    for func in api.functions:
92
        names.append(func.name)
93
    names.sort()
94
    return names
95
 
96
 
97
def ReturnType(funcname):
98
    """Return the C return type of named function."""
99
    func = __functions[funcname]
100
    return func.return_type
101
 
102
 
103
def Properties(funcname):
104
    """Return list of properties of the named GL function."""
105
    func = __functions[funcname]
106
    return [func.direction]
107
 
108
 
109
def _ValidValues(func, param):
110
    """Return the valid values of a parameter."""
111
    valid_values = []
112
    switch = func.checker.switches.get(param.name, [])
113
    for desc in switch:
114
        # no dependent vector
115
        if not desc.checker.switches:
116
            for val in desc.values:
117
                valid_values.append((val, None, None, [], desc.error, None))
118
            continue
119
 
120
        items = desc.checker.switches.items()
121
        if len(items) > 1:
122
            print >>sys.stderr, "%s: more than one parameter depend on %s" % \
123
                    (func.name, desc.name)
124
        dep_name, dep_switch = items[0]
125
 
126
        for dep_desc in dep_switch:
127
            if dep_desc.index >= 0 and dep_desc.index != 0:
128
                print >>sys.stderr, "%s: not first element of a vector" % func.name
129
            if dep_desc.checker.switches:
130
                print >>sys.stderr, "%s: deep nested dependence" % func.name
131
 
132
            convert = None if dep_desc.convert else "noconvert"
133
            for val in desc.values:
134
                valid_values.append((val, dep_desc.size_str, dep_desc.name,
135
                                     dep_desc.values, dep_desc.error, convert))
136
    return valid_values
137
 
138
 
139
def _Conversion(func, src_param):
140
    """Return the destination type of the conversion, or None."""
141
    alias, need_conv = __aliases[func.name]
142
    if need_conv:
143
        dst_param = alias.get_param(src_param.name)
144
        if src_param.type == dst_param.type:
145
            need_conv = False
146
    if not need_conv:
147
        return (None, "none")
148
 
149
    converts = { True: 0, False: 0 }
150
 
151
    # In Fogx, for example,  pname may be GL_FOG_DENSITY/GL_FOG_START/GL_FOG_END
152
    # or GL_FOG_MODE.  In the former three cases, param is not checked and the
153
    # default is to convert.
154
    if not func.checker.always_check(src_param.name):
155
        converts[True] += 1
156
 
157
    for desc in func.checker.flatten(src_param.name):
158
        converts[desc.convert] += 1
159
        if converts[True] and converts[False]:
160
            break
161
 
162
    # it should be "never", "sometimes", and "always"...
163
    if converts[False]:
164
        if converts[True]:
165
            conversion = "some"
166
        else:
167
            conversion = "none"
168
    else:
169
        conversion = "all"
170
 
171
    return (dst_param.base_type(), conversion)
172
 
173
 
174
def _MaxVecSize(func, param):
175
    """Return the largest possible size of a vector."""
176
    if not param.is_vector:
177
        return 0
178
    if param.size:
179
        return param.size
180
 
181
    # need to look at all descriptions
182
    size = 0
183
    for desc in func.checker.flatten(param.name):
184
        if desc.size_str and desc.size_str.isdigit():
185
            s = int(desc.size_str)
186
            if s > size:
187
                size = s
188
    if not size:
189
        need_conv = __aliases[func.name][1]
190
        if need_conv:
191
            print >>sys.stderr, \
192
                    "Error: unable to dicide the max size of %s in %s" % \
193
                    (param.name, func.name)
194
    return size
195
 
196
 
197
def _ParameterTuple(func, param):
198
    """Return a parameter tuple.
199
 
200
    [0] -- parameter name
201
    [1] -- parameter type
202
    [2] -- max vector size or 0
203
    [3] -- dest type the parameter converts to, or None
204
    [4] -- valid values
205
    [5] -- how often does the conversion happen
206
 
207
    """
208
    vec_size = _MaxVecSize(func, param)
209
    dst_type, conversion = _Conversion(func, param)
210
    valid_values = _ValidValues(func, param)
211
 
212
    return (param.name, param.type, vec_size, dst_type, valid_values, conversion)
213
 
214
 
215
def Parameters(funcname):
216
    """Return list of tuples of function parameters."""
217
    func = __functions[funcname]
218
    params = []
219
    for param in func.params:
220
        params.append(_ParameterTuple(func, param))
221
 
222
    return params
223
 
224
 
225
def FunctionPrefix(funcname):
226
    """Return function specific prefix."""
227
    func = __functions[funcname]
228
 
229
    return func.prefix
230
 
231
 
232
def FindParamIndex(params, paramname):
233
    """Find the index of a named parameter."""
234
    for i in xrange(len(params)):
235
        if params[i][0] == paramname:
236
            return i
237
    return None
238
 
239
 
240
def MakeDeclarationString(params):
241
    """Return a C-style parameter declaration string."""
242
    string = []
243
    for p in params:
244
        sep = "" if p[1].endswith("*") else " "
245
        string.append("%s%s%s" % (p[1], sep, p[0]))
246
    if not string:
247
        return "void"
248
    return ", ".join(string)
249
 
250
 
251
def AliasPrefix(funcname):
252
    """Return the prefix of the function the named function is an alias of."""
253
    alias = __aliases[funcname][0]
254
    return alias.prefix
255
 
256
 
257
def Alias(funcname):
258
    """Return the name of the function the named function is an alias of."""
259
    alias, need_conv = __aliases[funcname]
260
    return alias.name if not need_conv else None
261
 
262
 
263
def ConversionFunction(funcname):
264
    """Return the name of the function the named function converts to."""
265
    alias, need_conv = __aliases[funcname]
266
    return alias.name if need_conv else None
267
 
268
 
269
def Categories(funcname):
270
    """Return all the categories of the named GL function."""
271
    api = __spec["api"]
272
    return [api.name]