#!/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 optparse
import os.path
import sys

import interface


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


def _GetDirAbove(dirname):
  """Returns the directory "above" this file containing |dirname| (which must
  also be "above" this file)."""
  path = _ScriptDir()
  while True:
    path, tail = os.path.split(path)
    assert tail
    if tail == dirname:
      return path


def _AddThirdPartyImportPath():
  sys.path.append(os.path.join(_GetDirAbove('mojo'), '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.
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 implementing the public Mojo API.
def GenerateLibMojo(functions, 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

    # 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] = reinterpret_cast<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

    code << '}'
    code << ''

  body = code.GetValue()
  text = template.render(
    generator_warning=GeneratorWarning(),
    body=body)
  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()

  # 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()

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

  # 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_ptr)' % (p.uid + 1, p.name)

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

  def CopyOut(self, code):
    name = self.param.name
    code << '*%s_ptr = %s_value;' % (name, name)


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 StructInputImpl(ParamImpl):
  def DeclareVars(self, code):
    code << '%s %s;' % (self.param.param_type, self.param.name)

  def ConvertParam(self):
    p = self.param
    return ('ConvertStruct(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:
        return ScalarOutputImpl(p)
    else:
      return ScalarInputImpl(p)
  elif p.is_array:
    return ArrayImpl(p)
  elif p.is_struct:
    return StructInputImpl(p)
  else:
    assert False, p


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, out):
  template = jinja_env.get_template('mojo_syscall.cc.tmpl')

  code = CodeWriter()
  code.PushMargin()

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

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

    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(
    generator_warning=GeneratorWarning(),
    body=body)
  out.write(text)


def OutFile(dir_path, name):
  if not os.path.exists(dir_path):
    os.makedirs(dir_path)
  return open(os.path.join(dir_path, name), 'w')


def main(args):
  usage = 'usage: %prog [options]'
  parser = optparse.OptionParser(usage=usage)
  parser.add_option(
      '-d',
      dest='out_dir',
      metavar='DIR',
      help='output generated code into directory DIR')
  options, args = parser.parse_args(args=args)
  if not options.out_dir:
    parser.error('-d is required')
  if args:
    parser.error('unexpected positional arguments: %s' % ' '.join(args))

  mojo = interface.MakeInterface()

  out = OutFile(options.out_dir, 'libmojo.cc')
  GenerateLibMojo(mojo.functions, out)

  out = OutFile(options.out_dir, 'mojo_syscall.cc')
  GenerateMojoSyscall(mojo.functions, out)


if __name__ == '__main__':
  main(sys.argv[1:])
