mapi_abi.py revision 9f464c52
1af69d88dSmrg
2af69d88dSmrg# Mesa 3-D graphics library
3af69d88dSmrg#
4af69d88dSmrg# Copyright (C) 2010 LunarG Inc.
5af69d88dSmrg#
6af69d88dSmrg# Permission is hereby granted, free of charge, to any person obtaining a
7af69d88dSmrg# copy of this software and associated documentation files (the "Software"),
8af69d88dSmrg# to deal in the Software without restriction, including without limitation
9af69d88dSmrg# the rights to use, copy, modify, merge, publish, distribute, sublicense,
10af69d88dSmrg# and/or sell copies of the Software, and to permit persons to whom the
11af69d88dSmrg# Software is furnished to do so, subject to the following conditions:
12af69d88dSmrg#
13af69d88dSmrg# The above copyright notice and this permission notice shall be included
14af69d88dSmrg# in all copies or substantial portions of the Software.
15af69d88dSmrg#
16af69d88dSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17af69d88dSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18af69d88dSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19af69d88dSmrg# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20af69d88dSmrg# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21af69d88dSmrg# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22af69d88dSmrg# DEALINGS IN THE SOFTWARE.
23af69d88dSmrg#
24af69d88dSmrg# Authors:
25af69d88dSmrg#    Chia-I Wu <olv@lunarg.com>
26af69d88dSmrg
2701e04c3fSmrgfrom __future__ import print_function
2801e04c3fSmrg
29af69d88dSmrgimport sys
30af69d88dSmrg# make it possible to import glapi
31af69d88dSmrgimport os
329f464c52SmayaGLAPI = os.path.join(".", os.path.dirname(__file__), "glapi", "gen")
339f464c52Smayasys.path.insert(0, GLAPI)
34af69d88dSmrg
3501e04c3fSmrgfrom operator import attrgetter
36af69d88dSmrgimport re
37af69d88dSmrgfrom optparse import OptionParser
38af69d88dSmrgimport gl_XML
39af69d88dSmrgimport glX_XML
40af69d88dSmrg
41af69d88dSmrg
42af69d88dSmrg# number of dynamic entries
43af69d88dSmrgABI_NUM_DYNAMIC_ENTRIES = 256
44af69d88dSmrg
45af69d88dSmrgclass ABIEntry(object):
46af69d88dSmrg    """Represent an ABI entry."""
47af69d88dSmrg
48af69d88dSmrg    _match_c_param = re.compile(
49af69d88dSmrg            '^(?P<type>[\w\s*]+?)(?P<name>\w+)(\[(?P<array>\d+)\])?$')
50af69d88dSmrg
51af69d88dSmrg    def __init__(self, cols, attrs, xml_data = None):
52af69d88dSmrg        self._parse(cols)
53af69d88dSmrg
54af69d88dSmrg        self.slot = attrs['slot']
55af69d88dSmrg        self.hidden = attrs['hidden']
56af69d88dSmrg        self.alias = attrs['alias']
57af69d88dSmrg        self.handcode = attrs['handcode']
58af69d88dSmrg        self.xml_data = xml_data
59af69d88dSmrg
60af69d88dSmrg    def c_prototype(self):
61af69d88dSmrg        return '%s %s(%s)' % (self.c_return(), self.name, self.c_params())
62af69d88dSmrg
63af69d88dSmrg    def c_return(self):
64af69d88dSmrg        ret = self.ret
65af69d88dSmrg        if not ret:
66af69d88dSmrg            ret = 'void'
67af69d88dSmrg
68af69d88dSmrg        return ret
69af69d88dSmrg
70af69d88dSmrg    def c_params(self):
71af69d88dSmrg        """Return the parameter list used in the entry prototype."""
72af69d88dSmrg        c_params = []
73af69d88dSmrg        for t, n, a in self.params:
74af69d88dSmrg            sep = '' if t.endswith('*') else ' '
75af69d88dSmrg            arr = '[%d]' % a if a else ''
76af69d88dSmrg            c_params.append(t + sep + n + arr)
77af69d88dSmrg        if not c_params:
78af69d88dSmrg            c_params.append('void')
79af69d88dSmrg
80af69d88dSmrg        return ", ".join(c_params)
81af69d88dSmrg
82af69d88dSmrg    def c_args(self):
83af69d88dSmrg        """Return the argument list used in the entry invocation."""
84af69d88dSmrg        c_args = []
85af69d88dSmrg        for t, n, a in self.params:
86af69d88dSmrg            c_args.append(n)
87af69d88dSmrg
88af69d88dSmrg        return ", ".join(c_args)
89af69d88dSmrg
90af69d88dSmrg    def _parse(self, cols):
91af69d88dSmrg        ret = cols.pop(0)
92af69d88dSmrg        if ret == 'void':
93af69d88dSmrg            ret = None
94af69d88dSmrg
95af69d88dSmrg        name = cols.pop(0)
96af69d88dSmrg
97af69d88dSmrg        params = []
98af69d88dSmrg        if not cols:
99af69d88dSmrg            raise Exception(cols)
100af69d88dSmrg        elif len(cols) == 1 and cols[0] == 'void':
101af69d88dSmrg            pass
102af69d88dSmrg        else:
103af69d88dSmrg            for val in cols:
104af69d88dSmrg                params.append(self._parse_param(val))
105af69d88dSmrg
106af69d88dSmrg        self.ret = ret
107af69d88dSmrg        self.name = name
108af69d88dSmrg        self.params = params
109af69d88dSmrg
110af69d88dSmrg    def _parse_param(self, c_param):
111af69d88dSmrg        m = self._match_c_param.match(c_param)
112af69d88dSmrg        if not m:
113af69d88dSmrg            raise Exception('unrecognized param ' + c_param)
114af69d88dSmrg
115af69d88dSmrg        c_type = m.group('type').strip()
116af69d88dSmrg        c_name = m.group('name')
117af69d88dSmrg        c_array = m.group('array')
118af69d88dSmrg        c_array = int(c_array) if c_array else 0
119af69d88dSmrg
120af69d88dSmrg        return (c_type, c_name, c_array)
121af69d88dSmrg
122af69d88dSmrg    def __str__(self):
123af69d88dSmrg        return self.c_prototype()
124af69d88dSmrg
12501e04c3fSmrg    def __lt__(self, other):
126af69d88dSmrg        # compare slot, alias, and then name
12701e04c3fSmrg        if self.slot == other.slot:
128af69d88dSmrg            if not self.alias:
12901e04c3fSmrg                return True
130af69d88dSmrg            elif not other.alias:
13101e04c3fSmrg                return False
13201e04c3fSmrg
13301e04c3fSmrg            return self.name < other.name
134af69d88dSmrg
13501e04c3fSmrg        return self.slot < other.slot
136af69d88dSmrg
137af69d88dSmrg
138af69d88dSmrgdef abi_parse_xml(xml):
139af69d88dSmrg    """Parse a GLAPI XML file for ABI entries."""
140af69d88dSmrg    api = gl_XML.parse_GL_API(xml, glX_XML.glx_item_factory())
141af69d88dSmrg
142af69d88dSmrg    entry_dict = {}
143af69d88dSmrg    for func in api.functionIterateByOffset():
144af69d88dSmrg        # make sure func.name appear first
145af69d88dSmrg        entry_points = func.entry_points[:]
146af69d88dSmrg        entry_points.remove(func.name)
147af69d88dSmrg        entry_points.insert(0, func.name)
148af69d88dSmrg
149af69d88dSmrg        for name in entry_points:
150af69d88dSmrg            attrs = {
151af69d88dSmrg                    'slot': func.offset,
152af69d88dSmrg                    'hidden': not func.is_static_entry_point(name),
153af69d88dSmrg                    'alias': None if name == func.name else func.name,
154af69d88dSmrg                    'handcode': bool(func.has_different_protocol(name)),
155af69d88dSmrg            }
156af69d88dSmrg
157af69d88dSmrg            # post-process attrs
158af69d88dSmrg            if attrs['alias']:
159af69d88dSmrg                try:
160af69d88dSmrg                    alias = entry_dict[attrs['alias']]
161af69d88dSmrg                except KeyError:
162af69d88dSmrg                    raise Exception('failed to alias %s' % attrs['alias'])
163af69d88dSmrg                if alias.alias:
164af69d88dSmrg                    raise Exception('recursive alias %s' % ent.name)
165af69d88dSmrg                attrs['alias'] = alias
166af69d88dSmrg            if attrs['handcode']:
167af69d88dSmrg                attrs['handcode'] = func.static_glx_name(name)
168af69d88dSmrg            else:
169af69d88dSmrg                attrs['handcode'] = None
170af69d88dSmrg
17101e04c3fSmrg            if name in entry_dict:
172af69d88dSmrg                raise Exception('%s is duplicated' % (name))
173af69d88dSmrg
174af69d88dSmrg            cols = []
175af69d88dSmrg            cols.append(func.return_type)
176af69d88dSmrg            cols.append(name)
177af69d88dSmrg            params = func.get_parameter_string(name)
178af69d88dSmrg            cols.extend([p.strip() for p in params.split(',')])
179af69d88dSmrg
180af69d88dSmrg            ent = ABIEntry(cols, attrs, func)
181af69d88dSmrg            entry_dict[ent.name] = ent
182af69d88dSmrg
18301e04c3fSmrg    entries = sorted(entry_dict.values())
184af69d88dSmrg
185af69d88dSmrg    return entries
186af69d88dSmrg
187af69d88dSmrgdef abi_sanity_check(entries):
188af69d88dSmrg    if not entries:
189af69d88dSmrg        return
190af69d88dSmrg
191af69d88dSmrg    all_names = []
192af69d88dSmrg    last_slot = entries[-1].slot
193af69d88dSmrg    i = 0
19401e04c3fSmrg    for slot in range(last_slot + 1):
195af69d88dSmrg        if entries[i].slot != slot:
196af69d88dSmrg            raise Exception('entries are not ordered by slots')
197af69d88dSmrg        if entries[i].alias:
198af69d88dSmrg            raise Exception('first entry of slot %d aliases %s'
199af69d88dSmrg                    % (slot, entries[i].alias.name))
200af69d88dSmrg        handcode = None
201af69d88dSmrg        while i < len(entries) and entries[i].slot == slot:
202af69d88dSmrg            ent = entries[i]
203af69d88dSmrg            if not handcode and ent.handcode:
204af69d88dSmrg                handcode = ent.handcode
205af69d88dSmrg            elif ent.handcode != handcode:
206af69d88dSmrg                raise Exception('two aliases with handcode %s != %s',
207af69d88dSmrg                        ent.handcode, handcode)
208af69d88dSmrg
209af69d88dSmrg            if ent.name in all_names:
210af69d88dSmrg                raise Exception('%s is duplicated' % (ent.name))
211af69d88dSmrg            if ent.alias and ent.alias.name not in all_names:
212af69d88dSmrg                raise Exception('failed to alias %s' % (ent.alias.name))
213af69d88dSmrg            all_names.append(ent.name)
214af69d88dSmrg            i += 1
215af69d88dSmrg    if i < len(entries):
216af69d88dSmrg        raise Exception('there are %d invalid entries' % (len(entries) - 1))
217af69d88dSmrg
218af69d88dSmrgclass ABIPrinter(object):
219af69d88dSmrg    """MAPI Printer"""
220af69d88dSmrg
221af69d88dSmrg    def __init__(self, entries):
222af69d88dSmrg        self.entries = entries
223af69d88dSmrg
224af69d88dSmrg        # sort entries by their names
22501e04c3fSmrg        self.entries_sorted_by_names = sorted(self.entries, key=attrgetter('name'))
226af69d88dSmrg
227af69d88dSmrg        self.indent = ' ' * 3
228af69d88dSmrg        self.noop_warn = 'noop_warn'
229af69d88dSmrg        self.noop_generic = 'noop_generic'
230af69d88dSmrg        self.current_get = 'entry_current_get'
231af69d88dSmrg
232af69d88dSmrg        self.api_defines = []
233af69d88dSmrg        self.api_headers = ['"KHR/khrplatform.h"']
234af69d88dSmrg        self.api_call = 'KHRONOS_APICALL'
235af69d88dSmrg        self.api_entry = 'KHRONOS_APIENTRY'
236af69d88dSmrg        self.api_attrs = 'KHRONOS_APIATTRIBUTES'
237af69d88dSmrg
238af69d88dSmrg        self.c_header = ''
239af69d88dSmrg
240af69d88dSmrg        self.lib_need_table_size = True
241af69d88dSmrg        self.lib_need_noop_array = True
242af69d88dSmrg        self.lib_need_stubs = True
243af69d88dSmrg        self.lib_need_all_entries = True
244af69d88dSmrg        self.lib_need_non_hidden_entries = False
245af69d88dSmrg
246af69d88dSmrg    def c_notice(self):
247af69d88dSmrg        return '/* This file is automatically generated by mapi_abi.py.  Do not modify. */'
248af69d88dSmrg
249af69d88dSmrg    def c_public_includes(self):
250af69d88dSmrg        """Return includes of the client API headers."""
251af69d88dSmrg        defines = ['#define ' + d for d in self.api_defines]
252af69d88dSmrg        includes = ['#include ' + h for h in self.api_headers]
253af69d88dSmrg        return "\n".join(defines + includes)
254af69d88dSmrg
255af69d88dSmrg    def need_entry_point(self, ent):
256af69d88dSmrg        """Return True if an entry point is needed for the entry."""
257af69d88dSmrg        # non-handcode hidden aliases may share the entry they alias
258af69d88dSmrg        use_alias = (ent.hidden and ent.alias and not ent.handcode)
259af69d88dSmrg        return not use_alias
260af69d88dSmrg
261af69d88dSmrg    def c_public_declarations(self, prefix):
262af69d88dSmrg        """Return the declarations of public entry points."""
263af69d88dSmrg        decls = []
264af69d88dSmrg        for ent in self.entries:
265af69d88dSmrg            if not self.need_entry_point(ent):
266af69d88dSmrg                continue
267af69d88dSmrg            export = self.api_call if not ent.hidden else ''
2689f464c52Smaya            if not ent.hidden or not self.lib_need_non_hidden_entries:
2699f464c52Smaya                decls.append(self._c_decl(ent, prefix, True, export) + ';')
270af69d88dSmrg
271af69d88dSmrg        return "\n".join(decls)
272af69d88dSmrg
273af69d88dSmrg    def c_mapi_table(self):
274af69d88dSmrg        """Return defines of the dispatch table size."""
275af69d88dSmrg        num_static_entries = self.entries[-1].slot + 1
276af69d88dSmrg        return ('#define MAPI_TABLE_NUM_STATIC %d\n' + \
277af69d88dSmrg                '#define MAPI_TABLE_NUM_DYNAMIC %d') % (
278af69d88dSmrg                        num_static_entries, ABI_NUM_DYNAMIC_ENTRIES)
279af69d88dSmrg
280af69d88dSmrg    def _c_function(self, ent, prefix, mangle=False, stringify=False):
281af69d88dSmrg        """Return the function name of an entry."""
282af69d88dSmrg        formats = {
283af69d88dSmrg                True: { True: '%s_STR(%s)', False: '%s(%s)' },
284af69d88dSmrg                False: { True: '"%s%s"', False: '%s%s' },
285af69d88dSmrg        }
286af69d88dSmrg        fmt = formats[prefix.isupper()][stringify]
287af69d88dSmrg        name = ent.name
288af69d88dSmrg        if mangle and ent.hidden:
289af69d88dSmrg            name = '_dispatch_stub_' + str(ent.slot)
290af69d88dSmrg        return fmt % (prefix, name)
291af69d88dSmrg
292af69d88dSmrg    def _c_function_call(self, ent, prefix):
293af69d88dSmrg        """Return the function name used for calling."""
294af69d88dSmrg        if ent.handcode:
295af69d88dSmrg            # _c_function does not handle this case
296af69d88dSmrg            formats = { True: '%s(%s)', False: '%s%s' }
297af69d88dSmrg            fmt = formats[prefix.isupper()]
298af69d88dSmrg            name = fmt % (prefix, ent.handcode)
299af69d88dSmrg        elif self.need_entry_point(ent):
300af69d88dSmrg            name = self._c_function(ent, prefix, True)
301af69d88dSmrg        else:
302af69d88dSmrg            name = self._c_function(ent.alias, prefix, True)
303af69d88dSmrg        return name
304af69d88dSmrg
305af69d88dSmrg    def _c_decl(self, ent, prefix, mangle=False, export=''):
306af69d88dSmrg        """Return the C declaration for the entry."""
307af69d88dSmrg        decl = '%s %s %s(%s)' % (ent.c_return(), self.api_entry,
308af69d88dSmrg                self._c_function(ent, prefix, mangle), ent.c_params())
309af69d88dSmrg        if export:
310af69d88dSmrg            decl = export + ' ' + decl
311af69d88dSmrg        if self.api_attrs:
312af69d88dSmrg            decl += ' ' + self.api_attrs
313af69d88dSmrg
314af69d88dSmrg        return decl
315af69d88dSmrg
316af69d88dSmrg    def _c_cast(self, ent):
317af69d88dSmrg        """Return the C cast for the entry."""
318af69d88dSmrg        cast = '%s (%s *)(%s)' % (
319af69d88dSmrg                ent.c_return(), self.api_entry, ent.c_params())
320af69d88dSmrg
321af69d88dSmrg        return cast
322af69d88dSmrg
323af69d88dSmrg    def c_public_dispatches(self, prefix, no_hidden):
324af69d88dSmrg        """Return the public dispatch functions."""
325af69d88dSmrg        dispatches = []
326af69d88dSmrg        for ent in self.entries:
327af69d88dSmrg            if ent.hidden and no_hidden:
328af69d88dSmrg                continue
329af69d88dSmrg
330af69d88dSmrg            if not self.need_entry_point(ent):
331af69d88dSmrg                continue
332af69d88dSmrg
333af69d88dSmrg            export = self.api_call if not ent.hidden else ''
334af69d88dSmrg
335af69d88dSmrg            proto = self._c_decl(ent, prefix, True, export)
336af69d88dSmrg            cast = self._c_cast(ent)
337af69d88dSmrg
338af69d88dSmrg            ret = ''
339af69d88dSmrg            if ent.ret:
340af69d88dSmrg                ret = 'return '
341af69d88dSmrg            stmt1 = self.indent
34201e04c3fSmrg            stmt1 += 'const struct _glapi_table *_tbl = %s();' % (
343af69d88dSmrg                    self.current_get)
344af69d88dSmrg            stmt2 = self.indent
345af69d88dSmrg            stmt2 += 'mapi_func _func = ((const mapi_func *) _tbl)[%d];' % (
346af69d88dSmrg                    ent.slot)
347af69d88dSmrg            stmt3 = self.indent
348af69d88dSmrg            stmt3 += '%s((%s) _func)(%s);' % (ret, cast, ent.c_args())
349af69d88dSmrg
350af69d88dSmrg            disp = '%s\n{\n%s\n%s\n%s\n}' % (proto, stmt1, stmt2, stmt3)
351af69d88dSmrg
352af69d88dSmrg            if ent.handcode:
353af69d88dSmrg                disp = '#if 0\n' + disp + '\n#endif'
354af69d88dSmrg
355af69d88dSmrg            dispatches.append(disp)
356af69d88dSmrg
357af69d88dSmrg        return '\n\n'.join(dispatches)
358af69d88dSmrg
359af69d88dSmrg    def c_public_initializer(self, prefix):
360af69d88dSmrg        """Return the initializer for public dispatch functions."""
361af69d88dSmrg        names = []
362af69d88dSmrg        for ent in self.entries:
363af69d88dSmrg            if ent.alias:
364af69d88dSmrg                continue
365af69d88dSmrg
366af69d88dSmrg            name = '%s(mapi_func) %s' % (self.indent,
367af69d88dSmrg                    self._c_function_call(ent, prefix))
368af69d88dSmrg            names.append(name)
369af69d88dSmrg
370af69d88dSmrg        return ',\n'.join(names)
371af69d88dSmrg
372af69d88dSmrg    def c_stub_string_pool(self):
373af69d88dSmrg        """Return the string pool for use by stubs."""
374af69d88dSmrg        # sort entries by their names
37501e04c3fSmrg        sorted_entries = sorted(self.entries, key=attrgetter('name'))
376af69d88dSmrg
377af69d88dSmrg        pool = []
378af69d88dSmrg        offsets = {}
379af69d88dSmrg        count = 0
380af69d88dSmrg        for ent in sorted_entries:
381af69d88dSmrg            offsets[ent] = count
382af69d88dSmrg            pool.append('%s' % (ent.name))
383af69d88dSmrg            count += len(ent.name) + 1
384af69d88dSmrg
385af69d88dSmrg        pool_str =  self.indent + '"' + \
386af69d88dSmrg                ('\\0"\n' + self.indent + '"').join(pool) + '";'
387af69d88dSmrg        return (pool_str, offsets)
388af69d88dSmrg
389af69d88dSmrg    def c_stub_initializer(self, prefix, pool_offsets):
390af69d88dSmrg        """Return the initializer for struct mapi_stub array."""
391af69d88dSmrg        stubs = []
392af69d88dSmrg        for ent in self.entries_sorted_by_names:
393af69d88dSmrg            stubs.append('%s{ (void *) %d, %d, NULL }' % (
394af69d88dSmrg                self.indent, pool_offsets[ent], ent.slot))
395af69d88dSmrg
396af69d88dSmrg        return ',\n'.join(stubs)
397af69d88dSmrg
398af69d88dSmrg    def c_noop_functions(self, prefix, warn_prefix):
399af69d88dSmrg        """Return the noop functions."""
400af69d88dSmrg        noops = []
401af69d88dSmrg        for ent in self.entries:
402af69d88dSmrg            if ent.alias:
403af69d88dSmrg                continue
404af69d88dSmrg
405af69d88dSmrg            proto = self._c_decl(ent, prefix, False, 'static')
406af69d88dSmrg
407af69d88dSmrg            stmt1 = self.indent;
408af69d88dSmrg            space = ''
409af69d88dSmrg            for t, n, a in ent.params:
410af69d88dSmrg                stmt1 += "%s(void) %s;" % (space, n)
411af69d88dSmrg                space = ' '
412af69d88dSmrg
413af69d88dSmrg            if ent.params:
414af69d88dSmrg                stmt1 += '\n';
415af69d88dSmrg
416af69d88dSmrg            stmt1 += self.indent + '%s(%s);' % (self.noop_warn,
417af69d88dSmrg                    self._c_function(ent, warn_prefix, False, True))
418af69d88dSmrg
419af69d88dSmrg            if ent.ret:
420af69d88dSmrg                stmt2 = self.indent + 'return (%s) 0;' % (ent.ret)
421af69d88dSmrg                noop = '%s\n{\n%s\n%s\n}' % (proto, stmt1, stmt2)
422af69d88dSmrg            else:
423af69d88dSmrg                noop = '%s\n{\n%s\n}' % (proto, stmt1)
424af69d88dSmrg
425af69d88dSmrg            noops.append(noop)
426af69d88dSmrg
427af69d88dSmrg        return '\n\n'.join(noops)
428af69d88dSmrg
429af69d88dSmrg    def c_noop_initializer(self, prefix, use_generic):
430af69d88dSmrg        """Return an initializer for the noop dispatch table."""
431af69d88dSmrg        entries = [self._c_function(ent, prefix)
432af69d88dSmrg                for ent in self.entries if not ent.alias]
433af69d88dSmrg        if use_generic:
434af69d88dSmrg            entries = [self.noop_generic] * len(entries)
435af69d88dSmrg
436af69d88dSmrg        entries.extend([self.noop_generic] * ABI_NUM_DYNAMIC_ENTRIES)
437af69d88dSmrg
438af69d88dSmrg        pre = self.indent + '(mapi_func) '
439af69d88dSmrg        return pre + (',\n' + pre).join(entries)
440af69d88dSmrg
441af69d88dSmrg    def c_asm_gcc(self, prefix, no_hidden):
442af69d88dSmrg        asm = []
443af69d88dSmrg
444af69d88dSmrg        for ent in self.entries:
445af69d88dSmrg            if ent.hidden and no_hidden:
446af69d88dSmrg                continue
447af69d88dSmrg
448af69d88dSmrg            if not self.need_entry_point(ent):
449af69d88dSmrg                continue
450af69d88dSmrg
451af69d88dSmrg            name = self._c_function(ent, prefix, True, True)
452af69d88dSmrg
453af69d88dSmrg            if ent.handcode:
454af69d88dSmrg                asm.append('#if 0')
455af69d88dSmrg
456af69d88dSmrg            if ent.hidden:
457af69d88dSmrg                asm.append('".hidden "%s"\\n"' % (name))
458af69d88dSmrg
459af69d88dSmrg            if ent.alias and not (ent.alias.hidden and no_hidden):
460af69d88dSmrg                asm.append('".globl "%s"\\n"' % (name))
461af69d88dSmrg                asm.append('".set "%s", "%s"\\n"' % (name,
462af69d88dSmrg                    self._c_function(ent.alias, prefix, True, True)))
463af69d88dSmrg            else:
464af69d88dSmrg                asm.append('STUB_ASM_ENTRY(%s)"\\n"' % (name))
465af69d88dSmrg                asm.append('"\\t"STUB_ASM_CODE("%d")"\\n"' % (ent.slot))
466af69d88dSmrg
467af69d88dSmrg            if ent.handcode:
468af69d88dSmrg                asm.append('#endif')
469af69d88dSmrg            asm.append('')
470af69d88dSmrg
471af69d88dSmrg        return "\n".join(asm)
472af69d88dSmrg
473af69d88dSmrg    def output_for_lib(self):
47401e04c3fSmrg        print(self.c_notice())
475af69d88dSmrg
476af69d88dSmrg        if self.c_header:
47701e04c3fSmrg            print()
47801e04c3fSmrg            print(self.c_header)
479af69d88dSmrg
48001e04c3fSmrg        print()
48101e04c3fSmrg        print('#ifdef MAPI_TMP_DEFINES')
48201e04c3fSmrg        print(self.c_public_includes())
48301e04c3fSmrg        print()
48401e04c3fSmrg        print(self.c_public_declarations(self.prefix_lib))
48501e04c3fSmrg        print('#undef MAPI_TMP_DEFINES')
48601e04c3fSmrg        print('#endif /* MAPI_TMP_DEFINES */')
487af69d88dSmrg
488af69d88dSmrg        if self.lib_need_table_size:
48901e04c3fSmrg            print()
49001e04c3fSmrg            print('#ifdef MAPI_TMP_TABLE')
49101e04c3fSmrg            print(self.c_mapi_table())
49201e04c3fSmrg            print('#undef MAPI_TMP_TABLE')
49301e04c3fSmrg            print('#endif /* MAPI_TMP_TABLE */')
494af69d88dSmrg
495af69d88dSmrg        if self.lib_need_noop_array:
49601e04c3fSmrg            print()
49701e04c3fSmrg            print('#ifdef MAPI_TMP_NOOP_ARRAY')
49801e04c3fSmrg            print('#ifdef DEBUG')
49901e04c3fSmrg            print()
50001e04c3fSmrg            print(self.c_noop_functions(self.prefix_noop, self.prefix_warn))
50101e04c3fSmrg            print()
50201e04c3fSmrg            print('const mapi_func table_%s_array[] = {' % (self.prefix_noop))
50301e04c3fSmrg            print(self.c_noop_initializer(self.prefix_noop, False))
50401e04c3fSmrg            print('};')
50501e04c3fSmrg            print()
50601e04c3fSmrg            print('#else /* DEBUG */')
50701e04c3fSmrg            print()
50801e04c3fSmrg            print('const mapi_func table_%s_array[] = {' % (self.prefix_noop))
50901e04c3fSmrg            print(self.c_noop_initializer(self.prefix_noop, True))
51001e04c3fSmrg            print('};')
51101e04c3fSmrg            print()
51201e04c3fSmrg            print('#endif /* DEBUG */')
51301e04c3fSmrg            print('#undef MAPI_TMP_NOOP_ARRAY')
51401e04c3fSmrg            print('#endif /* MAPI_TMP_NOOP_ARRAY */')
515af69d88dSmrg
516af69d88dSmrg        if self.lib_need_stubs:
517af69d88dSmrg            pool, pool_offsets = self.c_stub_string_pool()
51801e04c3fSmrg            print()
51901e04c3fSmrg            print('#ifdef MAPI_TMP_PUBLIC_STUBS')
52001e04c3fSmrg            print('static const char public_string_pool[] =')
52101e04c3fSmrg            print(pool)
52201e04c3fSmrg            print()
52301e04c3fSmrg            print('static const struct mapi_stub public_stubs[] = {')
52401e04c3fSmrg            print(self.c_stub_initializer(self.prefix_lib, pool_offsets))
52501e04c3fSmrg            print('};')
52601e04c3fSmrg            print('#undef MAPI_TMP_PUBLIC_STUBS')
52701e04c3fSmrg            print('#endif /* MAPI_TMP_PUBLIC_STUBS */')
528af69d88dSmrg
529af69d88dSmrg        if self.lib_need_all_entries:
53001e04c3fSmrg            print()
53101e04c3fSmrg            print('#ifdef MAPI_TMP_PUBLIC_ENTRIES')
53201e04c3fSmrg            print(self.c_public_dispatches(self.prefix_lib, False))
53301e04c3fSmrg            print()
53401e04c3fSmrg            print('static const mapi_func public_entries[] = {')
53501e04c3fSmrg            print(self.c_public_initializer(self.prefix_lib))
53601e04c3fSmrg            print('};')
53701e04c3fSmrg            print('#undef MAPI_TMP_PUBLIC_ENTRIES')
53801e04c3fSmrg            print('#endif /* MAPI_TMP_PUBLIC_ENTRIES */')
53901e04c3fSmrg
54001e04c3fSmrg            print()
54101e04c3fSmrg            print('#ifdef MAPI_TMP_STUB_ASM_GCC')
54201e04c3fSmrg            print('__asm__(')
54301e04c3fSmrg            print(self.c_asm_gcc(self.prefix_lib, False))
54401e04c3fSmrg            print(');')
54501e04c3fSmrg            print('#undef MAPI_TMP_STUB_ASM_GCC')
54601e04c3fSmrg            print('#endif /* MAPI_TMP_STUB_ASM_GCC */')
547af69d88dSmrg
548af69d88dSmrg        if self.lib_need_non_hidden_entries:
549af69d88dSmrg            all_hidden = True
550af69d88dSmrg            for ent in self.entries:
551af69d88dSmrg                if not ent.hidden:
552af69d88dSmrg                    all_hidden = False
553af69d88dSmrg                    break
554af69d88dSmrg            if not all_hidden:
55501e04c3fSmrg                print()
55601e04c3fSmrg                print('#ifdef MAPI_TMP_PUBLIC_ENTRIES_NO_HIDDEN')
55701e04c3fSmrg                print(self.c_public_dispatches(self.prefix_lib, True))
55801e04c3fSmrg                print()
55901e04c3fSmrg                print('/* does not need public_entries */')
56001e04c3fSmrg                print('#undef MAPI_TMP_PUBLIC_ENTRIES_NO_HIDDEN')
56101e04c3fSmrg                print('#endif /* MAPI_TMP_PUBLIC_ENTRIES_NO_HIDDEN */')
56201e04c3fSmrg
56301e04c3fSmrg                print()
56401e04c3fSmrg                print('#ifdef MAPI_TMP_STUB_ASM_GCC_NO_HIDDEN')
56501e04c3fSmrg                print('__asm__(')
56601e04c3fSmrg                print(self.c_asm_gcc(self.prefix_lib, True))
56701e04c3fSmrg                print(');')
56801e04c3fSmrg                print('#undef MAPI_TMP_STUB_ASM_GCC_NO_HIDDEN')
56901e04c3fSmrg                print('#endif /* MAPI_TMP_STUB_ASM_GCC_NO_HIDDEN */')
570af69d88dSmrg
571af69d88dSmrgclass GLAPIPrinter(ABIPrinter):
572af69d88dSmrg    """OpenGL API Printer"""
573af69d88dSmrg
574af69d88dSmrg    def __init__(self, entries):
575af69d88dSmrg        for ent in entries:
576af69d88dSmrg            self._override_for_api(ent)
577af69d88dSmrg        super(GLAPIPrinter, self).__init__(entries)
578af69d88dSmrg
579af69d88dSmrg        self.api_defines = ['GL_GLEXT_PROTOTYPES']
580af69d88dSmrg        self.api_headers = ['"GL/gl.h"', '"GL/glext.h"']
581af69d88dSmrg        self.api_call = 'GLAPI'
582af69d88dSmrg        self.api_entry = 'APIENTRY'
583af69d88dSmrg        self.api_attrs = ''
584af69d88dSmrg
585af69d88dSmrg        self.lib_need_table_size = False
586af69d88dSmrg        self.lib_need_noop_array = False
587af69d88dSmrg        self.lib_need_stubs = False
588af69d88dSmrg        self.lib_need_all_entries = False
589af69d88dSmrg        self.lib_need_non_hidden_entries = True
590af69d88dSmrg
591af69d88dSmrg        self.prefix_lib = 'GLAPI_PREFIX'
592af69d88dSmrg        self.prefix_noop = 'noop'
593af69d88dSmrg        self.prefix_warn = self.prefix_lib
594af69d88dSmrg
595af69d88dSmrg        self.c_header = self._get_c_header()
596af69d88dSmrg
597af69d88dSmrg    def _override_for_api(self, ent):
598af69d88dSmrg        """Override attributes of an entry if necessary for this
599af69d88dSmrg        printer."""
600af69d88dSmrg        # By default, no override is necessary.
601af69d88dSmrg        pass
602af69d88dSmrg
603af69d88dSmrg    def _get_c_header(self):
604af69d88dSmrg        header = """#ifndef _GLAPI_TMP_H_
605af69d88dSmrg#define _GLAPI_TMP_H_
606af69d88dSmrg#ifdef USE_MGL_NAMESPACE
607af69d88dSmrg#define GLAPI_PREFIX(func)  mgl##func
608af69d88dSmrg#define GLAPI_PREFIX_STR(func)  "mgl"#func
609af69d88dSmrg#else
610af69d88dSmrg#define GLAPI_PREFIX(func)  gl##func
611af69d88dSmrg#define GLAPI_PREFIX_STR(func)  "gl"#func
612af69d88dSmrg#endif /* USE_MGL_NAMESPACE */
613af69d88dSmrg
614af69d88dSmrgtypedef int GLclampx;
615af69d88dSmrg#endif /* _GLAPI_TMP_H_ */"""
616af69d88dSmrg
617af69d88dSmrg        return header
618af69d88dSmrg
619af69d88dSmrgclass SharedGLAPIPrinter(GLAPIPrinter):
620af69d88dSmrg    """Shared GLAPI API Printer"""
621af69d88dSmrg
622af69d88dSmrg    def __init__(self, entries):
623af69d88dSmrg        super(SharedGLAPIPrinter, self).__init__(entries)
624af69d88dSmrg
625af69d88dSmrg        self.lib_need_table_size = True
626af69d88dSmrg        self.lib_need_noop_array = True
627af69d88dSmrg        self.lib_need_stubs = True
628af69d88dSmrg        self.lib_need_all_entries = True
629af69d88dSmrg        self.lib_need_non_hidden_entries = False
630af69d88dSmrg
631af69d88dSmrg        self.prefix_lib = 'shared'
632af69d88dSmrg        self.prefix_warn = 'gl'
633af69d88dSmrg
634af69d88dSmrg    def _override_for_api(self, ent):
635af69d88dSmrg        ent.hidden = True
636af69d88dSmrg        ent.handcode = False
637af69d88dSmrg
638af69d88dSmrg    def _get_c_header(self):
639af69d88dSmrg        header = """#ifndef _GLAPI_TMP_H_
640af69d88dSmrg#define _GLAPI_TMP_H_
641af69d88dSmrgtypedef int GLclampx;
642af69d88dSmrg#endif /* _GLAPI_TMP_H_ */"""
643af69d88dSmrg
644af69d88dSmrg        return header
645af69d88dSmrg
646af69d88dSmrgdef parse_args():
64701e04c3fSmrg    printers = ['glapi', 'es1api', 'es2api', 'shared-glapi']
648af69d88dSmrg
6499f464c52Smaya    parser = OptionParser(usage='usage: %prog [options] <xml_file>')
650af69d88dSmrg    parser.add_option('-p', '--printer', dest='printer',
651af69d88dSmrg            help='printer to use: %s' % (", ".join(printers)))
652af69d88dSmrg
653af69d88dSmrg    options, args = parser.parse_args()
65401e04c3fSmrg    if not args or options.printer not in printers:
655af69d88dSmrg        parser.print_help()
656af69d88dSmrg        sys.exit(1)
657af69d88dSmrg
6589f464c52Smaya    if not args[0].endswith('.xml'):
6599f464c52Smaya        parser.print_help()
6609f464c52Smaya        sys.exit(1)
6619f464c52Smaya
662af69d88dSmrg    return (args[0], options)
663af69d88dSmrg
664af69d88dSmrgdef main():
665af69d88dSmrg    printers = {
666af69d88dSmrg        'glapi': GLAPIPrinter,
667af69d88dSmrg        'shared-glapi': SharedGLAPIPrinter,
668af69d88dSmrg    }
669af69d88dSmrg
670af69d88dSmrg    filename, options = parse_args()
671af69d88dSmrg
6729f464c52Smaya    entries = abi_parse_xml(filename)
673af69d88dSmrg    abi_sanity_check(entries)
674af69d88dSmrg
675af69d88dSmrg    printer = printers[options.printer](entries)
67601e04c3fSmrg    printer.output_for_lib()
677af69d88dSmrg
678af69d88dSmrgif __name__ == '__main__':
679af69d88dSmrg    main()
680