#!/usr/bin/env python
# Copyright (c) 2012 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.

""" Generator for C style prototypes and definitions """

import glob
import os
import re
import sys

from idl_log import ErrOut, InfoOut, WarnOut
from idl_node import IDLAttribute, IDLNode
from idl_ast import IDLAst
from idl_option import GetOption, Option, ParseOptions
from idl_outfile import IDLOutFile
from idl_parser import ParseFiles
from idl_c_proto import CGen, GetNodeComments, CommentLines, Comment
from idl_generator import Generator, GeneratorByFile
from idl_visitor import IDLVisitor

Option('dstroot', 'Base directory of output', default=os.path.join('..', 'c'))
Option('guard', 'Include guard prefix', default=os.path.join('ppapi', 'c'))


#
# PrototypeResolver
#
# A specialized visitor which traverses the AST, building a mapping of
# Release names to Versions numbers and calculating a min version.
# The mapping is applied to the File nodes within the AST.
#
class ProtoResolver(IDLVisitor):
  def __init__(self):
    IDLVisitor.__init__(self)
    self.struct_map = {}
    self.interface_map = {}

  def Arrive(self, node, ignore):
    if node.IsA('Member') and node.GetProperty('ref'):
      typeref = node.typelist.GetReleases()[0]
      if typeref.IsA('Struct'):
        nodelist = self.struct_map.get(typeref.GetName(), [])
        nodelist.append(node)
        self.struct_map[typeref.GetName()] = nodelist

    if node.IsA('Param'):
      typeref = node.typelist.GetReleases()[0]
      if typeref.IsA('Interface'):
        nodelist = self.struct_map.get(typeref.GetName(), [])
        nodelist.append(node)
        self.interface_map[typeref.GetName()] = nodelist

    return None


def GetPathFromNode(filenode, relpath=None, ext=None):
  path, name = os.path.split(filenode.GetProperty('NAME'))
  if ext: name = os.path.splitext(name)[0] + ext
  if path: name = os.path.join(path, name)
  if relpath: name = os.path.join(relpath, name)
  name = os.path.normpath(name)
  return name


def GetHeaderFromNode(filenode, relpath=None):
  return GetPathFromNode(filenode, relpath, ext='.h')


def WriteGroupMarker(out, node, last_group):
  # If we are part of a group comment marker...
  if last_group and last_group != node.cls:
    pre = CommentLines(['*',' @}', '']) + '\n'
  else:
    pre = '\n'

  if node.cls in ['Typedef', 'Interface', 'Struct', 'Enum']:
    if last_group != node.cls:
      pre += CommentLines(['*',' @addtogroup %ss' % node.cls, ' @{', ''])
    last_group = node.cls
  else:
    last_group = None
  out.Write(pre)
  return last_group


def GenerateHeader(out, filenode, releases):
  cgen = CGen()
  pref = ''
  do_comments = True

  # Generate definitions.
  last_group = None
  top_types = ['Typedef', 'Interface', 'Struct', 'Enum', 'Inline']
  for node in filenode.GetListOf(*top_types):
    # Skip if this node is not in this release
    if not node.InReleases(releases):
      print "Skiping %s" % node
      continue

    # End/Start group marker
    if do_comments:
      last_group = WriteGroupMarker(out, node, last_group)

    if node.IsA('Inline'):
      item = node.GetProperty('VALUE')
      # If 'C++' use __cplusplus wrapper
      if node.GetName() == 'cc':
        item = '#ifdef __cplusplus\n%s\n#endif  /* __cplusplus */\n\n' % item
      # If not C++ or C, then skip it
      elif not node.GetName() == 'c':
        continue
      if item: out.Write(item)
      continue

    #
    # Otherwise we are defining a file level object, so generate the
    # correct document notation.
    #
    item = cgen.Define(node, releases, prefix=pref, comment=True)
    if not item: continue
    asize = node.GetProperty('assert_size()')
    if asize:
      name = '%s%s' % (pref, node.GetName())
      if node.IsA('Struct'):
        form = 'PP_COMPILE_ASSERT_STRUCT_SIZE_IN_BYTES(%s, %s);\n'
      elif node.IsA('Enum'):
        if node.GetProperty('notypedef'):
          form = 'PP_COMPILE_ASSERT_ENUM_SIZE_IN_BYTES(%s, %s);\n'
        else:
          form = 'PP_COMPILE_ASSERT_SIZE_IN_BYTES(%s, %s);\n'
      else:
        form = 'PP_COMPILE_ASSERT_SIZE_IN_BYTES(%s, %s);\n'
      item += form % (name, asize[0])

    if item: out.Write(item)
  if last_group:
    out.Write(CommentLines(['*',' @}', '']) + '\n')


