15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""Base class for generating wrapper functions for PPAPI methods.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from datetime import datetime
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import os
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import sys
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from idl_c_proto import CGen
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from idl_generator import Generator
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from idl_log import ErrOut, InfoOut, WarnOut
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from idl_option import  GetOption
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from idl_outfile import IDLOutFile
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PPKind(object):
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  @staticmethod
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def ChoosePPFunc(iface, ppb_func, ppp_func):
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name = iface.node.GetName()
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if name.startswith("PPP"):
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ppp_func
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif name.startswith("PPB"):
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ppb_func
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      raise Exception('Unknown PPKind for ' + name)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Interface(object):
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Tracks information about a particular interface version.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  - struct_name: the struct type used by the ppapi headers to hold the
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  method pointers (the vtable).
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  - needs_wrapping: True if a method in the interface needs wrapping.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  - header_file: the name of the header file that defined this interface.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __init__(self, interface_node, release, version,
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               struct_name, needs_wrapping, header_file):
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.node = interface_node
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.release = release
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.version = version
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.struct_name = struct_name
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # We may want finer grained filtering (method level), but it is not
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # yet clear how to actually do that.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.needs_wrapping = needs_wrapping
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.header_file = header_file
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class WrapperGen(Generator):
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """WrapperGen - An abstract class that generates wrappers for PPAPI methods.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  This generates a wrapper PPB and PPP GetInterface, which directs users
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  to wrapper PPAPI methods. Wrapper PPAPI methods may perform arbitrary
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  work before invoking the real PPAPI method (supplied by the original
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetInterface functions).
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Subclasses must implement GenerateWrapperForPPBMethod (and PPP).
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __init__(self, wrapper_prefix, s1, s2, s3):
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Generator.__init__(self, s1, s2, s3)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.wrapper_prefix = wrapper_prefix
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._skip_opt = False
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.output_file = None
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.cgen = CGen()
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def SetOutputFile(self, fname):
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.output_file = fname
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GenerateRelease(self, ast, release, options):
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return self.GenerateRange(ast, [release], options)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  @staticmethod
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GetHeaderName(name):
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Get the corresponding ppapi .h file from each IDL filename.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name = os.path.splitext(name)[0] + '.h'
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name = name.replace(os.sep, '/')
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 'ppapi/c/' + name
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def WriteCopyright(self, out):
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    now = datetime.now()
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c = """/* Copyright (c) %s The Chromium Authors. All rights reserved.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Use of this source code is governed by a BSD-style license that can be
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * found in the LICENSE file.
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/* NOTE: this is auto-generated from IDL */
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)""" % now.year
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.Write(c)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GetWrapperMetadataName(self):
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return '__%sWrapperInfo' % self.wrapper_prefix
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GenerateHelperFunctions(self, out):
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Generate helper functions to avoid dependencies on libc.
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.Write("""/* Use local strcmp to avoid dependency on libc. */
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int mystrcmp(const char* s1, const char *s2) {
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (1) {
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (*s1 == 0) break;
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (*s2 == 0) break;
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (*s1 != *s2) break;
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ++s1;
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ++s2;
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return (int)(*s1) - (int)(*s2);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}\n
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)""")
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GenerateFixedFunctions(self, out):
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Write out the set of constant functions (those that do not depend on
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    the current Pepper IDL).
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.Write("""
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PPB_GetInterface __real_PPBGetInterface;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PPP_GetInterface_Type __real_PPPGetInterface;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void __set_real_%(wrapper_prefix)s_PPBGetInterface(PPB_GetInterface real) {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  __real_PPBGetInterface = real;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void __set_real_%(wrapper_prefix)s_PPPGetInterface(PPP_GetInterface_Type real) {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  __real_PPPGetInterface = real;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Map interface string -> wrapper metadata */
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct %(wrapper_struct)s *%(wrapper_prefix)sPPBShimIface(
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char *name) {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct %(wrapper_struct)s **next = s_ppb_wrappers;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (*next != NULL) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (mystrcmp(name, (*next)->iface_macro) == 0) return *next;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++next;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Map interface string -> wrapper metadata */
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct %(wrapper_struct)s *%(wrapper_prefix)sPPPShimIface(
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char *name) {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct %(wrapper_struct)s **next = s_ppp_wrappers;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (*next != NULL) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (mystrcmp(name, (*next)->iface_macro) == 0) return *next;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++next;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const void *__%(wrapper_prefix)s_PPBGetInterface(const char *name) {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct %(wrapper_struct)s *wrapper = %(wrapper_prefix)sPPBShimIface(name);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (wrapper == NULL) {
160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    /* We did not generate a wrapper for this, so return the real interface. */
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (*__real_PPBGetInterface)(name);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Initialize the real_iface if it hasn't been. The wrapper depends on it. */
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (wrapper->real_iface == NULL) {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const void *iface = (*__real_PPBGetInterface)(name);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (NULL == iface) return NULL;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wrapper->real_iface = iface;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (wrapper->wrapped_iface) {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return wrapper->wrapped_iface;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return wrapper->real_iface;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const void *__%(wrapper_prefix)s_PPPGetInterface(const char *name) {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct %(wrapper_struct)s *wrapper = %(wrapper_prefix)sPPPShimIface(name);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (wrapper == NULL) {
181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    /* We did not generate a wrapper for this, so return the real interface. */
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (*__real_PPPGetInterface)(name);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Initialize the real_iface if it hasn't been. The wrapper depends on it. */
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (wrapper->real_iface == NULL) {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const void *iface = (*__real_PPPGetInterface)(name);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (NULL == iface) return NULL;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wrapper->real_iface = iface;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (wrapper->wrapped_iface) {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return wrapper->wrapped_iface;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return wrapper->real_iface;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)""" % { 'wrapper_struct' : self.GetWrapperMetadataName(),
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'wrapper_prefix' : self.wrapper_prefix,
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } )
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ############################################################
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def OwnHeaderFile(self):
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Return the header file that specifies the API of this wrapper.
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    We do not generate the header files.  """
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raise Exception('Child class must implement this')
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ############################################################
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def DetermineInterfaces(self, ast, releases):
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Get a list of interfaces along with whatever metadata we need.
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    iface_releases = []
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for filenode in ast.GetListOf('File'):
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # If this file has errors, skip it
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if filenode in self.skip_list:
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if GetOption('verbose'):
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          InfoOut.Log('WrapperGen: Skipping %s due to errors\n' %
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      filenode.GetName())
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      file_name = self.GetHeaderName(filenode.GetName())
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ifaces = filenode.GetListOf('Interface')
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for iface in ifaces:
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        releases_for_iface = iface.GetUniqueReleases(releases)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for release in releases_for_iface:
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          version = iface.GetVersion(release)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          struct_name = self.cgen.GetStructName(iface, release,
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                include_version=True)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          needs_wrap = self.InterfaceVersionNeedsWrapping(iface, version)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if not needs_wrap:
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if GetOption('verbose'):
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              InfoOut.Log('Interface %s ver %s does not need wrapping' %
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          (struct_name, version))
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          iface_releases.append(
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              Interface(iface, release, version,
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        struct_name, needs_wrap, file_name))
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return iface_releases
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GenerateIncludes(self, iface_releases, out):
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Generate the list of #include that define the original interfaces.
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.WriteCopyright(out)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # First include own header.
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.Write('#include "%s"\n\n' % self.OwnHeaderFile())
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Get typedefs for PPB_GetInterface.
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.Write('#include "%s"\n' % self.GetHeaderName('ppb.h'))
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Get a conservative list of all #includes that are needed,
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # whether it requires wrapping or not. We currently depend on the macro
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # string for comparison, even when it is not wrapped, to decide when
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # to use the original/real interface.
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    header_files = set()
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for iface in iface_releases:
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      header_files.add(iface.header_file)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for header in sorted(header_files):
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out.Write('#include "%s"\n' % header)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.Write('\n')
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def WrapperMethodPrefix(self, iface, release):
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return '%s_%s_%s_' % (self.wrapper_prefix, release, iface.GetName())
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GenerateWrapperForPPBMethod(self, iface, member):
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = []
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    func_prefix = self.WrapperMethodPrefix(iface.node, iface.release)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sig = self.cgen.GetSignature(member, iface.release, 'store',
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 func_prefix, False)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result.append('static %s {\n' % sig)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result.append(' while(1) { /* Not implemented */ } \n')
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result.append('}\n')
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GenerateWrapperForPPPMethod(self, iface, member):
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = []
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    func_prefix = self.WrapperMethodPrefix(iface.node, iface.release)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sig = self.cgen.GetSignature(member, iface.release, 'store',
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 func_prefix, False)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result.append('static %s {\n' % sig)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result.append(' while(1) { /* Not implemented */ } \n')
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result.append('}\n')
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GenerateWrapperForMethods(self, iface_releases, comments=True):
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Return a string representing the code for each wrapper method
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (using a string rather than writing to the file directly for testing.)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = []
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for iface in iface_releases:
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if not iface.needs_wrapping:
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if comments:
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          result.append('/* Not generating wrapper methods for %s */\n\n' %
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        iface.struct_name)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if comments:
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result.append('/* Begin wrapper methods for %s */\n\n' %
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      iface.struct_name)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      generator =  PPKind.ChoosePPFunc(iface,
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       self.GenerateWrapperForPPBMethod,
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       self.GenerateWrapperForPPPMethod)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for member in iface.node.GetListOf('Member'):
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Skip the method if it's not actually in the release.
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if not member.InReleases([iface.release]):
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          continue
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result.extend(generator(iface, member))
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if comments:
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result.append('/* End wrapper methods for %s */\n\n' %
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      iface.struct_name)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ''.join(result)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GenerateWrapperInterfaces(self, iface_releases, out):
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for iface in iface_releases:
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if not iface.needs_wrapping:
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        out.Write('/* Not generating wrapper interface for %s */\n\n' %
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  iface.struct_name)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out.Write('struct %s %s_Wrappers_%s = {\n' % (iface.struct_name,
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    self.wrapper_prefix,
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    iface.struct_name))
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      methods = []
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for member in iface.node.GetListOf('Member'):
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # Skip the method if it's not actually in the release.
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if not member.InReleases([iface.release]):
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          continue
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        prefix = self.WrapperMethodPrefix(iface.node, iface.release)
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        # Casts are necessary for the PPB_* wrappers because we must
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        # cast away "__attribute__((pnaclcall))".  The PPP_* wrappers
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        # must match the default calling conventions and so don't have
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        # the attribute, so omitting casts for them provides a little
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        # extra type checking.
341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if iface.node.GetName().startswith('PPB_'):
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          cast = '(%s)' % self.cgen.GetSignature(
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              member, iface.release, 'return',
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              prefix='',
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              func_as_ptr=True,
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              include_name=False)
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        else:
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          cast = ''
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        methods.append('  .%s = %s&%s%s' % (member.GetName(),
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                            cast,
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                            prefix,
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                            member.GetName()))
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out.Write('  ' + ',\n  '.join(methods) + '\n')
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out.Write('};\n\n')
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GetWrapperInfoName(self, iface):
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return '%s_WrapperInfo_%s' % (self.wrapper_prefix, iface.struct_name)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GenerateWrapperInfoAndCollection(self, iface_releases, out):
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for iface in iface_releases:
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      iface_macro = self.cgen.GetInterfaceMacro(iface.node, iface.version)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if iface.needs_wrapping:
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        wrap_iface = '(void *) &%s_Wrappers_%s' % (self.wrapper_prefix,
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   iface.struct_name)
367eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        out.Write("""static struct %s %s = {
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  .iface_macro = %s,
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  .wrapped_iface = %s,
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  .real_iface = NULL
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};\n\n""" % (self.GetWrapperMetadataName(),
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             self.GetWrapperInfoName(iface),
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             iface_macro,
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             wrap_iface))
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Now generate NULL terminated arrays of the above wrapper infos.
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ppb_wrapper_infos = []
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ppp_wrapper_infos = []
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for iface in iface_releases:
380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if iface.needs_wrapping:
381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        appender = PPKind.ChoosePPFunc(iface,
382eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       ppb_wrapper_infos.append,
383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       ppp_wrapper_infos.append)
384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        appender('  &%s' % self.GetWrapperInfoName(iface))
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ppb_wrapper_infos.append('  NULL')
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ppp_wrapper_infos.append('  NULL')
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.Write(
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'static struct %s *s_ppb_wrappers[] = {\n%s\n};\n\n' %
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (self.GetWrapperMetadataName(), ',\n'.join(ppb_wrapper_infos)))
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.Write(
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'static struct %s *s_ppp_wrappers[] = {\n%s\n};\n\n' %
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (self.GetWrapperMetadataName(), ',\n'.join(ppp_wrapper_infos)))
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def DeclareWrapperInfos(self, iface_releases, out):
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """The wrapper methods usually need access to the real_iface, so we must
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    declare these wrapper infos ahead of time (there is a circular dependency).
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.Write('/* BEGIN Declarations for all Wrapper Infos */\n\n')
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for iface in iface_releases:
401eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if iface.needs_wrapping:
402eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        out.Write('static struct %s %s;\n' %
403eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                  (self.GetWrapperMetadataName(),
404eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                   self.GetWrapperInfoName(iface)))
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.Write('/* END Declarations for all Wrapper Infos. */\n\n')
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GenerateRange(self, ast, releases, options):
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Generate shim code for a range of releases.
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Remember to set the output filename before running this.
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out_filename = self.output_file
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if out_filename is None:
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ErrOut.Log('Did not set filename for writing out wrapper\n')
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 1
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InfoOut.Log("Generating %s for %s" % (out_filename, self.wrapper_prefix))
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out = IDLOutFile(out_filename)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Get a list of all the interfaces along with metadata.
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    iface_releases = self.DetermineInterfaces(ast, releases)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Generate the includes.
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.GenerateIncludes(iface_releases, out)
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Write out static helper functions (mystrcmp).
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.GenerateHelperFunctions(out)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Declare list of WrapperInfo before actual wrapper methods, since
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # they reference each other.
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.DeclareWrapperInfos(iface_releases, out)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Generate wrapper functions for each wrapped method in the interfaces.
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = self.GenerateWrapperForMethods(iface_releases)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.Write(result)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Collect all the wrapper functions into interface structs.
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.GenerateWrapperInterfaces(iface_releases, out)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Generate a table of the wrapped interface structs that can be looked up.
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.GenerateWrapperInfoAndCollection(iface_releases, out)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Write out the IDL-invariant functions.
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.GenerateFixedFunctions(out)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out.Close()
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0
450