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] |