def CheckTypedefs(filenode, releases):
  """Checks that typedefs don't specify callbacks that take some structs.

  See http://crbug.com/233439 for details.
  """
  cgen = CGen()
  for node in filenode.GetListOf('Typedef'):
    build_list = node.GetUniqueReleases(releases)
    callnode = node.GetOneOf('Callspec')
    if callnode:
      for param in callnode.GetListOf('Param'):
        if param.GetListOf('Array'):
          continue
        if cgen.GetParamMode(param) != 'in':
          continue
        t = param.GetType(build_list[0])
        while t.IsA('Typedef'):
          t = t.GetType(build_list[0])
        if t.IsA('Struct') and t.GetProperty('passByValue'):
          raise Exception('%s is a struct in callback %s. '
                          'See http://crbug.com/233439' %
                          (t.GetName(), node.GetName()))


def CheckPassByValue(filenode, releases):
  """Checks that new pass-by-value structs are not introduced.

  See http://crbug.com/233439 for details.
  """
  cgen = CGen()
  # DO NOT add any more entries to this whitelist.
  # http://crbug.com/233439
  type_whitelist = ['PP_ArrayOutput', 'PP_CompletionCallback',
                    'PP_Ext_EventListener', 'PP_FloatPoint',
                    'PP_Point', 'PP_TouchPoint', 'PP_Var']
  nodes_to_check = filenode.GetListOf('Struct')
  nodes_to_check.extend(filenode.GetListOf('Union'))
  for node in nodes_to_check:
    if node.GetName() in type_whitelist:
      continue
    build_list = node.GetUniqueReleases(releases)
    if node.GetProperty('passByValue'):
      raise Exception('%s is a new passByValue struct or union. '
                      'See http://crbug.com/233439' % node.GetName())
    if node.GetProperty('returnByValue'):
      raise Exception('%s is a new returnByValue struct or union. '
                      'See http://crbug.com/233439' % node.GetName())


