#!/usr/bin/python
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# pylint: disable=W0104,W0106,F0401,R0201

import errno
import os.path
import sys

import interface


def ScriptDir():
  return os.path.dirname(os.path.abspath(__file__))


def RepoRoot():
  return os.path.dirname(ScriptDir())


def _AddThirdPartyImportPath():
  sys.path.append(os.path.join(RepoRoot(), 'third_party'))


_AddThirdPartyImportPath()
import jinja2

loader = jinja2.FileSystemLoader(ScriptDir())
jinja_env = jinja2.Environment(loader=loader, keep_trailing_newline=True)


# Accumulate lines of code with varying levels of indentation.
class CodeWriter(object):
  def __init__(self):
    self._lines = []
    self._margin = ''
    self._margin_stack = []

  def __lshift__(self, line):
    self._lines.append((self._margin + line).rstrip())

  def PushMargin(self):
    self._margin_stack.append(self._margin)
    self._margin += '  '

  def PopMargin(self):
    self._margin = self._margin_stack.pop()

  def GetValue(self):
    return '\n'.join(self._lines).rstrip() + '\n'

  def Indent(self):
    return Indent(self)


# Context handler that automatically indents and dedents a CodeWriter
class Indent(object):
  def __init__(self, writer):
    self._writer = writer

  def __enter__(self):
    self._writer.PushMargin()

  def __exit__(self, type_, value, traceback):
    self._writer.PopMargin()


def TemplateFile(name):
  return os.path.join(os.path.dirname(__file__), name)


# Wraps comma separated lists as needed.
# TODO(teravest): Eliminate Wrap() and use "git cl format" when code is checked
# in.
def Wrap(pre, items, post):
  complete = pre + ', '.join(items) + post
  if len(complete) <= 80:
    return [complete]
  lines = [pre]
  indent = '    '
  for i, item in enumerate(items):
    if i < len(items) - 1:
      lines.append(indent + item + ',')
    else:
      lines.append(indent + item + post)
  return lines


def GeneratorWarning():
  return ('// WARNING this file was generated by %s\n// Do not edit by hand.' %
          os.path.basename(__file__))


# Untrusted library which thunks from the public Mojo API to the IRT interface
# implementing the public Mojo API.
def GenerateLibMojo(functions, common_vars, out):
  template = jinja_env.get_template('libmojo.cc.tmpl')

  code = CodeWriter()

  for f in functions:
    for line in Wrap('%s %s(' % (f.return_type, f.name), f.ParamList(), ') {'):
      code << line

    with code.Indent():
      code << 'struct nacl_irt_mojo* irt_mojo = get_irt_mojo();'
      code << 'if (irt_mojo == NULL)'
      with code.Indent():
        code << 'return MOJO_RESULT_INTERNAL;'
      code << 'return irt_mojo->%s(%s);' % (
          f.name, ', '.join([p.name for p in f.params]))

    code << '}'
    code << ''

  body = code.GetValue()
  text = template.render(
    body=body,
    **common_vars)
  out.write(text)


# Parameters passed into trusted code are handled differently depending on
# details of the parameter.  ParamImpl instances encapsulate these differences
# and are used to generate the code that transfers parameters across the
# untrusted/trusted boundary.
class ParamImpl(object):
  def __init__(self, param):
    self.param = param

  # Declare whatever variables are needed to handle this particular parameter.
  def DeclareVars(self, code):
    raise NotImplementedError(type(self))

  # Convert the untrusted representation of the parameter into a trusted
  # representation, such as a scalar value or a trusted pointer into the
  # untrusted address space.
  def ConvertParam(self):
    raise NotImplementedError(type(self))

  # For this particular parameter, what expression should be passed when
  # invoking the trusted Mojo API function?
  def CallParam(self):
    raise NotImplementedError(type(self))

  # After invoking the trusted Mojo API function, transfer data back into
  # untrusted memory.  Overriden for Out and InOut parameters.
  def CopyOut(self, code):
    pass

  # Converting array parameters needs to be defered until after the scalar
  # parameter containing the size of the array has itself been converted.
  def IsArray(self):
    return False


class ScalarInputImpl(ParamImpl):
  def DeclareVars(self, code):
    code << '%s %s_value;' % (self.param.base_type, self.param.name)

  def ConvertParam(self):
    p = self.param
    return ('ConvertScalarInput(nap, params[%d], &%s_value)' %
            (p.uid + 1, p.name))

  def CallParam(self):
    return '%s_value' % self.param.name


