Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. #!/usr/bin/env python
  2.  
  3. # Mesa 3-D graphics library
  4. #
  5. # Copyright (C) 2010 LunarG Inc.
  6. #
  7. # Permission is hereby granted, free of charge, to any person obtaining a
  8. # copy of this software and associated documentation files (the "Software"),
  9. # to deal in the Software without restriction, including without limitation
  10. # the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11. # and/or sell copies of the Software, and to permit persons to whom the
  12. # Software is furnished to do so, subject to the following conditions:
  13. #
  14. # The above copyright notice and this permission notice shall be included
  15. # in all copies or substantial portions of the Software.
  16. #
  17. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  20. # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22. # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  23. # DEALINGS IN THE SOFTWARE.
  24. #
  25. # Authors:
  26. #    Chia-I Wu <olv@lunarg.com>
  27.  
  28. import sys
  29. # make it possible to import glapi
  30. import os
  31. GLAPI = os.path.join(".", os.path.dirname(sys.argv[0]), "glapi/gen")
  32. sys.path.append(GLAPI)
  33.  
  34. import re
  35. from optparse import OptionParser
  36. import gl_XML
  37. import glX_XML
  38.  
  39.  
  40. # number of dynamic entries
  41. ABI_NUM_DYNAMIC_ENTRIES = 256
  42.  
  43. class ABIEntry(object):
  44.     """Represent an ABI entry."""
  45.  
  46.     _match_c_param = re.compile(
  47.             '^(?P<type>[\w\s*]+?)(?P<name>\w+)(\[(?P<array>\d+)\])?$')
  48.  
  49.     def __init__(self, cols, attrs, xml_data = None):
  50.         self._parse(cols)
  51.  
  52.         self.slot = attrs['slot']
  53.         self.hidden = attrs['hidden']
  54.         self.alias = attrs['alias']
  55.         self.handcode = attrs['handcode']
  56.         self.xml_data = xml_data
  57.  
  58.     def c_prototype(self):
  59.         return '%s %s(%s)' % (self.c_return(), self.name, self.c_params())
  60.  
  61.     def c_return(self):
  62.         ret = self.ret
  63.         if not ret:
  64.             ret = 'void'
  65.  
  66.         return ret
  67.  
  68.     def c_params(self):
  69.         """Return the parameter list used in the entry prototype."""
  70.         c_params = []
  71.         for t, n, a in self.params:
  72.             sep = '' if t.endswith('*') else ' '
  73.             arr = '[%d]' % a if a else ''
  74.             c_params.append(t + sep + n + arr)
  75.         if not c_params:
  76.             c_params.append('void')
  77.  
  78.         return ", ".join(c_params)
  79.  
  80.     def c_args(self):
  81.         """Return the argument list used in the entry invocation."""
  82.         c_args = []
  83.         for t, n, a in self.params:
  84.             c_args.append(n)
  85.  
  86.         return ", ".join(c_args)
  87.  
  88.     def _parse(self, cols):
  89.         ret = cols.pop(0)
  90.         if ret == 'void':
  91.             ret = None
  92.  
  93.         name = cols.pop(0)
  94.  
  95.         params = []
  96.         if not cols:
  97.             raise Exception(cols)
  98.         elif len(cols) == 1 and cols[0] == 'void':
  99.             pass
  100.         else:
  101.             for val in cols:
  102.                 params.append(self._parse_param(val))
  103.  
  104.         self.ret = ret
  105.         self.name = name
  106.         self.params = params
  107.  
  108.     def _parse_param(self, c_param):
  109.         m = self._match_c_param.match(c_param)
  110.         if not m:
  111.             raise Exception('unrecognized param ' + c_param)
  112.  
  113.         c_type = m.group('type').strip()
  114.         c_name = m.group('name')
  115.         c_array = m.group('array')
  116.         c_array = int(c_array) if c_array else 0
  117.  
  118.         return (c_type, c_name, c_array)
  119.  
  120.     def __str__(self):
  121.         return self.c_prototype()
  122.  
  123.     def __cmp__(self, other):
  124.         # compare slot, alias, and then name
  125.         res = cmp(self.slot, other.slot)
  126.         if not res:
  127.             if not self.alias:
  128.                 res = -1
  129.             elif not other.alias:
  130.                 res = 1
  131.  
  132.             if not res:
  133.                 res = cmp(self.name, other.name)
  134.  
  135.         return res
  136.  
  137. def abi_parse_xml(xml):
  138.     """Parse a GLAPI XML file for ABI entries."""
  139.     api = gl_XML.parse_GL_API(xml, glX_XML.glx_item_factory())
  140.  
  141.     entry_dict = {}
  142.     for func in api.functionIterateByOffset():
  143.         # make sure func.name appear first
  144.         entry_points = func.entry_points[:]
  145.         entry_points.remove(func.name)
  146.         entry_points.insert(0, func.name)
  147.  
  148.         for name in entry_points:
  149.             attrs = {
  150.                     'slot': func.offset,
  151.                     'hidden': not func.is_static_entry_point(name),
  152.                     'alias': None if name == func.name else func.name,
  153.                     'handcode': bool(func.has_different_protocol(name)),
  154.             }
  155.  
  156.             # post-process attrs
  157.             if attrs['alias']:
  158.                 try:
  159.                     alias = entry_dict[attrs['alias']]
  160.                 except KeyError:
  161.                     raise Exception('failed to alias %s' % attrs['alias'])
  162.                 if alias.alias:
  163.                     raise Exception('recursive alias %s' % ent.name)
  164.                 attrs['alias'] = alias
  165.             if attrs['handcode']:
  166.                 attrs['handcode'] = func.static_glx_name(name)
  167.             else:
  168.                 attrs['handcode'] = None
  169.  
  170.             if entry_dict.has_key(name):
  171.                 raise Exception('%s is duplicated' % (name))
  172.  
  173.             cols = []
  174.             cols.append(func.return_type)
  175.             cols.append(name)
  176.             params = func.get_parameter_string(name)
  177.             cols.extend([p.strip() for p in params.split(',')])
  178.  
  179.             ent = ABIEntry(cols, attrs, func)
  180.             entry_dict[ent.name] = ent
  181.  
  182.     entries = entry_dict.values()
  183.     entries.sort()
  184.  
  185.     return entries
  186.  
  187. def abi_parse_line(line):
  188.     cols = [col.strip() for col in line.split(',')]
  189.  
  190.     attrs = {
  191.             'slot': -1,
  192.             'hidden': False,
  193.             'alias': None,
  194.             'handcode': None,
  195.     }
  196.  
  197.     # extract attributes from the first column
  198.     vals = cols[0].split(':')
  199.     while len(vals) > 1:
  200.         val = vals.pop(0)
  201.         if val.startswith('slot='):
  202.             attrs['slot'] = int(val[5:])
  203.         elif val == 'hidden':
  204.             attrs['hidden'] = True
  205.         elif val.startswith('alias='):
  206.             attrs['alias'] = val[6:]
  207.         elif val.startswith('handcode='):
  208.             attrs['handcode'] = val[9:]
  209.         elif not val:
  210.             pass
  211.         else:
  212.             raise Exception('unknown attribute %s' % val)
  213.     cols[0] = vals[0]
  214.  
  215.     return (attrs, cols)
  216.  
  217. def abi_parse(filename):
  218.     """Parse a CSV file for ABI entries."""
  219.     fp = open(filename) if filename != '-' else sys.stdin
  220.     lines = [line.strip() for line in fp.readlines()
  221.             if not line.startswith('#') and line.strip()]
  222.  
  223.     entry_dict = {}
  224.     next_slot = 0
  225.     for line in lines:
  226.         attrs, cols = abi_parse_line(line)
  227.  
  228.         # post-process attributes
  229.         if attrs['alias']:
  230.             try:
  231.                 alias = entry_dict[attrs['alias']]
  232.             except KeyError:
  233.                 raise Exception('failed to alias %s' % attrs['alias'])
  234.             if alias.alias:
  235.                 raise Exception('recursive alias %s' % ent.name)
  236.             slot = alias.slot
  237.             attrs['alias'] = alias
  238.         else:
  239.             slot = next_slot
  240.             next_slot += 1
  241.  
  242.         if attrs['slot'] < 0:
  243.             attrs['slot'] = slot
  244.         elif attrs['slot'] != slot:
  245.             raise Exception('invalid slot in %s' % (line))
  246.  
  247.         ent = ABIEntry(cols, attrs)
  248.         if entry_dict.has_key(ent.name):
  249.             raise Exception('%s is duplicated' % (ent.name))
  250.         entry_dict[ent.name] = ent
  251.  
  252.     entries = entry_dict.values()
  253.     entries.sort()
  254.  
  255.     return entries
  256.  
  257. def abi_sanity_check(entries):
  258.     if not entries:
  259.         return
  260.  
  261.     all_names = []
  262.     last_slot = entries[-1].slot
  263.     i = 0
  264.     for slot in xrange(last_slot + 1):
  265.         if entries[i].slot != slot:
  266.             raise Exception('entries are not ordered by slots')
  267.         if entries[i].alias:
  268.             raise Exception('first entry of slot %d aliases %s'
  269.                     % (slot, entries[i].alias.name))
  270.         handcode = None
  271.         while i < len(entries) and entries[i].slot == slot:
  272.             ent = entries[i]
  273.             if not handcode and ent.handcode:
  274.                 handcode = ent.handcode
  275.             elif ent.handcode != handcode:
  276.                 raise Exception('two aliases with handcode %s != %s',
  277.                         ent.handcode, handcode)
  278.  
  279.             if ent.name in all_names:
  280.                 raise Exception('%s is duplicated' % (ent.name))
  281.             if ent.alias and ent.alias.name not in all_names:
  282.                 raise Exception('failed to alias %s' % (ent.alias.name))
  283.             all_names.append(ent.name)
  284.             i += 1
  285.     if i < len(entries):
  286.         raise Exception('there are %d invalid entries' % (len(entries) - 1))
  287.  
  288. class ABIPrinter(object):
  289.     """MAPI Printer"""
  290.  
  291.     def __init__(self, entries):
  292.         self.entries = entries
  293.  
  294.         # sort entries by their names
  295.         self.entries_sorted_by_names = self.entries[:]
  296.         self.entries_sorted_by_names.sort(lambda x, y: cmp(x.name, y.name))
  297.  
  298.         self.indent = ' ' * 3
  299.         self.noop_warn = 'noop_warn'
  300.         self.noop_generic = 'noop_generic'
  301.         self.current_get = 'entry_current_get'
  302.  
  303.         self.api_defines = []
  304.         self.api_headers = ['"KHR/khrplatform.h"']
  305.         self.api_call = 'KHRONOS_APICALL'
  306.         self.api_entry = 'KHRONOS_APIENTRY'
  307.         self.api_attrs = 'KHRONOS_APIATTRIBUTES'
  308.  
  309.         self.c_header = ''
  310.  
  311.         self.lib_need_table_size = True
  312.         self.lib_need_noop_array = True
  313.         self.lib_need_stubs = True
  314.         self.lib_need_all_entries = True
  315.         self.lib_need_non_hidden_entries = False
  316.  
  317.     def c_notice(self):
  318.         return '/* This file is automatically generated by mapi_abi.py.  Do not modify. */'
  319.  
  320.     def c_public_includes(self):
  321.         """Return includes of the client API headers."""
  322.         defines = ['#define ' + d for d in self.api_defines]
  323.         includes = ['#include ' + h for h in self.api_headers]
  324.         return "\n".join(defines + includes)
  325.  
  326.     def need_entry_point(self, ent):
  327.         """Return True if an entry point is needed for the entry."""
  328.         # non-handcode hidden aliases may share the entry they alias
  329.         use_alias = (ent.hidden and ent.alias and not ent.handcode)
  330.         return not use_alias
  331.  
  332.     def c_public_declarations(self, prefix):
  333.         """Return the declarations of public entry points."""
  334.         decls = []
  335.         for ent in self.entries:
  336.             if not self.need_entry_point(ent):
  337.                 continue
  338.             export = self.api_call if not ent.hidden else ''
  339.             decls.append(self._c_decl(ent, prefix, True, export) + ';')
  340.  
  341.         return "\n".join(decls)
  342.  
  343.     def c_mapi_table(self):
  344.         """Return defines of the dispatch table size."""
  345.         num_static_entries = self.entries[-1].slot + 1
  346.         return ('#define MAPI_TABLE_NUM_STATIC %d\n' + \
  347.                 '#define MAPI_TABLE_NUM_DYNAMIC %d') % (
  348.                         num_static_entries, ABI_NUM_DYNAMIC_ENTRIES)
  349.  
  350.     def c_mapi_table_initializer(self, prefix):
  351.         """Return the array initializer for mapi_table_fill."""
  352.         entries = [self._c_function(ent, prefix)
  353.                 for ent in self.entries if not ent.alias]
  354.         pre = self.indent + '(mapi_proc) '
  355.         return pre + (',\n' + pre).join(entries)
  356.  
  357.     def c_mapi_table_spec(self):
  358.         """Return the spec for mapi_init."""
  359.         specv1 = []
  360.         line = '"1'
  361.         for ent in self.entries:
  362.             if not ent.alias:
  363.                 line += '\\0"\n'
  364.                 specv1.append(line)
  365.                 line = '"'
  366.             line += '%s\\0' % ent.name
  367.         line += '";'
  368.         specv1.append(line)
  369.  
  370.         return self.indent + self.indent.join(specv1)
  371.  
  372.     def _c_function(self, ent, prefix, mangle=False, stringify=False):
  373.         """Return the function name of an entry."""
  374.         formats = {
  375.                 True: { True: '%s_STR(%s)', False: '%s(%s)' },
  376.                 False: { True: '"%s%s"', False: '%s%s' },
  377.         }
  378.         fmt = formats[prefix.isupper()][stringify]
  379.         name = ent.name
  380.         if mangle and ent.hidden:
  381.             name = '_dispatch_stub_' + str(ent.slot)
  382.         return fmt % (prefix, name)
  383.  
  384.     def _c_function_call(self, ent, prefix):
  385.         """Return the function name used for calling."""
  386.         if ent.handcode:
  387.             # _c_function does not handle this case
  388.             formats = { True: '%s(%s)', False: '%s%s' }
  389.             fmt = formats[prefix.isupper()]
  390.             name = fmt % (prefix, ent.handcode)
  391.         elif self.need_entry_point(ent):
  392.             name = self._c_function(ent, prefix, True)
  393.         else:
  394.             name = self._c_function(ent.alias, prefix, True)
  395.         return name
  396.  
  397.     def _c_decl(self, ent, prefix, mangle=False, export=''):
  398.         """Return the C declaration for the entry."""
  399.         decl = '%s %s %s(%s)' % (ent.c_return(), self.api_entry,
  400.                 self._c_function(ent, prefix, mangle), ent.c_params())
  401.         if export:
  402.             decl = export + ' ' + decl
  403.         if self.api_attrs:
  404.             decl += ' ' + self.api_attrs
  405.  
  406.         return decl
  407.  
  408.     def _c_cast(self, ent):
  409.         """Return the C cast for the entry."""
  410.         cast = '%s (%s *)(%s)' % (
  411.                 ent.c_return(), self.api_entry, ent.c_params())
  412.  
  413.         return cast
  414.  
  415.     def c_private_declarations(self, prefix):
  416.         """Return the declarations of private functions."""
  417.         decls = [self._c_decl(ent, prefix) + ';'
  418.                 for ent in self.entries if not ent.alias]
  419.  
  420.         return "\n".join(decls)
  421.  
  422.     def c_public_dispatches(self, prefix, no_hidden):
  423.         """Return the public dispatch functions."""
  424.         dispatches = []
  425.         for ent in self.entries:
  426.             if ent.hidden and no_hidden:
  427.                 continue
  428.  
  429.             if not self.need_entry_point(ent):
  430.                 continue
  431.  
  432.             export = self.api_call if not ent.hidden else ''
  433.  
  434.             proto = self._c_decl(ent, prefix, True, export)
  435.             cast = self._c_cast(ent)
  436.  
  437.             ret = ''
  438.             if ent.ret:
  439.                 ret = 'return '
  440.             stmt1 = self.indent
  441.             stmt1 += 'const struct mapi_table *_tbl = %s();' % (
  442.                     self.current_get)
  443.             stmt2 = self.indent
  444.             stmt2 += 'mapi_func _func = ((const mapi_func *) _tbl)[%d];' % (
  445.                     ent.slot)
  446.             stmt3 = self.indent
  447.             stmt3 += '%s((%s) _func)(%s);' % (ret, cast, ent.c_args())
  448.  
  449.             disp = '%s\n{\n%s\n%s\n%s\n}' % (proto, stmt1, stmt2, stmt3)
  450.  
  451.             if ent.handcode:
  452.                 disp = '#if 0\n' + disp + '\n#endif'
  453.  
  454.             dispatches.append(disp)
  455.  
  456.         return '\n\n'.join(dispatches)
  457.  
  458.     def c_public_initializer(self, prefix):
  459.         """Return the initializer for public dispatch functions."""
  460.         names = []
  461.         for ent in self.entries:
  462.             if ent.alias:
  463.                 continue
  464.  
  465.             name = '%s(mapi_func) %s' % (self.indent,
  466.                     self._c_function_call(ent, prefix))
  467.             names.append(name)
  468.  
  469.         return ',\n'.join(names)
  470.  
  471.     def c_stub_string_pool(self):
  472.         """Return the string pool for use by stubs."""
  473.         # sort entries by their names
  474.         sorted_entries = self.entries[:]
  475.         sorted_entries.sort(lambda x, y: cmp(x.name, y.name))
  476.  
  477.         pool = []
  478.         offsets = {}
  479.         count = 0
  480.         for ent in sorted_entries:
  481.             offsets[ent] = count
  482.             pool.append('%s' % (ent.name))
  483.             count += len(ent.name) + 1
  484.  
  485.         pool_str =  self.indent + '"' + \
  486.                 ('\\0"\n' + self.indent + '"').join(pool) + '";'
  487.         return (pool_str, offsets)
  488.  
  489.     def c_stub_initializer(self, prefix, pool_offsets):
  490.         """Return the initializer for struct mapi_stub array."""
  491.         stubs = []
  492.         for ent in self.entries_sorted_by_names:
  493.             stubs.append('%s{ (void *) %d, %d, NULL }' % (
  494.                 self.indent, pool_offsets[ent], ent.slot))
  495.  
  496.         return ',\n'.join(stubs)
  497.  
  498.     def c_noop_functions(self, prefix, warn_prefix):
  499.         """Return the noop functions."""
  500.         noops = []
  501.         for ent in self.entries:
  502.             if ent.alias:
  503.                 continue
  504.  
  505.             proto = self._c_decl(ent, prefix, False, 'static')
  506.  
  507.             stmt1 = self.indent;
  508.             space = ''
  509.             for t, n, a in ent.params:
  510.                 stmt1 += "%s(void) %s;" % (space, n)
  511.                 space = ' '
  512.  
  513.             if ent.params:
  514.                 stmt1 += '\n';
  515.  
  516.             stmt1 += self.indent + '%s(%s);' % (self.noop_warn,
  517.                     self._c_function(ent, warn_prefix, False, True))
  518.  
  519.             if ent.ret:
  520.                 stmt2 = self.indent + 'return (%s) 0;' % (ent.ret)
  521.                 noop = '%s\n{\n%s\n%s\n}' % (proto, stmt1, stmt2)
  522.             else:
  523.                 noop = '%s\n{\n%s\n}' % (proto, stmt1)
  524.  
  525.             noops.append(noop)
  526.  
  527.         return '\n\n'.join(noops)
  528.  
  529.     def c_noop_initializer(self, prefix, use_generic):
  530.         """Return an initializer for the noop dispatch table."""
  531.         entries = [self._c_function(ent, prefix)
  532.                 for ent in self.entries if not ent.alias]
  533.         if use_generic:
  534.             entries = [self.noop_generic] * len(entries)
  535.  
  536.         entries.extend([self.noop_generic] * ABI_NUM_DYNAMIC_ENTRIES)
  537.  
  538.         pre = self.indent + '(mapi_func) '
  539.         return pre + (',\n' + pre).join(entries)
  540.  
  541.     def c_asm_gcc(self, prefix, no_hidden):
  542.         asm = []
  543.  
  544.         for ent in self.entries:
  545.             if ent.hidden and no_hidden:
  546.                 continue
  547.  
  548.             if not self.need_entry_point(ent):
  549.                 continue
  550.  
  551.             name = self._c_function(ent, prefix, True, True)
  552.  
  553.             if ent.handcode:
  554.                 asm.append('#if 0')
  555.  
  556.             if ent.hidden:
  557.                 asm.append('".hidden "%s"\\n"' % (name))
  558.  
  559.             if ent.alias and not (ent.alias.hidden and no_hidden):
  560.                 asm.append('".globl "%s"\\n"' % (name))
  561.                 asm.append('".set "%s", "%s"\\n"' % (name,
  562.                     self._c_function(ent.alias, prefix, True, True)))
  563.             else:
  564.                 asm.append('STUB_ASM_ENTRY(%s)"\\n"' % (name))
  565.                 asm.append('"\\t"STUB_ASM_CODE("%d")"\\n"' % (ent.slot))
  566.  
  567.             if ent.handcode:
  568.                 asm.append('#endif')
  569.             asm.append('')
  570.  
  571.         return "\n".join(asm)
  572.  
  573.     def output_for_lib(self):
  574.         print self.c_notice()
  575.  
  576.         if self.c_header:
  577.             print
  578.             print self.c_header
  579.  
  580.         print
  581.         print '#ifdef MAPI_TMP_DEFINES'
  582.         print self.c_public_includes()
  583.         print
  584.         print self.c_public_declarations(self.prefix_lib)
  585.         print '#undef MAPI_TMP_DEFINES'
  586.         print '#endif /* MAPI_TMP_DEFINES */'
  587.  
  588.         if self.lib_need_table_size:
  589.             print
  590.             print '#ifdef MAPI_TMP_TABLE'
  591.             print self.c_mapi_table()
  592.             print '#undef MAPI_TMP_TABLE'
  593.             print '#endif /* MAPI_TMP_TABLE */'
  594.  
  595.         if self.lib_need_noop_array:
  596.             print
  597.             print '#ifdef MAPI_TMP_NOOP_ARRAY'
  598.             print '#ifdef DEBUG'
  599.             print
  600.             print self.c_noop_functions(self.prefix_noop, self.prefix_warn)
  601.             print
  602.             print 'const mapi_func table_%s_array[] = {' % (self.prefix_noop)
  603.             print self.c_noop_initializer(self.prefix_noop, False)
  604.             print '};'
  605.             print
  606.             print '#else /* DEBUG */'
  607.             print
  608.             print 'const mapi_func table_%s_array[] = {' % (self.prefix_noop)
  609.             print self.c_noop_initializer(self.prefix_noop, True)
  610.             print '};'
  611.             print
  612.             print '#endif /* DEBUG */'
  613.             print '#undef MAPI_TMP_NOOP_ARRAY'
  614.             print '#endif /* MAPI_TMP_NOOP_ARRAY */'
  615.  
  616.         if self.lib_need_stubs:
  617.             pool, pool_offsets = self.c_stub_string_pool()
  618.             print
  619.             print '#ifdef MAPI_TMP_PUBLIC_STUBS'
  620.             print 'static const char public_string_pool[] ='
  621.             print pool
  622.             print
  623.             print 'static const struct mapi_stub public_stubs[] = {'
  624.             print self.c_stub_initializer(self.prefix_lib, pool_offsets)
  625.             print '};'
  626.             print '#undef MAPI_TMP_PUBLIC_STUBS'
  627.             print '#endif /* MAPI_TMP_PUBLIC_STUBS */'
  628.  
  629.         if self.lib_need_all_entries:
  630.             print
  631.             print '#ifdef MAPI_TMP_PUBLIC_ENTRIES'
  632.             print self.c_public_dispatches(self.prefix_lib, False)
  633.             print
  634.             print 'static const mapi_func public_entries[] = {'
  635.             print self.c_public_initializer(self.prefix_lib)
  636.             print '};'
  637.             print '#undef MAPI_TMP_PUBLIC_ENTRIES'
  638.             print '#endif /* MAPI_TMP_PUBLIC_ENTRIES */'
  639.  
  640.             print
  641.             print '#ifdef MAPI_TMP_STUB_ASM_GCC'
  642.             print '__asm__('
  643.             print self.c_asm_gcc(self.prefix_lib, False)
  644.             print ');'
  645.             print '#undef MAPI_TMP_STUB_ASM_GCC'
  646.             print '#endif /* MAPI_TMP_STUB_ASM_GCC */'
  647.  
  648.         if self.lib_need_non_hidden_entries:
  649.             all_hidden = True
  650.             for ent in self.entries:
  651.                 if not ent.hidden:
  652.                     all_hidden = False
  653.                     break
  654.             if not all_hidden:
  655.                 print
  656.                 print '#ifdef MAPI_TMP_PUBLIC_ENTRIES_NO_HIDDEN'
  657.                 print self.c_public_dispatches(self.prefix_lib, True)
  658.                 print
  659.                 print '/* does not need public_entries */'
  660.                 print '#undef MAPI_TMP_PUBLIC_ENTRIES_NO_HIDDEN'
  661.                 print '#endif /* MAPI_TMP_PUBLIC_ENTRIES_NO_HIDDEN */'
  662.  
  663.                 print
  664.                 print '#ifdef MAPI_TMP_STUB_ASM_GCC_NO_HIDDEN'
  665.                 print '__asm__('
  666.                 print self.c_asm_gcc(self.prefix_lib, True)
  667.                 print ');'
  668.                 print '#undef MAPI_TMP_STUB_ASM_GCC_NO_HIDDEN'
  669.                 print '#endif /* MAPI_TMP_STUB_ASM_GCC_NO_HIDDEN */'
  670.  
  671.     def output_for_app(self):
  672.         print self.c_notice()
  673.         print
  674.         print self.c_private_declarations(self.prefix_app)
  675.         print
  676.         print '#ifdef API_TMP_DEFINE_SPEC'
  677.         print
  678.         print 'static const char %s_spec[] =' % (self.prefix_app)
  679.         print self.c_mapi_table_spec()
  680.         print
  681.         print 'static const mapi_proc %s_procs[] = {' % (self.prefix_app)
  682.         print self.c_mapi_table_initializer(self.prefix_app)
  683.         print '};'
  684.         print
  685.         print '#endif /* API_TMP_DEFINE_SPEC */'
  686.  
  687. class GLAPIPrinter(ABIPrinter):
  688.     """OpenGL API Printer"""
  689.  
  690.     def __init__(self, entries):
  691.         for ent in entries:
  692.             self._override_for_api(ent)
  693.         super(GLAPIPrinter, self).__init__(entries)
  694.  
  695.         self.api_defines = ['GL_GLEXT_PROTOTYPES']
  696.         self.api_headers = ['"GL/gl.h"', '"GL/glext.h"']
  697.         self.api_call = 'GLAPI'
  698.         self.api_entry = 'APIENTRY'
  699.         self.api_attrs = ''
  700.  
  701.         self.lib_need_table_size = False
  702.         self.lib_need_noop_array = False
  703.         self.lib_need_stubs = False
  704.         self.lib_need_all_entries = False
  705.         self.lib_need_non_hidden_entries = True
  706.  
  707.         self.prefix_lib = 'GLAPI_PREFIX'
  708.         self.prefix_app = '_mesa_'
  709.         self.prefix_noop = 'noop'
  710.         self.prefix_warn = self.prefix_lib
  711.  
  712.         self.c_header = self._get_c_header()
  713.  
  714.     def _override_for_api(self, ent):
  715.         """Override attributes of an entry if necessary for this
  716.        printer."""
  717.         # By default, no override is necessary.
  718.         pass
  719.  
  720.     def _get_c_header(self):
  721.         header = """#ifndef _GLAPI_TMP_H_
  722. #define _GLAPI_TMP_H_
  723. #ifdef USE_MGL_NAMESPACE
  724. #define GLAPI_PREFIX(func)  mgl##func
  725. #define GLAPI_PREFIX_STR(func)  "mgl"#func
  726. #else
  727. #define GLAPI_PREFIX(func)  gl##func
  728. #define GLAPI_PREFIX_STR(func)  "gl"#func
  729. #endif /* USE_MGL_NAMESPACE */
  730.  
  731. typedef int GLclampx;
  732. #endif /* _GLAPI_TMP_H_ */"""
  733.  
  734.         return header
  735.  
  736. class ES1APIPrinter(GLAPIPrinter):
  737.     """OpenGL ES 1.x API Printer"""
  738.  
  739.     def __init__(self, entries):
  740.         super(ES1APIPrinter, self).__init__(entries)
  741.         self.prefix_lib = 'gl'
  742.         self.prefix_warn = 'gl'
  743.  
  744.     def _override_for_api(self, ent):
  745.         if ent.xml_data is None:
  746.             raise Exception('ES2 API printer requires XML input')
  747.         ent.hidden = ent.name not in \
  748.             ent.xml_data.entry_points_for_api_version('es1')
  749.         ent.handcode = False
  750.  
  751.     def _get_c_header(self):
  752.         header = """#ifndef _GLAPI_TMP_H_
  753. #define _GLAPI_TMP_H_
  754. typedef int GLclampx;
  755. #endif /* _GLAPI_TMP_H_ */"""
  756.  
  757.         return header
  758.  
  759. class ES2APIPrinter(GLAPIPrinter):
  760.     """OpenGL ES 2.x API Printer"""
  761.  
  762.     def __init__(self, entries):
  763.         super(ES2APIPrinter, self).__init__(entries)
  764.         self.prefix_lib = 'gl'
  765.         self.prefix_warn = 'gl'
  766.  
  767.     def _override_for_api(self, ent):
  768.         if ent.xml_data is None:
  769.             raise Exception('ES2 API printer requires XML input')
  770.         ent.hidden = ent.name not in \
  771.             ent.xml_data.entry_points_for_api_version('es2')
  772.         ent.handcode = False
  773.  
  774.     def _get_c_header(self):
  775.         header = """#ifndef _GLAPI_TMP_H_
  776. #define _GLAPI_TMP_H_
  777. typedef int GLclampx;
  778. #endif /* _GLAPI_TMP_H_ */"""
  779.  
  780.         return header
  781.  
  782. class SharedGLAPIPrinter(GLAPIPrinter):
  783.     """Shared GLAPI API Printer"""
  784.  
  785.     def __init__(self, entries):
  786.         super(SharedGLAPIPrinter, self).__init__(entries)
  787.  
  788.         self.lib_need_table_size = True
  789.         self.lib_need_noop_array = True
  790.         self.lib_need_stubs = True
  791.         self.lib_need_all_entries = True
  792.         self.lib_need_non_hidden_entries = False
  793.  
  794.         self.prefix_lib = 'shared'
  795.         self.prefix_warn = 'gl'
  796.  
  797.     def _override_for_api(self, ent):
  798.         ent.hidden = True
  799.         ent.handcode = False
  800.  
  801.     def _get_c_header(self):
  802.         header = """#ifndef _GLAPI_TMP_H_
  803. #define _GLAPI_TMP_H_
  804. typedef int GLclampx;
  805. #endif /* _GLAPI_TMP_H_ */"""
  806.  
  807.         return header
  808.  
  809. class VGAPIPrinter(ABIPrinter):
  810.     """OpenVG API Printer"""
  811.  
  812.     def __init__(self, entries):
  813.         super(VGAPIPrinter, self).__init__(entries)
  814.  
  815.         self.api_defines = ['VG_VGEXT_PROTOTYPES']
  816.         self.api_headers = ['"VG/openvg.h"', '"VG/vgext.h"']
  817.         self.api_call = 'VG_API_CALL'
  818.         self.api_entry = 'VG_API_ENTRY'
  819.         self.api_attrs = 'VG_API_EXIT'
  820.  
  821.         self.prefix_lib = 'vg'
  822.         self.prefix_app = 'vega'
  823.         self.prefix_noop = 'noop'
  824.         self.prefix_warn = 'vg'
  825.  
  826. def parse_args():
  827.     printers = ['vgapi', 'glapi', 'es1api', 'es2api', 'shared-glapi']
  828.     modes = ['lib', 'app']
  829.  
  830.     parser = OptionParser(usage='usage: %prog [options] <filename>')
  831.     parser.add_option('-p', '--printer', dest='printer',
  832.             help='printer to use: %s' % (", ".join(printers)))
  833.     parser.add_option('-m', '--mode', dest='mode',
  834.             help='target user: %s' % (", ".join(modes)))
  835.  
  836.     options, args = parser.parse_args()
  837.     if not args or options.printer not in printers or \
  838.             options.mode not in modes:
  839.         parser.print_help()
  840.         sys.exit(1)
  841.  
  842.     return (args[0], options)
  843.  
  844. def main():
  845.     printers = {
  846.         'vgapi': VGAPIPrinter,
  847.         'glapi': GLAPIPrinter,
  848.         'es1api': ES1APIPrinter,
  849.         'es2api': ES2APIPrinter,
  850.         'shared-glapi': SharedGLAPIPrinter,
  851.     }
  852.  
  853.     filename, options = parse_args()
  854.  
  855.     if filename.endswith('.xml'):
  856.         entries = abi_parse_xml(filename)
  857.     else:
  858.         entries = abi_parse(filename)
  859.     abi_sanity_check(entries)
  860.  
  861.     printer = printers[options.printer](entries)
  862.     if options.mode == 'lib':
  863.         printer.output_for_lib()
  864.     else:
  865.         printer.output_for_app()
  866.  
  867. if __name__ == '__main__':
  868.     main()
  869.