12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#!/usr/bin/env python
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved.
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# found in the LICENSE file.
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)""" Generator for C++ style thunks """
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import glob
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import os
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import re
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import sys
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from idl_log import ErrOut, InfoOut, WarnOut
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from idl_node import IDLAttribute, IDLNode
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from idl_ast import IDLAst
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from idl_option import GetOption, Option, ParseOptions
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from idl_outfile import IDLOutFile
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from idl_parser import ParseFiles
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from idl_c_proto import CGen, GetNodeComments, CommentLines, Comment
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from idl_generator import Generator, GeneratorByFile
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Option('thunkroot', 'Base directory of output',
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       default=os.path.join('..', 'thunk'))
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class TGenError(Exception):
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def __init__(self, msg):
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.value = msg
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def __str__(self):
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return repr(self.value)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class ThunkBodyMetadata(object):
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  """Metadata about thunk body. Used for selecting which headers to emit."""
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def __init__(self):
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._apis = set()
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self._builtin_includes = set()
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._includes = set()
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def AddApi(self, api):
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._apis.add(api)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def Apis(self):
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return self._apis
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def AddInclude(self, include):
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._includes.add(include)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def Includes(self):
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return self._includes
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  def AddBuiltinInclude(self, include):
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self._builtin_includes.add(include)
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  def BuiltinIncludes(self):
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return self._builtin_includes
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def _GetBaseFileName(filenode):
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  """Returns the base name for output files, given the filenode.
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Examples:
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    'dev/ppb_find_dev.h' -> 'ppb_find_dev'
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    'trusted/ppb_buffer_trusted.h' -> 'ppb_buffer_trusted'
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  """
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  path, name = os.path.split(filenode.GetProperty('NAME'))
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  name = os.path.splitext(name)[0]
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return name
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def _GetHeaderFileName(filenode):
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  """Returns the name for the header for this file."""
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  path, name = os.path.split(filenode.GetProperty('NAME'))
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  name = os.path.splitext(name)[0]
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if path:
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    header = "ppapi/c/%s/%s.h" % (path, name)
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else:
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    header = "ppapi/c/%s.h" % name
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return header
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def _GetThunkFileName(filenode, relpath):
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  """Returns the thunk file name."""
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  path = os.path.split(filenode.GetProperty('NAME'))[0]
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  name = _GetBaseFileName(filenode)
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  # We don't reattach the path for thunk.
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if relpath: name = os.path.join(relpath, name)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  name = '%s%s' % (name, '_thunk.cc')
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return name
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def _StripFileName(filenode):
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  """Strips path  and dev, trusted, and private suffixes from the file name."""
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  api_basename = _GetBaseFileName(filenode)
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if api_basename.endswith('_dev'):
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    api_basename = api_basename[:-len('_dev')]
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if api_basename.endswith('_trusted'):
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    api_basename = api_basename[:-len('_trusted')]
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if api_basename.endswith('_private'):
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    api_basename = api_basename[:-len('_private')]
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return api_basename
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def _StripApiName(api_name):
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  """Strips Dev, Private, and Trusted suffixes from the API name."""
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if api_name.endswith('Trusted'):
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    api_name = api_name[:-len('Trusted')]
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if api_name.endswith('_Dev'):
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    api_name = api_name[:-len('_Dev')]
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if api_name.endswith('_Private'):
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    api_name = api_name[:-len('_Private')]
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return api_name
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def _MakeEnterLine(filenode, interface, member, arg, handle_errors, callback,
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   meta):
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  """Returns an EnterInstance/EnterResource string for a function."""
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  api_name = _StripApiName(interface.GetName()) + '_API'
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if member.GetProperty('api'):  # Override API name.
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    manually_provided_api = True
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    # TODO(teravest): Automatically guess the API header file.
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    api_name = member.GetProperty('api')
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  else:
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    manually_provided_api = False
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if arg[0] == 'PP_Instance':
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if callback is None:
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      arg_string = arg[1]
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    else:
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      arg_string = '%s, %s' % (arg[1], callback)
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if interface.GetProperty('singleton') or member.GetProperty('singleton'):
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if not manually_provided_api:
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        meta.AddApi('ppapi/thunk/%s_api.h' % _StripFileName(filenode))
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return 'EnterInstanceAPI<%s> enter(%s);' % (api_name, arg_string)
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else:
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return 'EnterInstance enter(%s);' % arg_string
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  elif arg[0] == 'PP_Resource':
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    enter_type = 'EnterResource<%s>' % api_name
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if not manually_provided_api:
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      meta.AddApi('ppapi/thunk/%s_api.h' % _StripFileName(filenode))
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if callback is None:
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return '%s enter(%s, %s);' % (enter_type, arg[1],
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    str(handle_errors).lower())
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else:
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return '%s enter(%s, %s, %s);' % (enter_type, arg[1],
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        callback,
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        str(handle_errors).lower())
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else:
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    raise TGenError("Unknown type for _MakeEnterLine: %s" % arg[0])
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def _GetShortName(interface, filter_suffixes):
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  """Return a shorter interface name that matches Is* and Create* functions."""
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  parts = interface.GetName().split('_')[1:]
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  tail = parts[len(parts) - 1]
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if tail in filter_suffixes:
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    parts = parts[:-1]
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return ''.join(parts)
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def _IsTypeCheck(interface, node, args):
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  """Returns true if node represents a type-checking function."""
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if len(args) == 0 or args[0][0] != 'PP_Resource':
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return False
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return node.GetName() == 'Is%s' % _GetShortName(interface, ['Dev', 'Private'])
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def _GetCreateFuncName(interface):
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  """Returns the creation function name for an interface."""
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 'Create%s' % _GetShortName(interface, ['Dev'])
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def _GetDefaultFailureValue(t):
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  """Returns the default failure value for a given type.
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Returns None if no default failure value exists for the type.
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  """
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  values = {
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      'PP_Bool': 'PP_FALSE',
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      'PP_Resource': '0',
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      'struct PP_Var': 'PP_MakeUndefined()',
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      'float': '0.0f',
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      'int32_t': 'enter.retval()',
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      'uint16_t': '0',
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      'uint32_t': '0',
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      'uint64_t': '0',
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      'void*': 'NULL'
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if t in values:
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return values[t]
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return None
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def _MakeCreateMemberBody(interface, member, args):
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  """Returns the body of a Create() function.
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Args:
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    interface - IDLNode for the interface
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    member - IDLNode for member function
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    args - List of arguments for the Create() function
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  """
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if args[0][0] == 'PP_Resource':
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    body = 'Resource* object =\n'
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    body += '    PpapiGlobals::Get()->GetResourceTracker()->'
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    body += 'GetResource(%s);\n' % args[0][1]
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    body += 'if (!object)\n'
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    body += '  return 0;\n'
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    body += 'EnterResourceCreation enter(object->pp_instance());\n'
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  elif args[0][0] == 'PP_Instance':
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    body = 'EnterResourceCreation enter(%s);\n' % args[0][1]
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else:
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    raise TGenError('Unknown arg type for Create(): %s' % args[0][0])
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  body += 'if (enter.failed())\n'
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  body += '  return 0;\n'
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  arg_list = ', '.join([a[1] for a in args])
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if member.GetProperty('create_func'):
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    create_func = member.GetProperty('create_func')
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else:
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    create_func = _GetCreateFuncName(interface)
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  body += 'return enter.functions()->%s(%s);' % (create_func,
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                 arg_list)
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return body
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def _GetOutputParams(member, release):
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  """Returns output parameters (and their types) for a member function.
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Args:
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    member - IDLNode for the member function
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    release - Release to get output parameters for
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Returns:
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    A list of name strings for all output parameters of the member
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    function.
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  """
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  out_params = []
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callnode = member.GetOneOf('Callspec')
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if callnode:
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    cgen = CGen()
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    for param in callnode.GetListOf('Param'):
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      mode = cgen.GetParamMode(param)
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if mode == 'out':
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        # We use the 'store' mode when getting the parameter type, since we
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        # need to call sizeof() for memset().
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        _, pname, _, _ = cgen.GetComponents(param, release, 'store')
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        out_params.append(pname)
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return out_params
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def _MakeNormalMemberBody(filenode, release, node, member, rtype, args,
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          include_version, meta):
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  """Returns the body of a typical function.
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Args:
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    filenode - IDLNode for the file
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    release - release to generate body for
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    node - IDLNode for the interface
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    member - IDLNode for the member function
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rtype - Return type for the member function
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    args - List of 4-tuple arguments for the member function
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    include_version - whether to include the version in the invocation
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    meta - ThunkBodyMetadata for header hints
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  """
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if len(args) == 0:
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    # Calling into the "Shared" code for the interface seems like a reasonable
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    # heuristic when we don't have any arguments; some thunk code follows this
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    # convention today.
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    meta.AddApi('ppapi/shared_impl/%s_shared.h' % _StripFileName(filenode))
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return 'return %s::%s();' % (_StripApiName(node.GetName()) + '_Shared',
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 member.GetName())
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  is_callback_func = args[len(args) - 1][0] == 'struct PP_CompletionCallback'
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if is_callback_func:
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    call_args = args[:-1] + [('', 'enter.callback()', '', '')]
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    meta.AddInclude('ppapi/c/pp_completion_callback.h')
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else:
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    call_args = args
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if args[0][0] == 'PP_Instance':
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    call_arglist = ', '.join(a[1] for a in call_args)
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    function_container = 'functions'
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  elif args[0][0] == 'PP_Resource':
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    call_arglist = ', '.join(a[1] for a in call_args[1:])
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    function_container = 'object'
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  else:
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    # Calling into the "Shared" code for the interface seems like a reasonable
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    # heuristic when the first argument isn't a PP_Instance or a PP_Resource;
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    # some thunk code follows this convention today.
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    meta.AddApi('ppapi/shared_impl/%s_shared.h' % _StripFileName(filenode))
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return 'return %s::%s(%s);' % (_StripApiName(node.GetName()) + '_Shared',
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                   member.GetName(),
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                   ', '.join(a[1] for a in args))
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  function_name = member.GetName()
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if include_version:
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    version = node.GetVersion(release).replace('.', '_')
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    function_name += version
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  invocation = 'enter.%s()->%s(%s)' % (function_container,
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       function_name,
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       call_arglist)
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  handle_errors = not (member.GetProperty('report_errors') == 'False')
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  out_params = _GetOutputParams(member, release)
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if is_callback_func:
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    body = '%s\n' % _MakeEnterLine(filenode, node, member, args[0],
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                   handle_errors, args[len(args) - 1][1], meta)
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    failure_value = member.GetProperty('on_failure')
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if failure_value is None:
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      failure_value = 'enter.retval()'
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    failure_return = 'return %s;' % failure_value
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    success_return = 'return enter.SetResult(%s);' % invocation
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  elif rtype == 'void':
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    body = '%s\n' % _MakeEnterLine(filenode, node, member, args[0],
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                   handle_errors, None, meta)
318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    failure_return = 'return;'
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    success_return = '%s;' % invocation  # We don't return anything for void.
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  else:
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    body = '%s\n' % _MakeEnterLine(filenode, node, member, args[0],
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                   handle_errors, None, meta)
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    failure_value = member.GetProperty('on_failure')
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if failure_value is None:
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      failure_value = _GetDefaultFailureValue(rtype)
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if failure_value is None:
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      raise TGenError('There is no default value for rtype %s. '
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      'Maybe you should provide an on_failure attribute '
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      'in the IDL file.' % rtype)
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    failure_return = 'return %s;' % failure_value
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    success_return = 'return %s;' % invocation
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if member.GetProperty('always_set_output_parameters'):
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    body += 'if (enter.failed()) {\n'
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    for param in out_params:
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      body += '  memset(%s, 0, sizeof(*%s));\n' % (param, param)
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    body += '  %s\n' % failure_return
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    body += '}\n'
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    body += '%s' % success_return
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    meta.AddBuiltinInclude('string.h')
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else:
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    body += 'if (enter.failed())\n'
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    body += '  %s\n' % failure_return
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    body += '%s' % success_return
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return body
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def DefineMember(filenode, node, member, release, include_version, meta):
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  """Returns a definition for a member function of an interface.
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Args:
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    filenode - IDLNode for the file
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    node - IDLNode for the interface
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    member - IDLNode for the member function
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    release - release to generate
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    include_version - include the version in emitted function name.
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    meta - ThunkMetadata for header hints
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Returns:
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    A string with the member definition.
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  """
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  cgen = CGen()
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rtype, name, arrays, args = cgen.GetComponents(member, release, 'return')
36323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  log_body = '\"%s::%s()\";' % (node.GetName(), member.GetName())
36423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if len(log_body) > 69:  # Prevent lines over 80 characters.
36523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    body = 'VLOG(4) <<\n'
36623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    body += '    %s\n' % log_body
36723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  else:
36823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    body = 'VLOG(4) << %s\n' % log_body
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if _IsTypeCheck(node, member, args):
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    body += '%s\n' % _MakeEnterLine(filenode, node, member, args[0], False,
372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                    None, meta)
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    body += 'return PP_FromBool(enter.succeeded());'
374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  elif member.GetName() == 'Create' or member.GetName() == 'CreateTrusted':
375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    body += _MakeCreateMemberBody(node, member, args)
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else:
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    body += _MakeNormalMemberBody(filenode, release, node, member, rtype, args,
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  include_version, meta)
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  signature = cgen.GetSignature(member, release, 'return', func_as_ptr=False,
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                include_version=include_version)
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return '%s\n%s\n}' % (cgen.Indent('%s {' % signature, tabs=0),
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        cgen.Indent(body, tabs=1))
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def _IsNewestMember(member, members, releases):
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  """Returns true if member is the newest node with its name in members.
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Currently, every node in the AST only has one version. This means that we
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  will have two sibling nodes with the same name to represent different
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  versions.
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  See http://crbug.com/157017 .
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Special handling is required for nodes which share their name with others,
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  but aren't the newest version in the IDL.
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Args:
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    member - The member which is checked if it's newest
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    members - The list of members to inspect
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    releases - The set of releases to check for versions in.
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  """
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  build_list = member.GetUniqueReleases(releases)
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  release = build_list[0]  # Pick the oldest release.
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  same_name_siblings = filter(
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      lambda n: str(n) == str(member) and n != member, members)
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for s in same_name_siblings:
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sibling_build_list = s.GetUniqueReleases(releases)
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sibling_release = sibling_build_list[0]
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if sibling_release > release:
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return False
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return True
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class TGen(GeneratorByFile):
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def __init__(self):
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Generator.__init__(self, 'Thunk', 'tgen', 'Generate the C++ thunk.')
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def GenerateFile(self, filenode, releases, options):
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    savename = _GetThunkFileName(filenode, GetOption('thunkroot'))
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    my_min, my_max = filenode.GetMinMax(releases)
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if my_min > releases[-1] or my_max < releases[0]:
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if os.path.isfile(savename):
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        print "Removing stale %s for this range." % filenode.GetName()
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        os.remove(os.path.realpath(savename))
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return False
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    do_generate = filenode.GetProperty('generate_thunk')
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if not do_generate:
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return False
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    thunk_out = IDLOutFile(savename)
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    body, meta = self.GenerateBody(thunk_out, filenode, releases, options)
433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    # TODO(teravest): How do we handle repeated values?
434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if filenode.GetProperty('thunk_include'):
435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      meta.AddInclude(filenode.GetProperty('thunk_include'))
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.WriteHead(thunk_out, filenode, releases, options, meta)
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    thunk_out.Write('\n\n'.join(body))
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.WriteTail(thunk_out, filenode, releases, options)
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return thunk_out.Close()
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def WriteHead(self, out, filenode, releases, options, meta):
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    __pychecker__ = 'unusednames=options'
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cgen = CGen()
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cright_node = filenode.GetChildren()[0]
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    assert(cright_node.IsA('Copyright'))
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    out.Write('%s\n' % cgen.Copyright(cright_node, cpp_style=True))
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # Wrap the From ... modified ... comment if it would be >80 characters.
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    from_text = 'From %s' % (
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        filenode.GetProperty('NAME').replace(os.sep,'/'))
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    modified_text = 'modified %s.' % (
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        filenode.GetProperty('DATETIME'))
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if len(from_text) + len(modified_text) < 74:
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      out.Write('// %s %s\n\n' % (from_text, modified_text))
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else:
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      out.Write('// %s,\n//   %s\n\n' % (from_text, modified_text))
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if meta.BuiltinIncludes():
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      for include in sorted(meta.BuiltinIncludes()):
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        out.Write('#include <%s>\n' % include)
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      out.Write('\n')
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # TODO(teravest): Don't emit includes we don't need.
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    includes = ['ppapi/c/pp_errors.h',
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                'ppapi/shared_impl/tracked_callback.h',
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                'ppapi/thunk/enter.h',
4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                'ppapi/thunk/ppapi_thunk_export.h']
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    includes.append(_GetHeaderFileName(filenode))
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for api in meta.Apis():
471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      includes.append('%s' % api.lower())
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for i in meta.Includes():
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      includes.append(i)
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for include in sorted(includes):
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      out.Write('#include "%s"\n' % include)
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    out.Write('\n')
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    out.Write('namespace ppapi {\n')
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    out.Write('namespace thunk {\n')
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    out.Write('\n')
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    out.Write('namespace {\n')
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    out.Write('\n')
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def GenerateBody(self, out, filenode, releases, options):
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """Generates a member function lines to be written and metadata.
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Returns a tuple of (body, meta) where:
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      body - a list of lines with member function bodies
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      meta - a ThunkMetadata instance for hinting which headers are needed.
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    __pychecker__ = 'unusednames=options'
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    out_members = []
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    meta = ThunkBodyMetadata()
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for node in filenode.GetListOf('Interface'):
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      # Skip if this node is not in this release
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if not node.InReleases(releases):
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        print "Skipping %s" % node
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        continue
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      # Generate Member functions
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if node.IsA('Interface'):
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        members = node.GetListOf('Member')
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        for child in members:
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          build_list = child.GetUniqueReleases(releases)
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          # We have to filter out releases this node isn't in.
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          build_list = filter(lambda r: child.InReleases([r]), build_list)
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if len(build_list) == 0:
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            continue
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          release = build_list[-1]
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          include_version = not _IsNewestMember(child, members, releases)
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          member = DefineMember(filenode, node, child, release, include_version,
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                meta)
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if not member:
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            continue
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          out_members.append(member)
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return (out_members, meta)
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def WriteTail(self, out, filenode, releases, options):
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    __pychecker__ = 'unusednames=options'
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cgen = CGen()
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    version_list = []
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    out.Write('\n\n')
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for node in filenode.GetListOf('Interface'):
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      build_list = node.GetUniqueReleases(releases)
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for build in build_list:
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        version = node.GetVersion(build).replace('.', '_')
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        thunk_name = 'g_' + node.GetName().lower() + '_thunk_' + \
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      version
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        thunk_type = '_'.join((node.GetName(), version))
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        version_list.append((thunk_type, thunk_name))
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        declare_line = 'const %s %s = {' % (thunk_type, thunk_name)
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if len(declare_line) > 80:
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          declare_line = 'const %s\n    %s = {' % (thunk_type, thunk_name)
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        out.Write('%s\n' % declare_line)
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        generated_functions = []
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        members = node.GetListOf('Member')
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        for child in members:
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          rtype, name, arrays, args = cgen.GetComponents(
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              child, build, 'return')
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if child.InReleases([build]):
54290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            if not _IsNewestMember(child, members, releases):
54390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)              version = child.GetVersion(
54490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                  child.first_release[build]).replace('.', '_')
54590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)              name += '_' + version
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            generated_functions.append(name)
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        out.Write(',\n'.join(['  &%s' % f for f in generated_functions]))
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        out.Write('\n};\n\n')
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    out.Write('}  // namespace\n')
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    out.Write('\n')
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for thunk_type, thunk_name in version_list:
5535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      thunk_decl = ('PPAPI_THUNK_EXPORT const %s* Get%s_Thunk() {\n' %
5545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    (thunk_type, thunk_type))
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if len(thunk_decl) > 80:
5565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        thunk_decl = ('PPAPI_THUNK_EXPORT const %s*\n    Get%s_Thunk() {\n' %
5575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      (thunk_type, thunk_type))
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      out.Write(thunk_decl)
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      out.Write('  return &%s;\n' % thunk_name)
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      out.Write('}\n')
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      out.Write('\n')
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    out.Write('}  // namespace thunk\n')
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    out.Write('}  // namespace ppapi\n')
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)tgen = TGen()
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)def Main(args):
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  # Default invocation will verify the golden files are unchanged.
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  failed = 0
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if not args:
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    args = ['--wnone', '--diff', '--test', '--thunkroot=.']
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ParseOptions(args)
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  idldir = os.path.split(sys.argv[0])[0]
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  idldir = os.path.join(idldir, 'test_thunk', '*.idl')
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  filenames = glob.glob(idldir)
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ast = ParseFiles(filenames)
58190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if tgen.GenerateRange(ast, ['M13', 'M14', 'M15'], {}):
58290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    print "Golden file for M13-M15 failed."
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    failed = 1
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else:
58590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    print "Golden file for M13-M15 passed."
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return failed
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)if __name__ == '__main__':
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sys.exit(Main(sys.argv[1:]))
592