class ScalarOutputImpl(ParamImpl):
  def DeclareVars(self, code):
    code << '%s volatile* %s_ptr;' % (self.param.base_type, self.param.name)
    code << '%s %s_value;' % (self.param.base_type, self.param.name)

  def ConvertParam(self):
    p = self.param
    return ('ConvertScalarOutput(nap, params[%d], %s, &%s_ptr)' %
            (p.uid + 1, CBool(p.is_optional), p.name))

  def CallParam(self):
    name = self.param.name
    expr = '&%s_value' % name
    if self.param.is_optional:
      expr = '%s_ptr ? %s : NULL' % (name, expr)
    return expr

  def CopyOut(self, code):
    name = self.param.name
    if self.param.is_struct:
      # C++ errors when you try to copy a volatile struct pointer.
      # (There are no default copy constructors for this case.)
      # memcpy instead.
      copy_stmt = ('memcpy_volatile_out(%s_ptr, &%s_value, sizeof(%s));' %
                   (name, name, self.param.base_type))
    else:
      copy_stmt = '*%s_ptr = %s_value;' % (name, name)

    if self.param.is_optional:
      code << 'if (%s_ptr != NULL) {' % (name)
      with code.Indent():
        code << copy_stmt
      code << '}'
    else:
      code << copy_stmt


class ScalarInOutImpl(ParamImpl):
  def DeclareVars(self, code):
    code << '%s volatile* %s_ptr;' % (self.param.base_type, self.param.name)
    code << '%s %s_value;' % (self.param.base_type, self.param.name)

  def ConvertParam(self):
    p = self.param
    return ('ConvertScalarInOut(nap, params[%d], %s, &%s_value, &%s_ptr)' %
            (p.uid + 1, CBool(p.is_optional), p.name, p.name))

  def CallParam(self):
    name = self.param.name
    expr = '&%s_value' % name
    if self.param.is_optional:
      expr = '%s_ptr ? %s : NULL' % (name, expr)
    return expr

  def CopyOut(self, code):
    name = self.param.name
    if self.param.is_optional:
      code << 'if (%s_ptr != NULL) {' % (name)
      with code.Indent():
        code << '*%s_ptr = %s_value;' % (name, name)
      code << '}'
    else:
      code << '*%s_ptr = %s_value;' % (name, name)


class ArrayImpl(ParamImpl):
  def DeclareVars(self, code):
    code << '%s %s;' % (self.param.param_type, self.param.name)

  def ConvertParam(self):
    p = self.param
    if p.base_type == 'void':
      element_size = '1'
    else:
      element_size = 'sizeof(*%s)' % p.name

    return ('ConvertArray(nap, params[%d], %s, %s, %s, &%s)' %
            (p.uid + 1, p.size + '_value', element_size, CBool(p.is_optional),
             p.name))

  def CallParam(self):
    return self.param.name

  def IsArray(self):
    return True


class ExtensibleStructInputImpl(ParamImpl):
  def DeclareVars(self, code):
    code << '%s %s;' % (self.param.param_type, self.param.name)

  def ConvertParam(self):
    p = self.param
    return ('ConvertExtensibleStructInput(nap, params[%d], %s, &%s)' %
            (p.uid + 1, CBool(p.is_optional), p.name))

  def CallParam(self):
    return self.param.name

def ImplForParam(p):
  if p.IsScalar():
    if p.is_output:
      if p.is_input:
        return ScalarInOutImpl(p)
      else:
        if p.is_always_written:
          return ScalarOutputImpl(p)
        else:
          # Mojo defines that some of its outputs will not be set in specific
          # cases.  To avoid the complexity of determining if the output was set
          # by Mojo, copy the output's current value (possibly junk) and copy it
          # back to untrusted memory afterwards.
          return ScalarInOutImpl(p)
    else:
      return ScalarInputImpl(p)
  elif p.is_array:
    return ArrayImpl(p)
  elif p.is_struct:
    if p.is_input and not p.is_output and p.is_extensible:
      return ExtensibleStructInputImpl(p)
    if not p.is_input and p.is_output and not p.is_extensible:
      return ScalarOutputImpl(p)
  assert False, p.name


def CBool(value):
  return 'true' if value else 'false'


# A trusted wrapper that validates the arguments passed from untrusted code
# before passing them to the underlying public Mojo API.
def GenerateMojoSyscall(functions, common_vars, out):
  template = jinja_env.get_template('mojo_syscall.cc.tmpl')

  code = CodeWriter()
  code.PushMargin()

  for f in functions:
    is_implemented = True

    # Mojo API calls that take or return pointers are currently not supported.
    # The underlying Mojo implementation is unaware of NaCl's address space. In
    # addition, if we pass blindly pass the parameters through to the underlying
    # Mojo API, memory corruption can result from pointer-size mistmatches.
    for p in f.params:
      if p.base_type.endswith("*"):
        is_implemented = False

    impls = [ImplForParam(p) for p in f.params]
    impls.append(ImplForParam(f.result_param))

    code << 'case %d:' % f.uid

    if not is_implemented:
      with code.Indent():
        code << 'fprintf(stderr, "%s not implemented\\n");' % f.name
        code << 'return -1;'
      continue

    code.PushMargin()

    code << '{'

    with code.Indent():
      num_params = len(f.params) + 2
      code << 'if (num_params != %d) {' % num_params
      with code.Indent():
        code << 'return -1;'
      code << '}'

      # Declare temporaries.
      for impl in impls:
        impl.DeclareVars(code)

      def ConvertParam(code, impl):
        code << 'if (!%s) {' % impl.ConvertParam()
        with code.Indent():
          code << 'return -1;'
        code << '}'

      code << '{'
      with code.Indent():
        code << 'ScopedCopyLock copy_lock(nap);'
        # Convert and validate pointers in two passes.
        # Arrays cannot be validated until the size parameter has been
        # converted.
        for impl in impls:
          if not impl.IsArray():
            ConvertParam(code, impl)
        for impl in impls:
          if impl.IsArray():
            ConvertParam(code, impl)
      code << '}'
      code << ''

      # Call
      getParams = [impl.CallParam() for impl in impls[:-1]]
      code << 'result_value = %s(%s);' % (f.name, ', '.join(getParams))
      code << ''

      # Write outputs
      code << '{'
      with code.Indent():
        code << 'ScopedCopyLock copy_lock(nap);'
        for impl in impls:
          impl.CopyOut(code)
      code << '}'
      code << ''

      code << 'return 0;'
    code << '}'

    code.PopMargin()

  body = code.GetValue()
  text = template.render(
    body=body,
    **common_vars)
  out.write(text)


