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
27af69d88dSmrgimport sys
28af69d88dSmrg# make it possible to import glapi
29af69d88dSmrgimport os
309f464c52SmayaGLAPI = os.path.join(".", os.path.dirname(__file__), "glapi", "gen")
319f464c52Smayasys.path.insert(0, GLAPI)
32af69d88dSmrg
3301e04c3fSmrgfrom operator import attrgetter
34af69d88dSmrgimport re
35af69d88dSmrgfrom optparse import OptionParser
36af69d88dSmrgimport gl_XML
37af69d88dSmrgimport glX_XML
38af69d88dSmrg
39af69d88dSmrg
40af69d88dSmrg# number of dynamic entries
41af69d88dSmrgABI_NUM_DYNAMIC_ENTRIES = 256
42af69d88dSmrg
43af69d88dSmrgclass ABIEntry(object):
44af69d88dSmrg    """Represent an ABI entry."""
45af69d88dSmrg
46af69d88dSmrg    _match_c_param = re.compile(
47af69d88dSmrg            '^(?P<type>[\w\s*]+?)(?P<name>\w+)(\[(?P<array>\d+)\])?$')
48af69d88dSmrg
49af69d88dSmrg    def __init__(self, cols, attrs, xml_data = None):
50af69d88dSmrg        self._parse(cols)
51af69d88dSmrg
52af69d88dSmrg        self.slot = attrs['slot']
53af69d88dSmrg        self.hidden = attrs['hidden']
54af69d88dSmrg        self.alias = attrs['alias']
55af69d88dSmrg        self.handcode = attrs['handcode']
56af69d88dSmrg        self.xml_data = xml_data
57af69d88dSmrg
58af69d88dSmrg    def c_prototype(self):
59af69d88dSmrg        return '%s %s(%s)' % (self.c_return(), self.name, self.c_params())
60af69d88dSmrg
61af69d88dSmrg    def c_return(self):
62af69d88dSmrg        ret = self.ret
63af69d88dSmrg        if not ret:
64af69d88dSmrg            ret = 'void'
65af69d88dSmrg
66af69d88dSmrg        return ret
67af69d88dSmrg
68af69d88dSmrg    def c_params(self):
69af69d88dSmrg        """Return the parameter list used in the entry prototype."""
70af69d88dSmrg        c_params = []
71af69d88dSmrg        for t, n, a in self.params:
72af69d88dSmrg            sep = '' if t.endswith('*') else ' '
73af69d88dSmrg            arr = '[%d]' % a if a else ''
74af69d88dSmrg            c_params.append(t + sep + n + arr)
75af69d88dSmrg        if not c_params:
76af69d88dSmrg            c_params.append('void')
77af69d88dSmrg
78af69d88dSmrg        return ", ".join(c_params)
79af69d88dSmrg
80af69d88dSmrg    def c_args(self):
81af69d88dSmrg        """Return the argument list used in the entry invocation."""
82af69d88dSmrg        c_args = []
83af69d88dSmrg        for t, n, a in self.params:
84af69d88dSmrg            c_args.append(n)
85af69d88dSmrg
86af69d88dSmrg        return ", ".join(c_args)
87af69d88dSmrg
88af69d88dSmrg    def _parse(self, cols):
89af69d88dSmrg        ret = cols.pop(0)
90af69d88dSmrg        if ret == 'void':
91af69d88dSmrg            ret = None
92af69d88dSmrg
93af69d88dSmrg        name = cols.pop(0)
94af69d88dSmrg
95af69d88dSmrg        params = []
96af69d88dSmrg        if not cols:
97af69d88dSmrg            raise Exception(cols)
98af69d88dSmrg        elif len(cols) == 1 and cols[0] == 'void':
99af69d88dSmrg            pass
100af69d88dSmrg        else:
101af69d88dSmrg            for val in cols:
102af69d88dSmrg                params.append(self._parse_param(val))
103af69d88dSmrg
104af69d88dSmrg        self.ret = ret
105af69d88dSmrg        self.name = name
106af69d88dSmrg        self.params = params
107af69d88dSmrg
108af69d88dSmrg    def _parse_param(self, c_param):
109af69d88dSmrg        m = self._match_c_param.match(c_param)
110af69d88dSmrg        if not m:
111af69d88dSmrg            raise Exception('unrecognized param ' + c_param)
112af69d88dSmrg
113af69d88dSmrg        c_type = m.group('type').strip()
114af69d88dSmrg        c_name = m.group('name')
115af69d88dSmrg        c_array = m.group('array')
116af69d88dSmrg        c_array = int(c_array) if c_array else 0
117af69d88dSmrg
118af69d88dSmrg        return (c_type, c_name, c_array)
119af69d88dSmrg
120af69d88dSmrg    def __str__(self):
121af69d88dSmrg        return self.c_prototype()
122af69d88dSmrg
12301e04c3fSmrg    def __lt__(self, other):
124af69d88dSmrg        # compare slot, alias, and then name
12501e04c3fSmrg        if self.slot == other.slot:
126af69d88dSmrg            if not self.alias:
12701e04c3fSmrg                return True
128af69d88dSmrg            elif not other.alias:
12901e04c3fSmrg                return False
13001e04c3fSmrg
13101e04c3fSmrg            return self.name < other.name
132af69d88dSmrg
13301e04c3fSmrg        return self.slot < other.slot
134af69d88dSmrg
135af69d88dSmrg
136af69d88dSmrgdef abi_parse_xml(xml):
137af69d88dSmrg    """Parse a GLAPI XML file for ABI entries."""
138af69d88dSmrg    api = gl_XML.parse_GL_API(xml, glX_XML.glx_item_factory())
139af69d88dSmrg
140af69d88dSmrg    entry_dict = {}
141af69d88dSmrg    for func in api.functionIterateByOffset():
142af69d88dSmrg        # make sure func.name appear first
143af69d88dSmrg        entry_points = func.entry_points[:]
144af69d88dSmrg        entry_points.remove(func.name)
145af69d88dSmrg        entry_points.insert(0, func.name)
146af69d88dSmrg
147af69d88dSmrg        for name in entry_points:
148af69d88dSmrg            attrs = {
149af69d88dSmrg                    'slot': func.offset,
150af69d88dSmrg                    'hidden': not func.is_static_entry_point(name),
151af69d88dSmrg                    'alias': None if name == func.name else func.name,
152af69d88dSmrg                    'handcode': bool(func.has_different_protocol(name)),
153af69d88dSmrg            }
154af69d88dSmrg
155af69d88dSmrg            # post-process attrs
156af69d88dSmrg            if attrs['alias']:
157af69d88dSmrg                try:
158af69d88dSmrg                    alias = entry_dict[attrs['alias']]
159af69d88dSmrg                except KeyError:
160af69d88dSmrg                    raise Exception('failed to alias %s' % attrs['alias'])
161af69d88dSmrg                if alias.alias:
162af69d88dSmrg                    raise Exception('recursive alias %s' % ent.name)
163af69d88dSmrg                attrs['alias'] = alias
164af69d88dSmrg            if attrs['handcode']:
165af69d88dSmrg                attrs['handcode'] = func.static_glx_name(name)
166af69d88dSmrg            else:
167af69d88dSmrg                attrs['handcode'] = None
168af69d88dSmrg
16901e04c3fSmrg            if name in entry_dict:
170af69d88dSmrg                raise Exception('%s is duplicated' % (name))
171af69d88dSmrg
172af69d88dSmrg            cols = []
173af69d88dSmrg            cols.append(func.return_type)
174af69d88dSmrg            cols.append(name)
175af69d88dSmrg            params = func.get_parameter_string(name)
176af69d88dSmrg            cols.extend([p.strip() for p in params.split(',')])
177af69d88dSmrg
178af69d88dSmrg            ent = ABIEntry(cols, attrs, func)
179af69d88dSmrg            entry_dict[ent.name] = ent
180af69d88dSmrg
18101e04c3fSmrg    entries = sorted(entry_dict.values())
182af69d88dSmrg
183af69d88dSmrg    return entries
184af69d88dSmrg
185af69d88dSmrgdef abi_sanity_check(entries):
186af69d88dSmrg    if not entries:
187af69d88dSmrg        return
188af69d88dSmrg
189af69d88dSmrg    all_names = []
190af69d88dSmrg    last_slot = entries[-1].slot
191af69d88dSmrg    i = 0
19201e04c3fSmrg    for slot in range(last_slot + 1):
193af69d88dSmrg        if entries[i].slot != slot:
194af69d88dSmrg            raise Exception('entries are not ordered by slots')
195af69d88dSmrg        if entries[i].alias:
196af69d88dSmrg            raise Exception('first entry of slot %d aliases %s'
197af69d88dSmrg                    % (slot, entries[i].alias.name))
198af69d88dSmrg        handcode = None
199af69d88dSmrg        while i < len(entries) and entries[i].slot == slot:
200af69d88dSmrg            ent = entries[i]
201af69d88dSmrg            if not handcode and ent.handcode:
202af69d88dSmrg                handcode = ent.handcode
203af69d88dSmrg            elif ent.handcode != handcode:
204af69d88dSmrg                raise Exception('two aliases with handcode %s != %s',
205af69d88dSmrg                        ent.handcode, handcode)
206af69d88dSmrg
207af69d88dSmrg            if ent.name in all_names:
208af69d88dSmrg                raise Exception('%s is duplicated' % (ent.name))
209af69d88dSmrg            if ent.alias and ent.alias.name not in all_names:
210af69d88dSmrg                raise Exception('failed to alias %s' % (ent.alias.name))
211af69d88dSmrg            all_names.append(ent.name)
212af69d88dSmrg            i += 1
213af69d88dSmrg    if i < len(entries):
214af69d88dSmrg        raise Exception('there are %d invalid entries' % (len(entries) - 1))
215af69d88dSmrg
216af69d88dSmrgclass ABIPrinter(object):
217af69d88dSmrg    """MAPI Printer"""
218af69d88dSmrg
219af69d88dSmrg    def __init__(self, entries):
220af69d88dSmrg        self.entries = entries
221af69d88dSmrg
222af69d88dSmrg        # sort entries by their names
22301e04c3fSmrg        self.entries_sorted_by_names = sorted(self.entries, key=attrgetter('name'))
224af69d88dSmrg
225af69d88dSmrg        self.indent = ' ' * 3
226af69d88dSmrg        self.noop_warn = 'noop_warn'
227af69d88dSmrg        self.noop_generic = 'noop_generic'
228af69d88dSmrg        self.current_get = 'entry_current_get'
229af69d88dSmrg
230af69d88dSmrg        self.api_defines = []
231af69d88dSmrg        self.api_headers = ['"KHR/khrplatform.h"']
232af69d88dSmrg        self.api_call = 'KHRONOS_APICALL'
233af69d88dSmrg        self.api_entry = 'KHRONOS_APIENTRY'
234af69d88dSmrg        self.api_attrs = 'KHRONOS_APIATTRIBUTES'
235af69d88dSmrg
236af69d88dSmrg        self.c_header = ''
237af69d88dSmrg
238af69d88dSmrg        self.lib_need_table_size = True
239af69d88dSmrg        self.lib_need_noop_array = True
240af69d88dSmrg        self.lib_need_stubs = True
241af69d88dSmrg        self.lib_need_all_entries = True
242af69d88dSmrg        self.lib_need_non_hidden_entries = False
243af69d88dSmrg
244af69d88dSmrg    def c_notice(self):
245af69d88dSmrg        return '/* This file is automatically generated by mapi_abi.py.  Do not modify. */'
246af69d88dSmrg
247af69d88dSmrg    def c_public_includes(self):
248af69d88dSmrg        """Return includes of the client API headers."""
249af69d88dSmrg        defines = ['#define ' + d for d in self.api_defines]
250af69d88dSmrg        includes = ['#include ' + h for h in self.api_headers]
251af69d88dSmrg        return "\n".join(defines + includes)
252af69d88dSmrg
253af69d88dSmrg    def need_entry_point(self, ent):
254af69d88dSmrg        """Return True if an entry point is needed for the entry."""
255af69d88dSmrg        # non-handcode hidden aliases may share the entry they alias
256af69d88dSmrg        use_alias = (ent.hidden and ent.alias and not ent.handcode)
257af69d88dSmrg        return not use_alias
258af69d88dSmrg
259af69d88dSmrg    def c_public_declarations(self, prefix):
260af69d88dSmrg        """Return the declarations of public entry points."""
261af69d88dSmrg        decls = []
262af69d88dSmrg        for ent in self.entries:
263af69d88dSmrg            if not self.need_entry_point(ent):
264af69d88dSmrg                continue
265af69d88dSmrg            export = self.api_call if not ent.hidden else ''
2669f464c52Smaya            if not ent.hidden or not self.lib_need_non_hidden_entries:
2679f464c52Smaya                decls.append(self._c_decl(ent, prefix, True, export) + ';')
268af69d88dSmrg
269af69d88dSmrg        return "\n".join(decls)
270af69d88dSmrg
271af69d88dSmrg    def c_mapi_table(self):
272af69d88dSmrg        """Return defines of the dispatch table size."""
273af69d88dSmrg        num_static_entries = self.entries[-1].slot + 1
274af69d88dSmrg        return ('#define MAPI_TABLE_NUM_STATIC %d\n' + \
275af69d88dSmrg                '#define MAPI_TABLE_NUM_DYNAMIC %d') % (
276af69d88dSmrg                        num_static_entries, ABI_NUM_DYNAMIC_ENTRIES)
277af69d88dSmrg
278af69d88dSmrg    def _c_function(self, ent, prefix, mangle=False, stringify=False):
279af69d88dSmrg        """Return the function name of an entry."""
280af69d88dSmrg        formats = {
281af69d88dSmrg                True: { True: '%s_STR(%s)', False: '%s(%s)' },
282af69d88dSmrg                False: { True: '"%s%s"', False: '%s%s' },
283af69d88dSmrg        }
284af69d88dSmrg        fmt = formats[prefix.isupper()][stringify]
285af69d88dSmrg        name = ent.name
286af69d88dSmrg        if mangle and ent.hidden:
287af69d88dSmrg            name = '_dispatch_stub_' + str(ent.slot)
288af69d88dSmrg        return fmt % (prefix, name)
289af69d88dSmrg
290af69d88dSmrg    def _c_function_call(self, ent, prefix):
291af69d88dSmrg        """Return the function name used for calling."""
292af69d88dSmrg        if ent.handcode:
293af69d88dSmrg            # _c_function does not handle this case
294af69d88dSmrg            formats = { True: '%s(%s)', False: '%s%s' }
295af69d88dSmrg            fmt = formats[prefix.isupper()]
296af69d88dSmrg            name = fmt % (prefix, ent.handcode)
297af69d88dSmrg        elif self.need_entry_point(ent):
298af69d88dSmrg            name = self._c_function(ent, prefix, True)
299af69d88dSmrg        else:
300af69d88dSmrg            name = self._c_function(ent.alias, prefix, True)
301af69d88dSmrg        return name
302af69d88dSmrg
303af69d88dSmrg    def _c_decl(self, ent, prefix, mangle=False, export=''):
304af69d88dSmrg        """Return the C declaration for the entry."""
305af69d88dSmrg        decl = '%s %s %s(%s)' % (ent.c_return(), self.api_entry,
306af69d88dSmrg                self._c_function(ent, prefix, mangle), ent.c_params())
307af69d88dSmrg        if export:
308af69d88dSmrg            decl = export + ' ' + decl
309af69d88dSmrg        if self.api_attrs:
310af69d88dSmrg            decl += ' ' + self.api_attrs
311af69d88dSmrg
312af69d88dSmrg        return decl
313af69d88dSmrg
314af69d88dSmrg    def _c_cast(self, ent):
315af69d88dSmrg        """Return the C cast for the entry."""
316af69d88dSmrg        cast = '%s (%s *)(%s)' % (
317af69d88dSmrg                ent.c_return(), self.api_entry, ent.c_params())
318af69d88dSmrg
319af69d88dSmrg        return cast
320af69d88dSmrg
321af69d88dSmrg    def c_public_dispatches(self, prefix, no_hidden):
322af69d88dSmrg        """Return the public dispatch functions."""
323af69d88dSmrg        dispatches = []
324af69d88dSmrg        for ent in self.entries:
325af69d88dSmrg            if ent.hidden and no_hidden:
326af69d88dSmrg                continue
327af69d88dSmrg
328af69d88dSmrg            if not self.need_entry_point(ent):
329af69d88dSmrg                continue
330af69d88dSmrg
331af69d88dSmrg            export = self.api_call if not ent.hidden else ''
332af69d88dSmrg
333af69d88dSmrg            proto = self._c_decl(ent, prefix, True, export)
334af69d88dSmrg            cast = self._c_cast(ent)
335af69d88dSmrg
336af69d88dSmrg            ret = ''
337af69d88dSmrg            if ent.ret:
338af69d88dSmrg                ret = 'return '
339af69d88dSmrg            stmt1 = self.indent
34001e04c3fSmrg            stmt1 += 'const struct _glapi_table *_tbl = %s();' % (
341af69d88dSmrg                    self.current_get)
342af69d88dSmrg            stmt2 = self.indent
343af69d88dSmrg            stmt2 += 'mapi_func _func = ((const mapi_func *) _tbl)[%d];' % (
344af69d88dSmrg                    ent.slot)
345af69d88dSmrg            stmt3 = self.indent
346af69d88dSmrg            stmt3 += '%s((%s) _func)(%s);' % (ret, cast, ent.c_args())
347af69d88dSmrg
348af69d88dSmrg            disp = '%s\n{\n%s\n%s\n%s\n}' % (proto, stmt1, stmt2, stmt3)
349af69d88dSmrg
350af69d88dSmrg            if ent.handcode:
351af69d88dSmrg                disp = '#if 0\n' + disp + '\n#endif'
352af69d88dSmrg
353af69d88dSmrg            dispatches.append(disp)
354af69d88dSmrg
355af69d88dSmrg        return '\n\n'.join(dispatches)
356af69d88dSmrg
357af69d88dSmrg    def c_public_initializer(self, prefix):
358af69d88dSmrg        """Return the initializer for public dispatch functions."""
359af69d88dSmrg        names = []
360af69d88dSmrg        for ent in self.entries:
361af69d88dSmrg            if ent.alias:
362af69d88dSmrg                continue
363af69d88dSmrg
364af69d88dSmrg            name = '%s(mapi_func) %s' % (self.indent,
365af69d88dSmrg                    self._c_function_call(ent, prefix))
366af69d88dSmrg            names.append(name)
367af69d88dSmrg
368af69d88dSmrg        return ',\n'.join(names)
369af69d88dSmrg
370af69d88dSmrg    def c_stub_string_pool(self):
371af69d88dSmrg        """Return the string pool for use by stubs."""
372af69d88dSmrg        # sort entries by their names
37301e04c3fSmrg        sorted_entries = sorted(self.entries, key=attrgetter('name'))
374af69d88dSmrg
375af69d88dSmrg        pool = []
376af69d88dSmrg        offsets = {}
377af69d88dSmrg        count = 0
378af69d88dSmrg        for ent in sorted_entries:
379af69d88dSmrg            offsets[ent] = count
380af69d88dSmrg            pool.append('%s' % (ent.name))
381af69d88dSmrg            count += len(ent.name) + 1
382af69d88dSmrg
383af69d88dSmrg        pool_str =  self.indent + '"' + \
384af69d88dSmrg                ('\\0"\n' + self.indent + '"').join(pool) + '";'
385af69d88dSmrg        return (pool_str, offsets)
386af69d88dSmrg
387af69d88dSmrg    def c_stub_initializer(self, prefix, pool_offsets):
388af69d88dSmrg        """Return the initializer for struct mapi_stub array."""
389af69d88dSmrg        stubs = []
390af69d88dSmrg        for ent in self.entries_sorted_by_names:
391af69d88dSmrg            stubs.append('%s{ (void *) %d, %d, NULL }' % (
392af69d88dSmrg                self.indent, pool_offsets[ent], ent.slot))
393af69d88dSmrg
394af69d88dSmrg        return ',\n'.join(stubs)
395af69d88dSmrg
396af69d88dSmrg    def c_noop_functions(self, prefix, warn_prefix):
397af69d88dSmrg        """Return the noop functions."""
398af69d88dSmrg        noops = []
399af69d88dSmrg        for ent in self.entries:
400af69d88dSmrg            if ent.alias:
401af69d88dSmrg                continue
402af69d88dSmrg
403af69d88dSmrg            proto = self._c_decl(ent, prefix, False, 'static')
404af69d88dSmrg
405af69d88dSmrg            stmt1 = self.indent;
406af69d88dSmrg            space = ''
407af69d88dSmrg            for t, n, a in ent.params:
408af69d88dSmrg                stmt1 += "%s(void) %s;" % (space, n)
409af69d88dSmrg                space = ' '
410af69d88dSmrg
411af69d88dSmrg            if ent.params:
412af69d88dSmrg                stmt1 += '\n';
413af69d88dSmrg
414af69d88dSmrg            stmt1 += self.indent + '%s(%s);' % (self.noop_warn,
415af69d88dSmrg                    self._c_function(ent, warn_prefix, False, True))
416af69d88dSmrg
417af69d88dSmrg            if ent.ret:
418af69d88dSmrg                stmt2 = self.indent + 'return (%s) 0;' % (ent.ret)
419af69d88dSmrg                noop = '%s\n{\n%s\n%s\n}' % (proto, stmt1, stmt2)
420af69d88dSmrg            else:
421af69d88dSmrg                noop = '%s\n{\n%s\n}' % (proto, stmt1)
422af69d88dSmrg
423af69d88dSmrg            noops.append(noop)
424af69d88dSmrg
425af69d88dSmrg        return '\n\n'.join(noops)
426af69d88dSmrg
427af69d88dSmrg    def c_noop_initializer(self, prefix, use_generic):
428af69d88dSmrg        """Return an initializer for the noop dispatch table."""
429af69d88dSmrg        entries = [self._c_function(ent, prefix)
430af69d88dSmrg                for ent in self.entries if not ent.alias]
431af69d88dSmrg        if use_generic:
432af69d88dSmrg            entries = [self.noop_generic] * len(entries)
433af69d88dSmrg
434af69d88dSmrg        entries.extend([self.noop_generic] * ABI_NUM_DYNAMIC_ENTRIES)
435af69d88dSmrg
436af69d88dSmrg        pre = self.indent + '(mapi_func) '
437af69d88dSmrg        return pre + (',\n' + pre).join(entries)
438af69d88dSmrg
439af69d88dSmrg    def c_asm_gcc(self, prefix, no_hidden):
440af69d88dSmrg        asm = []
441af69d88dSmrg
442af69d88dSmrg        for ent in self.entries:
443af69d88dSmrg            if ent.hidden and no_hidden:
444af69d88dSmrg                continue
445af69d88dSmrg
446af69d88dSmrg            if not self.need_entry_point(ent):
447af69d88dSmrg                continue
448af69d88dSmrg
449af69d88dSmrg            name = self._c_function(ent, prefix, True, True)
450af69d88dSmrg
451af69d88dSmrg            if ent.handcode:
452af69d88dSmrg                asm.append('#if 0')
453af69d88dSmrg
454af69d88dSmrg            if ent.hidden:
455af69d88dSmrg                asm.append('".hidden "%s"\\n"' % (name))
456af69d88dSmrg
457af69d88dSmrg            if ent.alias and not (ent.alias.hidden and no_hidden):
458af69d88dSmrg                asm.append('".globl "%s"\\n"' % (name))
459af69d88dSmrg                asm.append('".set "%s", "%s"\\n"' % (name,
460af69d88dSmrg                    self._c_function(ent.alias, prefix, True, True)))
461af69d88dSmrg            else:
462af69d88dSmrg                asm.append('STUB_ASM_ENTRY(%s)"\\n"' % (name))
463af69d88dSmrg                asm.append('"\\t"STUB_ASM_CODE("%d")"\\n"' % (ent.slot))
464af69d88dSmrg
465af69d88dSmrg            if ent.handcode:
466af69d88dSmrg                asm.append('#endif')
467af69d88dSmrg            asm.append('')
468af69d88dSmrg
469af69d88dSmrg        return "\n".join(asm)
470af69d88dSmrg
471af69d88dSmrg    def output_for_lib(self):
47201e04c3fSmrg        print(self.c_notice())
473af69d88dSmrg
474af69d88dSmrg        if self.c_header:
47501e04c3fSmrg            print()
47601e04c3fSmrg            print(self.c_header)
477af69d88dSmrg
47801e04c3fSmrg        print()
47901e04c3fSmrg        print('#ifdef MAPI_TMP_DEFINES')
48001e04c3fSmrg        print(self.c_public_includes())
48101e04c3fSmrg        print()
4827ec681f3Smrg        print('#ifdef MemoryBarrier')
4837ec681f3Smrg        print('#undef MemoryBarrier')
4847ec681f3Smrg        print('#endif')
4857ec681f3Smrg        print()
48601e04c3fSmrg        print(self.c_public_declarations(self.prefix_lib))
48701e04c3fSmrg        print('#undef MAPI_TMP_DEFINES')
48801e04c3fSmrg        print('#endif /* MAPI_TMP_DEFINES */')
489af69d88dSmrg
490af69d88dSmrg        if self.lib_need_table_size:
49101e04c3fSmrg            print()
49201e04c3fSmrg            print('#ifdef MAPI_TMP_TABLE')
49301e04c3fSmrg            print(self.c_mapi_table())
49401e04c3fSmrg            print('#undef MAPI_TMP_TABLE')
49501e04c3fSmrg            print('#endif /* MAPI_TMP_TABLE */')
496af69d88dSmrg
497af69d88dSmrg        if self.lib_need_noop_array:
49801e04c3fSmrg            print()
49901e04c3fSmrg            print('#ifdef MAPI_TMP_NOOP_ARRAY')
50001e04c3fSmrg            print('#ifdef DEBUG')
50101e04c3fSmrg            print()
50201e04c3fSmrg            print(self.c_noop_functions(self.prefix_noop, self.prefix_warn))
50301e04c3fSmrg            print()
50401e04c3fSmrg            print('const mapi_func table_%s_array[] = {' % (self.prefix_noop))
50501e04c3fSmrg            print(self.c_noop_initializer(self.prefix_noop, False))
50601e04c3fSmrg            print('};')
50701e04c3fSmrg            print()
50801e04c3fSmrg            print('#else /* DEBUG */')
50901e04c3fSmrg            print()
51001e04c3fSmrg            print('const mapi_func table_%s_array[] = {' % (self.prefix_noop))
51101e04c3fSmrg            print(self.c_noop_initializer(self.prefix_noop, True))
51201e04c3fSmrg            print('};')
51301e04c3fSmrg            print()
51401e04c3fSmrg            print('#endif /* DEBUG */')
51501e04c3fSmrg            print('#undef MAPI_TMP_NOOP_ARRAY')
51601e04c3fSmrg            print('#endif /* MAPI_TMP_NOOP_ARRAY */')
517af69d88dSmrg
518af69d88dSmrg        if self.lib_need_stubs:
519af69d88dSmrg            pool, pool_offsets = self.c_stub_string_pool()
52001e04c3fSmrg            print()
52101e04c3fSmrg            print('#ifdef MAPI_TMP_PUBLIC_STUBS')
52201e04c3fSmrg            print('static const char public_string_pool[] =')
52301e04c3fSmrg            print(pool)
52401e04c3fSmrg            print()
52501e04c3fSmrg            print('static const struct mapi_stub public_stubs[] = {')
52601e04c3fSmrg            print(self.c_stub_initializer(self.prefix_lib, pool_offsets))
52701e04c3fSmrg            print('};')
52801e04c3fSmrg            print('#undef MAPI_TMP_PUBLIC_STUBS')
52901e04c3fSmrg            print('#endif /* MAPI_TMP_PUBLIC_STUBS */')
530af69d88dSmrg
531af69d88dSmrg        if self.lib_need_all_entries:
53201e04c3fSmrg            print()
53301e04c3fSmrg            print('#ifdef MAPI_TMP_PUBLIC_ENTRIES')
53401e04c3fSmrg            print(self.c_public_dispatches(self.prefix_lib, False))
53501e04c3fSmrg            print()
53601e04c3fSmrg            print('static const mapi_func public_entries[] = {')
53701e04c3fSmrg            print(self.c_public_initializer(self.prefix_lib))
53801e04c3fSmrg            print('};')
53901e04c3fSmrg            print('#undef MAPI_TMP_PUBLIC_ENTRIES')
54001e04c3fSmrg            print('#endif /* MAPI_TMP_PUBLIC_ENTRIES */')
54101e04c3fSmrg
54201e04c3fSmrg            print()
54301e04c3fSmrg            print('#ifdef MAPI_TMP_STUB_ASM_GCC')
54401e04c3fSmrg            print('__asm__(')
54501e04c3fSmrg            print(self.c_asm_gcc(self.prefix_lib, False))
54601e04c3fSmrg            print(');')
54701e04c3fSmrg            print('#undef MAPI_TMP_STUB_ASM_GCC')
54801e04c3fSmrg            print('#endif /* MAPI_TMP_STUB_ASM_GCC */')
549af69d88dSmrg
550af69d88dSmrg        if self.lib_need_non_hidden_entries:
551af69d88dSmrg            all_hidden = True
552af69d88dSmrg            for ent in self.entries:
553af69d88dSmrg                if not ent.hidden:
554af69d88dSmrg                    all_hidden = False
555af69d88dSmrg                    break
556af69d88dSmrg            if not all_hidden:
55701e04c3fSmrg                print()
55801e04c3fSmrg                print('#ifdef MAPI_TMP_PUBLIC_ENTRIES_NO_HIDDEN')
55901e04c3fSmrg                print(self.c_public_dispatches(self.prefix_lib, True))
56001e04c3fSmrg                print()
56101e04c3fSmrg                print('/* does not need public_entries */')
56201e04c3fSmrg                print('#undef MAPI_TMP_PUBLIC_ENTRIES_NO_HIDDEN')
56301e04c3fSmrg                print('#endif /* MAPI_TMP_PUBLIC_ENTRIES_NO_HIDDEN */')
56401e04c3fSmrg
56501e04c3fSmrg                print()
56601e04c3fSmrg                print('#ifdef MAPI_TMP_STUB_ASM_GCC_NO_HIDDEN')
56701e04c3fSmrg                print('__asm__(')
56801e04c3fSmrg                print(self.c_asm_gcc(self.prefix_lib, True))
56901e04c3fSmrg                print(');')
57001e04c3fSmrg                print('#undef MAPI_TMP_STUB_ASM_GCC_NO_HIDDEN')
57101e04c3fSmrg                print('#endif /* MAPI_TMP_STUB_ASM_GCC_NO_HIDDEN */')
572af69d88dSmrg
573af69d88dSmrgclass GLAPIPrinter(ABIPrinter):
574af69d88dSmrg    """OpenGL API Printer"""
575af69d88dSmrg
576af69d88dSmrg    def __init__(self, entries):
577af69d88dSmrg        for ent in entries:
578af69d88dSmrg            self._override_for_api(ent)
579af69d88dSmrg        super(GLAPIPrinter, self).__init__(entries)
580af69d88dSmrg
581af69d88dSmrg        self.api_defines = ['GL_GLEXT_PROTOTYPES']
582af69d88dSmrg        self.api_headers = ['"GL/gl.h"', '"GL/glext.h"']
583af69d88dSmrg        self.api_call = 'GLAPI'
584af69d88dSmrg        self.api_entry = 'APIENTRY'
585af69d88dSmrg        self.api_attrs = ''
586af69d88dSmrg
587af69d88dSmrg        self.lib_need_table_size = False
588af69d88dSmrg        self.lib_need_noop_array = False
589af69d88dSmrg        self.lib_need_stubs = False
590af69d88dSmrg        self.lib_need_all_entries = False
591af69d88dSmrg        self.lib_need_non_hidden_entries = True
592af69d88dSmrg
593af69d88dSmrg        self.prefix_lib = 'GLAPI_PREFIX'
594af69d88dSmrg        self.prefix_noop = 'noop'
595af69d88dSmrg        self.prefix_warn = self.prefix_lib
596af69d88dSmrg
597af69d88dSmrg        self.c_header = self._get_c_header()
598af69d88dSmrg
599af69d88dSmrg    def _override_for_api(self, ent):
600af69d88dSmrg        """Override attributes of an entry if necessary for this
601af69d88dSmrg        printer."""
602af69d88dSmrg        # By default, no override is necessary.
603af69d88dSmrg        pass
604af69d88dSmrg
605af69d88dSmrg    def _get_c_header(self):
606af69d88dSmrg        header = """#ifndef _GLAPI_TMP_H_
607af69d88dSmrg#define _GLAPI_TMP_H_
608af69d88dSmrg#define GLAPI_PREFIX(func)  gl##func
609af69d88dSmrg#define GLAPI_PREFIX_STR(func)  "gl"#func
610af69d88dSmrg
611af69d88dSmrgtypedef int GLclampx;
612af69d88dSmrg#endif /* _GLAPI_TMP_H_ */"""
613af69d88dSmrg
614af69d88dSmrg        return header
615af69d88dSmrg
616af69d88dSmrgclass SharedGLAPIPrinter(GLAPIPrinter):
617af69d88dSmrg    """Shared GLAPI API Printer"""
618af69d88dSmrg
619af69d88dSmrg    def __init__(self, entries):
620af69d88dSmrg        super(SharedGLAPIPrinter, self).__init__(entries)
621af69d88dSmrg
622af69d88dSmrg        self.lib_need_table_size = True
623af69d88dSmrg        self.lib_need_noop_array = True
624af69d88dSmrg        self.lib_need_stubs = True
625af69d88dSmrg        self.lib_need_all_entries = True
626af69d88dSmrg        self.lib_need_non_hidden_entries = False
627af69d88dSmrg
628af69d88dSmrg        self.prefix_lib = 'shared'
629af69d88dSmrg        self.prefix_warn = 'gl'
630af69d88dSmrg
631af69d88dSmrg    def _override_for_api(self, ent):
632af69d88dSmrg        ent.hidden = True
633af69d88dSmrg        ent.handcode = False
634af69d88dSmrg
635af69d88dSmrg    def _get_c_header(self):
636af69d88dSmrg        header = """#ifndef _GLAPI_TMP_H_
637af69d88dSmrg#define _GLAPI_TMP_H_
638af69d88dSmrgtypedef int GLclampx;
639af69d88dSmrg#endif /* _GLAPI_TMP_H_ */"""
640af69d88dSmrg
641af69d88dSmrg        return header
642af69d88dSmrg
643af69d88dSmrgdef parse_args():
64401e04c3fSmrg    printers = ['glapi', 'es1api', 'es2api', 'shared-glapi']
645af69d88dSmrg
6469f464c52Smaya    parser = OptionParser(usage='usage: %prog [options] <xml_file>')
647af69d88dSmrg    parser.add_option('-p', '--printer', dest='printer',
648af69d88dSmrg            help='printer to use: %s' % (", ".join(printers)))
649af69d88dSmrg
650af69d88dSmrg    options, args = parser.parse_args()
65101e04c3fSmrg    if not args or options.printer not in printers:
652af69d88dSmrg        parser.print_help()
653af69d88dSmrg        sys.exit(1)
654af69d88dSmrg
6559f464c52Smaya    if not args[0].endswith('.xml'):
6569f464c52Smaya        parser.print_help()
6579f464c52Smaya        sys.exit(1)
6589f464c52Smaya
659af69d88dSmrg    return (args[0], options)
660af69d88dSmrg
661af69d88dSmrgdef main():
662af69d88dSmrg    printers = {
663af69d88dSmrg        'glapi': GLAPIPrinter,
664af69d88dSmrg        'shared-glapi': SharedGLAPIPrinter,
665af69d88dSmrg    }
666af69d88dSmrg
667af69d88dSmrg    filename, options = parse_args()
668af69d88dSmrg
6699f464c52Smaya    entries = abi_parse_xml(filename)
670af69d88dSmrg    abi_sanity_check(entries)
671af69d88dSmrg
672af69d88dSmrg    printer = printers[options.printer](entries)
67301e04c3fSmrg    printer.output_for_lib()
674af69d88dSmrg
675af69d88dSmrgif __name__ == '__main__':
676af69d88dSmrg    main()
677