class HGen(GeneratorByFile):
  def __init__(self):
    Generator.__init__(self, 'C Header', 'cgen', 'Generate the C headers.')

  def GenerateFile(self, filenode, releases, options):
    CheckTypedefs(filenode, releases)
    CheckPassByValue(filenode, releases)
    savename = GetHeaderFromNode(filenode, GetOption('dstroot'))
    my_min, my_max = filenode.GetMinMax(releases)
    if my_min > releases[-1] or my_max < releases[0]:
      if os.path.isfile(savename):
        print "Removing stale %s for this range." % filenode.GetName()
        os.remove(os.path.realpath(savename))
      return False

    out = IDLOutFile(savename)
    self.GenerateHead(out, filenode, releases, options)
    self.GenerateBody(out, filenode, releases, options)
    self.GenerateTail(out, filenode, releases, options)
    return out.Close()

  def GenerateHead(self, out, filenode, releases, options):
    __pychecker__ = 'unusednames=options'

    proto = ProtoResolver()
    proto.Visit(filenode, None)

    cgen = CGen()
    gpath = GetOption('guard')
    def_guard = GetHeaderFromNode(filenode, relpath=gpath)
    def_guard = def_guard.replace(os.sep,'_').replace('.','_').upper() + '_'

    cright_node = filenode.GetChildren()[0]
    assert(cright_node.IsA('Copyright'))
    fileinfo = filenode.GetChildren()[1]
    assert(fileinfo.IsA('Comment'))

    out.Write('%s\n' % cgen.Copyright(cright_node))

    # Wrap the From ... modified ... comment if it would be >80 characters.
    from_text = 'From %s' % GetPathFromNode(filenode).replace(os.sep, '/')
    modified_text = 'modified %s.' % (
        filenode.GetProperty('DATETIME'))
    if len(from_text) + len(modified_text) < 74:
      out.Write('/* %s %s */\n\n' % (from_text, modified_text))
    else:
      out.Write('/* %s,\n *   %s\n */\n\n' % (from_text, modified_text))

    out.Write('#ifndef %s\n#define %s\n\n' % (def_guard, def_guard))
    # Generate set of includes

    deps = set()
    for release in releases:
      deps |= filenode.GetDeps(release)

    includes = set([])
    for dep in deps:
      depfile = dep.GetProperty('FILE')
      if depfile:
        includes.add(depfile)
    includes = [GetHeaderFromNode(
        include, relpath=gpath).replace(os.sep, '/') for include in includes]
    includes.append('ppapi/c/pp_macros.h')

    # Assume we need stdint if we "include" C or C++ code
    if filenode.GetListOf('Include'):
      includes.append('ppapi/c/pp_stdint.h')

    includes = sorted(set(includes))
    cur_include = GetHeaderFromNode(filenode,
                                    relpath=gpath).replace(os.sep, '/')
    for include in includes:
      if include == cur_include: continue
      out.Write('#include "%s"\n' % include)

    # Generate Prototypes
    if proto.struct_map:
      out.Write('\n/* Struct prototypes */\n')
      for struct in proto.struct_map:
        out.Write('struct %s;\n' % struct)

    # Create a macro for the highest available release number.
    if filenode.GetProperty('NAME').endswith('pp_macros.idl'):
      releasestr = ' '.join(releases)
      if releasestr:
        release_numbers = re.findall('[\d\_]+', releasestr)
        release = re.findall('\d+', release_numbers[-1])[0]
        if release:
          out.Write('\n#define PPAPI_RELEASE %s\n' % release)

    # Generate all interface defines
    out.Write('\n')
    for node in filenode.GetListOf('Interface'):
      idefs = ''
      macro = cgen.GetInterfaceMacro(node)
      unique = node.GetUniqueReleases(releases)

      # Skip this interface if there are no matching versions
      if not unique: continue

      # Skip this interface if it should have no interface string.
      if node.GetProperty('no_interface_string'): continue

      last_stable_ver = None
      last_dev_rel = None
      for rel in unique:
        channel = node.GetProperty('FILE').release_map.GetChannel(rel)
        if channel == 'dev':
          last_dev_rel = rel

      for rel in unique:
        version = node.GetVersion(rel)
        name = cgen.GetInterfaceString(node, version)
        strver = str(version).replace('.', '_')
        channel = node.GetProperty('FILE').release_map.GetChannel(rel)
        if channel == 'dev':
          # Skip dev channel interface versions that are
          #   Not the newest version, and
          #   Don't have an equivalent stable version.
          if rel != last_dev_rel and not node.DevInterfaceMatchesStable(rel):
            continue
          value_string = '"%s" /* dev */' % name
        else:
          value_string = '"%s"' % name
          last_stable_ver = strver
        idefs += cgen.GetDefine('%s_%s' % (macro, strver), value_string)
      if last_stable_ver:
        idefs += cgen.GetDefine(macro, '%s_%s' % (macro, last_stable_ver))
        idefs += '\n'

      out.Write(idefs)

    # Generate the @file comment
    out.Write('%s\n' % Comment(fileinfo, prefix='*\n @file'))

  def GenerateBody(self, out, filenode, releases, options):
    __pychecker__ = 'unusednames=options'
    GenerateHeader(out, filenode, releases)

  def GenerateTail(self, out, filenode, releases, options):
    __pychecker__ = 'unusednames=options,releases'
    gpath = GetOption('guard')
    def_guard = GetPathFromNode(filenode, relpath=gpath, ext='.h')
    def_guard = def_guard.replace(os.sep,'_').replace('.','_').upper() + '_'
    out.Write('#endif  /* %s */\n\n' % def_guard)


hgen = HGen()

def main(args):
  # Default invocation will verify the golden files are unchanged.
  failed = 0
  if not args:
    args = ['--wnone', '--diff', '--test', '--dstroot=.']

  ParseOptions(args)

  idldir = os.path.split(sys.argv[0])[0]
  idldir = os.path.join(idldir, 'test_cgen', '*.idl')
  filenames = glob.glob(idldir)
  ast = ParseFiles(filenames)
  if hgen.GenerateRelease(ast, 'M14', {}):
    print "Golden file for M14 failed."
    failed = 1
  else:
    print "Golden file for M14 passed."


  idldir = os.path.split(sys.argv[0])[0]
  idldir = os.path.join(idldir, 'test_cgen_range', '*.idl')
  filenames = glob.glob(idldir)

  ast = ParseFiles(filenames)
  if hgen.GenerateRange(ast, ['M13', 'M14', 'M15', 'M16', 'M17'], {}):
    print "Golden file for M13-M17 failed."
    failed =1
  else:
    print "Golden file for M13-M17 passed."

  return failed

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

