#!/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 PointerInputImpl(ParamImpl):
  def DeclareVars(self, code):
    code << '%s %s_value;' % (self.param.base_type, self.param.name)

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

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


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

  def ConvertParam(self):
    p = self.param
    return ('ConvertPointerInOut(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):
    assert not self.param.is_optional
    name = self.param.name
    if self.param.is_optional:
      code << 'if (%s_ptr != NULL) {' % (name)
      with code.Indent():
        code << 'CopyOutPointer(nap, %s_value, %s_ptr);' % (name, name)
      code << '}'
    else:
      code << 'CopyOutPointer(nap, %s_value, %s_ptr);' % (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_pointer:
        return PointerInOutImpl(p)
      elif 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:
      if p.is_pointer:
        return PointerInputImpl(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 = not f.broken_in_nacl

    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]]
      callTarget = f.name
      # Redirect to namespaced functions.
      if callTarget.startswith("Mojo"):
        callTarget = callTarget[:4] + 'SystemImpl' + callTarget[4:]
        getParams = ['g_mojo_system'] + getParams
      code << 'result_value = %s(%s);' % (callTarget, ', '.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()
