#!/usr/bin/env python2.7
# Copyright 2016 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Script to check C and C++ file header guards.

This script accepts a list of file or directory arguments. If a given
path is a file, it runs the checker on it. If the path is a directory,
it runs the checker on all files in that directory.

In addition, this script checks for potential header guard
collisions. This is useful since we munge / to _, and so
    lib/abc/xyz/xyz.h
and
    lib/abc_xyz/xyz.h
both want to use LIB_ABC_XYZ_XYZ_H_ as a header guard.

"""

import argparse
import collections
import fileinput
import os.path
import re
import string
import sys

SOURCE_ROOT = os.path.dirname(  # $root
    os.path.dirname(  # tools
        os.path.dirname(  # style
            os.path.realpath(os.path.abspath(__file__)))))

SYSROOT_PREFIXES = [
    'ZIRCON_SYSTEM_PUBLIC',
    'ZIRCON_THIRD_PARTY_ULIB_MUSL_INCLUDE',
]
sysroot_prefix = re.compile('^(' + string.join(SYSROOT_PREFIXES, '|') + ')_')

PUBLIC_PREFIXES = [
    'ZIRCON_SYSTEM_ULIB_.*_INCLUDE', 'GARNET_PUBLIC', 'PERIDOT_PUBLIC',
    'TOPAZ_PUBLIC', 'SDK'
]
public_prefix = re.compile('^(' + string.join(PUBLIC_PREFIXES, '|') + ')_')

all_header_guards = collections.defaultdict(list)

pragma_once = re.compile('^#pragma once$')
disallowed_header_characters = re.compile('[^a-zA-Z0-9_]')


def adjust_for_location(header_guard):
  """Remove internal location prefix from public headers if applicable."""
  # Remove public prefixes
  header_guard = public_prefix.sub('', header_guard, 1)
  # Replace sysroot prefixes
  header_guard = sysroot_prefix.sub('SYSROOT_', header_guard, 1)

  return header_guard


def header_guard_from_path(path):
  """Compute the header guard from the path"""
  assert (path.startswith(SOURCE_ROOT))
  relative_path = path[len(SOURCE_ROOT):].strip('/')
  upper_path = relative_path.upper()
  header_guard = re.sub(disallowed_header_characters, '_', upper_path) + '_'
  header_guard = adjust_for_location(header_guard)
  return 'COBALT_' + header_guard


def check_file(path, fix_guards=False):
  """Check whether the file has a correct header guard.

    A header guard can either be a #pragma once, or else a matching set of
        #ifndef PATH_TO_FILE_
        #define PATH_TO_FILE_
        ...
        #endif  // PATH_TO_FILE_
    preprocessor directives, where both '.' and '/' in the path are
    mapped to '_', and a trailing '_' is appended.

    In either the #pragma once case or the header guard case, it is
    assumed that there is no trailing or leading whitespace.

    """

  # Only check .h files
  if path[-2:] != '.h':
    return True

  header_guard = header_guard_from_path(path)
  all_header_guards[header_guard].append(path)

  ifndef = re.compile('^#ifndef %s$' % header_guard)
  define = re.compile('^#define %s$' % header_guard)
  endif = re.compile('^#endif +// *%s$' % header_guard)

  found_pragma_once = False
  found_ifndef = False
  found_define = False
  found_endif = False

  with open(path, 'r') as f:
    for line in f.readlines():
      match = pragma_once.match(line)
      if match:
        if found_pragma_once:
          print('%s contains multiple #pragma once' % path)
          return False
        found_pragma_once = True

      match = ifndef.match(line)
      if match:
        if found_ifndef:
          print('%s contains multiple ifndef header guards' % path)
          return False
        found_ifndef = True

      match = define.match(line)
      if match:
        if found_define:
          print('%s contains multiple define header guards' % path)
          return False
        found_define = True

      match = endif.match(line)
      if match:
        if found_endif:
          print('%s contains multiple endif header guards' % path)
          return False
        found_endif = True

  if found_pragma_once:
    if found_ifndef or found_define or found_endif:
      print('%s contains both #pragma once and header guards' % path)
      return False
    if not fix_guards:
      return True

  if found_ifndef and found_define and found_endif:
    return True

  if not found_ifndef:
    print('%s did not contain ifndef part of its header guard' % path)
  elif not found_define:
    print('%s did not contain define part of its header guard' % path)
  elif not found_endif:
    print('%s did not contain endif part of its header guard' % path)
  elif fix_guards:
    if found_pragma_once:
      print('%s contained #pragma once instead of a header guard' % path)
    else:
      print('%s did not contain a header guard or the header guard did '
            'not match the file path' % path)
  else:
    print('%s contained neither a proper header guard nor #pragma once' % path)

  header_guards_fixed = False
  if fix_guards:
    header_guards_fixed = fix_header_guard(path, header_guard)

  if not header_guards_fixed:
    print('Expected header guard value is %s' % header_guard)

  return False


def fix_header_guard(path, header_guard):
  """Attempt to fix the header guard in the given file."""
  ifndef = re.compile('^#ifndef [^\s]+_H_$')
  define = re.compile('^#define [^\s]+_H_$')
  endif = re.compile('^#endif +// *[^\s]+_H_$')
  fixed_ifndef = False
  fixed_define = False
  fixed_endif = False
  fixed_pragma_once = False

  for line in fileinput.input(path, inplace=1):
    (new_line, changes) = re.subn(ifndef, '#ifndef %s' % header_guard, line)
    if changes:
      fixed_ifndef = True
      sys.stdout.write(new_line)
      continue
    (new_line, changes) = re.subn(define, '#define %s' % header_guard, line)
    if changes:
      fixed_define = True
      sys.stdout.write(new_line)
      continue
    (new_line, changes) = re.subn(endif, '#endif  // %s' % header_guard, line)
    if changes:
      fixed_endif = True
      sys.stdout.write(new_line)
      continue
    if pragma_once.match(line):
      fixed_pragma_once = True
      sys.stdout.write('#ifndef %s\n' % header_guard)
      sys.stdout.write('#define %s\n' % header_guard)
      continue
    sys.stdout.write(line)

  if fixed_pragma_once:
    with open(path, 'a') as file:
      file.write('\n')
      file.write('#endif  // %s\n' % header_guard)

  if (fixed_ifndef and fixed_define and fixed_endif) or fixed_pragma_once:
    print('Fixed!')
    return True

  print('Not fixed...')
  return False


def check_dir(p, fix_guards=False):
  """Walk recursively over a directory checking .h files"""

  def prune(d):
    if d[0] == '.' or d == 'third_party':
      return True
    return False

  bad_files = 0
  for root, dirs, paths in os.walk(p):
    # Prune dot directories like .git
    [dirs.remove(d) for d in list(dirs) if prune(d)]
    for path in paths:
      if not check_file(os.path.join(root, path), fix_guards=fix_guards):
        bad_files += 1

  return bad_files


def check_collisions():
  collisions = 0
  for header_guard, paths in all_header_guards.iteritems():
    if len(paths) == 1:
      continue
    collisions += 1
    print('Multiple files could use %s as a header guard:' % header_guard)
    for path in paths:
      print('    %s' % path)

  return collisions


def main():
  parser = argparse.ArgumentParser()
  parser.add_argument(
      '--fix', help='Correct wrong header guards', action='store_true')
  (arg_results, other_args) = parser.parse_known_args()
  fix_guards = arg_results.fix
  errors = 0
  for p in other_args:
    p = os.path.realpath(os.path.abspath(p))
    if os.path.isdir(p):
      errors += check_dir(p, fix_guards=fix_guards)
    else:
      if not check_file(p, fix_guards=fix_guards):
        errors += 1
  errors += check_collisions()

  if not fix_guards:
    return errors
  else:
    return 0


if __name__ == '__main__':
  sys.exit(main())