# A header declaring the IRT interface for accessing Mojo functions.
def GenerateMojoIrtHeader(functions, common_vars, out):
  template = jinja_env.get_template('mojo_irt.h.tmpl')
  code = CodeWriter()

  code << 'struct nacl_irt_mojo {'
  with code.Indent():
    for f in functions:
      for line in Wrap('%s (*%s)(' % (f.return_type, f.name),
                       f.ParamList(),
                       ');'):
        code << line

  code << '};'

  body = code.GetValue()

  text = template.render(
    body=body,
    **common_vars)
  out.write(text)

# IRT interface which implements the Mojo public API.
def GenerateMojoIrtImplementation(functions, common_vars, out):
  template = jinja_env.get_template('mojo_irt.c.tmpl')
  code = CodeWriter()

  for f in functions:
    for line in Wrap('static %s irt_%s(' % (f.return_type, f.name),
                     f.ParamList(),
                     ') {'):
      code << line

    # 2 extra parameters: message ID and return value.
    num_params = len(f.params) + 2

    with code.Indent():
      code << 'uint32_t params[%d];' % num_params
      return_type = f.result_param.base_type
      if return_type == 'MojoResult':
        default = 'MOJO_RESULT_INVALID_ARGUMENT'
      elif return_type == 'MojoTimeTicks':
        default = '0'
      else:
        raise Exception('Unhandled return type: ' + return_type)
      code << '%s %s = %s;' % (return_type, f.result_param.name, default)

      # Message ID
      code << 'params[0] = %d;' % f.uid
      # Parameter pointers
      cast_template = 'params[%d] = (uint32_t)(%s);'
      for p in f.params:
        ptr = p.name
        if p.IsPassedByValue():
          ptr = '&' + ptr
        code << cast_template % (p.uid + 1, ptr)
      # Return value pointer
      code << cast_template % (num_params - 1, '&' + f.result_param.name)

      code << 'DoMojoCall(params, sizeof(params));'
      code << 'return %s;' % f.result_param.name

    # Add body here.
    code << "};"
    code << "\n"

  # Now we've emitted all the functions, but we still need the struct
  # definition.
  code << 'struct nacl_irt_mojo kIrtMojo = {'
  for f in functions:
    with code.Indent():
      code << '&irt_%s,' % f.name
  code << '};'

  body = code.GetValue()

  text = template.render(
    body=body,
    **common_vars)
  out.write(text)


def OutFile(dir_path, name):
  if not os.path.exists(dir_path):
    try:
      os.makedirs(dir_path)
    except OSError as e:
      # There may have been a race to create this directory.
      if e.errno != errno.EEXIST:
        raise
  full_path = os.path.join(dir_path, name)
  print full_path
  return open(full_path, 'w')


def main():
  root_dir = RepoRoot()

  platform_dir = 'mojo/public/platform/nacl'
  bindings_dir = 'nacl_bindings'

  full_platform_dir = os.path.join(root_dir, platform_dir)
  full_bindings_dir = os.path.join(root_dir, bindings_dir)

  common_vars = dict(
    generator_warning=GeneratorWarning(),
    platform_dir=platform_dir,
    platform_dir_header_path=platform_dir.replace("/", "_").upper(),
    bindings_dir=bindings_dir,
  )

  mojo = interface.MakeInterface()

  out = OutFile(full_platform_dir, 'libmojo.cc')
  GenerateLibMojo(mojo.functions, common_vars, out)

  out = OutFile(full_bindings_dir, 'mojo_syscall.cc')
  GenerateMojoSyscall(mojo.functions, common_vars, out)

  out = OutFile(full_platform_dir, 'mojo_irt.h')
  GenerateMojoIrtHeader(mojo.functions, common_vars, out)

  out = OutFile(full_bindings_dir, 'mojo_irt.c')
  GenerateMojoIrtImplementation(mojo.functions, common_vars, out)

if __name__ == '__main__':
  main()
