# Copyright 2015 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# Runs the Microsoft Message Compiler (mc.exe).
#
# Usage: message_compiler.py <environment_file> [<args to mc.exe>*]


import difflib
import filecmp
import os
import re
import shutil
import subprocess
import sys
import tempfile

def main():
  env_file, rest = sys.argv[1], sys.argv[2:]

  # Parse some argument flags.
  header_dir = None
  resource_dir = None
  input_file = None
  for i, arg in enumerate(rest):
    if arg == '-h' and len(rest) > i + 1:
      assert header_dir == None
      header_dir = rest[i + 1]
    elif arg == '-r' and len(rest) > i + 1:
      assert resource_dir == None
      resource_dir = rest[i + 1]
    elif arg.endswith('.mc') or arg.endswith('.man'):
      assert input_file == None
      input_file = arg

  # Copy checked-in outputs to final location.
  THIS_DIR = os.path.abspath(os.path.dirname(__file__))
  assert header_dir == resource_dir
  source = os.path.join(THIS_DIR, "..", "..",
      "third_party", "win_build_output",
      re.sub(r'^(?:[^/]+/)?gen/', 'mc/', header_dir))
  # Set copy_function to shutil.copy to update the timestamp on the destination.
  shutil.copytree(source,
                  header_dir,
                  copy_function=shutil.copy,
                  dirs_exist_ok=True)

  # On non-Windows, that's all we can do.
  if sys.platform != 'win32':
    return

  # On Windows, run mc.exe on the input and check that its outputs are
  # identical to the checked-in outputs.

  # Read the environment block from the file. This is stored in the format used
  # by CreateProcess. Drop last 2 NULs, one for list terminator, one for
  # trailing vs. separator.
  env_pairs = open(env_file).read()[:-2].split('\0')
  env_dict = dict([item.split('=', 1) for item in env_pairs])

  extension = os.path.splitext(input_file)[1]
  if extension in ['.man', '.mc']:
    # For .man files, mc's output changed significantly from Version 10.0.15063
    # to Version 10.0.16299.  We should always have the output of the current
    # default SDK checked in and compare to that. Early out if a different SDK
    # is active. This also happens with .mc files.
    # TODO(thakis): Check in new baselines and compare to 16299 instead once
    # we use the 2017 Fall Creator's Update by default.
    mc_help = subprocess.check_output(['mc.exe', '/?'], env=env_dict,
                                      stderr=subprocess.STDOUT, shell=True)
    version = re.search(br'Message Compiler\s+Version (\S+)', mc_help).group(1)
    if version != b'10.0.22621':
      return

  # mc writes to stderr, so this explicitly redirects to stdout and eats it.
  try:
    tmp_dir = tempfile.mkdtemp()
    delete_tmp_dir = True
    if header_dir:
      rest[rest.index('-h') + 1] = tmp_dir
      header_dir = tmp_dir
    if resource_dir:
      rest[rest.index('-r') + 1] = tmp_dir
      resource_dir = tmp_dir

    # This needs shell=True to search the path in env_dict for the mc
    # executable.
    subprocess.check_output(['mc.exe'] + rest,
                            env=env_dict,
                            stderr=subprocess.STDOUT,
                            shell=True)
    # We require all source code (in particular, the header generated here) to
    # be UTF-8. jinja can output the intermediate .mc file in UTF-8 or UTF-16LE.
    # However, mc.exe only supports Unicode via the -u flag, and it assumes when
    # that is specified that the input is UTF-16LE (and errors out on UTF-8
    # files, assuming they're ANSI). Even with -u specified and UTF16-LE input,
    # it generates an ANSI header, and includes broken versions of the message
    # text in the comment before the value. To work around this, for any invalid
    # // comment lines, we simply drop the line in the header after building it.
    # Also, mc.exe apparently doesn't always write #define lines in
    # deterministic order, so manually sort each block of #defines.
    if header_dir:
      header_file = os.path.join(
          header_dir, os.path.splitext(os.path.basename(input_file))[0] + '.h')
      header_contents = []
      with open(header_file, 'rb') as f:
        define_block = []  # The current contiguous block of #defines.
        for line in f.readlines():
          if line.startswith(b'//') and b'?' in line:
            continue
          if line.startswith(b'#define '):
            define_block.append(line)
            continue
          # On the first non-#define line, emit the sorted preceding #define
          # block.
          header_contents += sorted(define_block, key=lambda s: s.split()[-1])
          define_block = []
          header_contents.append(line)
        # If the .h file ends with a #define block, flush the final block.
        header_contents += sorted(define_block, key=lambda s: s.split()[-1])
      with open(header_file, 'wb') as f:
        f.write(b''.join(header_contents))

    # mc.exe invocation and post-processing are complete, now compare the output
    # in tmp_dir to the checked-in outputs.
    diff = filecmp.dircmp(tmp_dir, source)
    if diff.diff_files or set(diff.left_list) != set(diff.right_list):
      print('mc.exe output different from files in %s, see %s' % (source,
                                                                  tmp_dir))
      diff.report()
      for f in diff.diff_files:
        if f.endswith('.bin'): continue
        fromfile = os.path.join(source, f)
        tofile = os.path.join(tmp_dir, f)
        print(''.join(
            difflib.unified_diff(
                open(fromfile).readlines(),
                open(tofile).readlines(), fromfile, tofile)))
      delete_tmp_dir = False
      sys.exit(1)
  except subprocess.CalledProcessError as e:
    print(e.output)
    sys.exit(e.returncode)
  finally:
    if os.path.exists(tmp_dir) and delete_tmp_dir:
      shutil.rmtree(tmp_dir)

if __name__ == '__main__':
  main()
