idl_gen_pnacl.py revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#!/usr/bin/env python
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file.
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""Generator for Pnacl Shim functions that bridges the calling conventions
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)between GCC and PNaCl.  """
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from datetime import datetime
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import difflib
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import glob
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import os
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import sys
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from idl_c_proto import CGen
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from idl_gen_wrapper import Interface, WrapperGen
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from idl_log import ErrOut, InfoOut, WarnOut
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from idl_option import GetOption, Option, ParseOptions
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from idl_parser import ParseFiles
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Option('pnaclshim', 'Name of the pnacl shim file.',
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       default='temp_pnacl_shim.c')
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Option('disable_pnacl_opt', 'Turn off optimization of pnacl shim.')
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PnaclGen(WrapperGen):
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """PnaclGen generates shim code to bridge the Gcc ABI with PNaCl.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  This subclass of WrapperGenerator takes the IDL sources and
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  generates shim methods for bridging the calling conventions between GCC
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  and PNaCl (LLVM). Some of the PPAPI methods do not need shimming, so
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  this will also detect those situations and provide direct access to the
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  original PPAPI methods (rather than the shim methods).
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __init__(self):
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WrapperGen.__init__(self,
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        'Pnacl',
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        'Pnacl Shim Gen',
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        'pnacl',
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        'Generate the PNaCl shim.')
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.cgen = CGen()
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._skip_opt = False
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._pnacl_attribute = '__attribute__((pnaclcall))'
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ############################################################
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def OwnHeaderFile(self):
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Return the header file that specifies the API of this wrapper.
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    We do not generate the header files.  """
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 'ppapi/generators/pnacl_shim.h'
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GetGuardStart(self):
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ('\n/* The PNaCl PPAPI shims are only needed on x86-64 and arm. */\n'
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            '#if defined(__x86_64__) || defined(__arm__)\n\n')
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GetGuardEnd(self):
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return '\n#endif\n'
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def InterfaceNeedsWrapper(self, iface, releases):
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Return true if the interface has ANY methods that need wrapping.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if self._skip_opt:
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return True
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for release in iface.GetUniqueReleases(releases):
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      version = iface.GetVersion(release)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if self.InterfaceVersionNeedsWrapping(iface, version):
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return True
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return False
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def InterfaceVersionNeedsWrapping(self, iface, version):
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Return true if the interface+version has ANY methods that
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    need wrapping.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if self._skip_opt:
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return True
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for member in iface.GetListOf('Member'):
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      release = member.GetRelease(version)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if self.MemberNeedsWrapping(member, release):
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return True
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return False
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def MemberNeedsWrapping(self, member, release):
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Return true if a particular member function at a particular
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    release needs wrapping.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if self._skip_opt:
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return True
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not member.InReleases([release]):
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return False
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret, name, array, args_spec = self.cgen.GetComponents(member,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                          release,
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                          'store')
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return self.TypeNeedsWrapping(ret, []) or self.ArgsNeedWrapping(args_spec)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def ArgsNeedWrapping(self, args):
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Return true if any parameter in the list needs wrapping.
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for arg in args:
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (type_str, name, array_dims, more_args) = arg
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if self.TypeNeedsWrapping(type_str, array_dims):
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return True
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return False
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def TypeNeedsWrapping(self, type_node, array_dims):
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Return true if a parameter type needs wrapping.
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Currently, this is true for byval aggregates.
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    is_aggregate = type_node.startswith('struct') or \
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        type_node.startswith('union')
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    is_reference = (type_node.find('*') != -1 or array_dims != [])
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return is_aggregate and not is_reference
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ############################################################
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GenerateWrapperForPPBMethod(self, iface, member):
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = []
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    func_prefix = self.WrapperMethodPrefix(iface.node, iface.release)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sig = self.cgen.GetSignature(member, iface.release, 'store',
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 func_prefix, False)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result.append('static %s\n%s {\n' % (self._pnacl_attribute, sig))
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result.append('  const struct %s *iface = %s.real_iface;\n' %
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  (iface.struct_name, self.GetWrapperInfoName(iface)))
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret, name, array, cspec = self.cgen.GetComponents(member,
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                      iface.release,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                      'store')
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret_str, args_str = self.GetReturnArgs(ret, cspec)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result.append('  %siface->%s(%s);\n}\n\n' % (ret_str,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 member.GetName(), args_str))
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GenerateWrapperForPPPMethod(self, iface, member):
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = []
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    func_prefix = self.WrapperMethodPrefix(iface.node, iface.release)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sig = self.cgen.GetSignature(member, iface.release, 'store',
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 func_prefix, False)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result.append('static %s {\n' % sig)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result.append('  const struct %s *iface = %s.real_iface;\n' %
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  (iface.struct_name, self.GetWrapperInfoName(iface)))
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    temp_fp = self.cgen.GetSignature(member, iface.release, 'return',
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     'temp_fp',
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     func_as_ptr=True,
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     ptr_prefix=self._pnacl_attribute + ' ',
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     include_name=False)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cast = self.cgen.GetSignature(member, iface.release, 'return',
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  prefix='',
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  func_as_ptr=True,
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  ptr_prefix=self._pnacl_attribute + ' ',
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  include_name=False)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result.append('  %s = ((%s)iface->%s);\n' % (temp_fp,
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 cast,
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 member.GetName()))
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret, name, array, cspec = self.cgen.GetComponents(member,
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                      iface.release,
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                      'store')
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret_str, args_str = self.GetReturnArgs(ret, cspec)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result.append('  %stemp_fp(%s);\n}\n\n' % (ret_str, args_str))
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GenerateRange(self, ast, releases, options):
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Generate shim code for a range of releases.
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._skip_opt = GetOption('disable_pnacl_opt')
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.SetOutputFile(GetOption('pnaclshim'))
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return WrapperGen.GenerateRange(self, ast, releases, options)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)pnaclgen = PnaclGen()
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)######################################################################
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Tests.
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Clean a string representing an object definition and return then string
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# as a single space delimited set of tokens.
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def CleanString(instr):
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instr = instr.strip()
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instr = instr.split()
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ' '.join(instr)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def PrintErrorDiff(old, new):
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  oldlines = old.split(';')
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  newlines = new.split(';')
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  d = difflib.Differ()
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  diff = d.compare(oldlines, newlines)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ErrOut.Log('Diff is:\n%s' % '\n'.join(diff))
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GetOldTestOutput(ast):
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Scan the top-level comments in the IDL file for comparison.
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  old = []
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for filenode in ast.GetListOf('File'):
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for node in filenode.GetChildren():
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      instr = node.GetOneOf('Comment')
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if not instr: continue
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      instr.Dump()
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      old.append(instr.GetName())
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CleanString(''.join(old))
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def TestFiles(filenames, test_releases):
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ast = ParseFiles(filenames)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  iface_releases = pnaclgen.DetermineInterfaces(ast, test_releases)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  new_output = CleanString(pnaclgen.GenerateWrapperForMethods(
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      iface_releases, comments=False))
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  old_output = GetOldTestOutput(ast)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if new_output != old_output:
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrintErrorDiff(old_output, new_output)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ErrOut.Log('Failed pnacl generator test.')
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 1
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else:
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InfoOut.Log('Passed pnacl generator test.')
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def Main(args):
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filenames = ParseOptions(args)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_releases = ['M13', 'M14', 'M15']
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if not filenames:
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    idldir = os.path.split(sys.argv[0])[0]
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    idldir = os.path.join(idldir, 'test_gen_pnacl', '*.idl')
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    filenames = glob.glob(idldir)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filenames = sorted(filenames)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if GetOption('test'):
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Run the tests.
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TestFiles(filenames, test_releases)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  # Otherwise, generate the output file (for potential use as golden file).
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ast = ParseFiles(filenames)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return pnaclgen.GenerateRange(ast, test_releases, filenames)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if __name__ == '__main__':
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  retval = Main(sys.argv[1:])
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sys.exit(retval)
243