#!/usr/bin/env fuchsia-vendored-python
# 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

FUCHSIA_ROOT = os.path.dirname(  # $root
    os.path.dirname(  # scripts
        os.path.dirname(os.path.realpath(os.path.abspath(__file__)))  # style
    )
)

SYSROOT_PREFIXES = ["ZIRCON_THIRD_PARTY_ULIB_MUSL_INCLUDE"]
sysroot_prefix = re.compile("^(" + "|".join(SYSROOT_PREFIXES) + ")_")

PUBLIC_PREFIXES = [
    "ZIRCON_SYSTEM_PUBLIC",
    "ZIRCON_SYSTEM_ULIB_.*_INCLUDE",
    "SDK(_.*_INCLUDE)?",
]
public_prefix = re.compile("^(" + "|".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(FUCHSIA_ROOT)
    relative_path = path[len(FUCHSIA_ROOT) :].strip("/")
    upper_path = relative_path.upper()
    header_guard = re.sub(disallowed_header_characters, "_", upper_path) + "_"
    header_guard = adjust_for_location(header_guard)
    return 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(
            "Allowable header guard values are %s"
            % list(all_header_guards.keys())
        )

    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

    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:
            check_file(os.path.join(root, path), fix_guards=fix_guards)


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


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
    for p in other_args:
        p = os.path.realpath(os.path.abspath(p))
        if os.path.isdir(p):
            check_dir(p, fix_guards=fix_guards)
        else:
            check_file(p, fix_guards=fix_guards)
    check_collisions()


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