#!/usr/bin/env python3

# Copyright (c) 2018-2023 Nordic Semiconductor ASA and Ulf Magnusson
# Originally modified from:
# https://github.com/ulfalizer/Kconfiglib/blob/master/examples/merge_config.py

# SPDX-License-Identifier: ISC

# Writes/updates the zephyr/.config configuration file by merging configuration
# files passed as arguments, e.g. board *_defconfig and application prj.conf
# files.
#
# When fragments haven't changed, zephyr/.config is both the input and the
# output, which just updates it. This is handled in the CMake files.
#
# Also does various checks (most via Kconfiglib warnings).

import argparse
import os
import re
import sys
import textwrap

# Zephyr doesn't use tristate symbols. They're supported here just to make the
# script a bit more generic.
from kconfiglib import (
    AND,
    BOOL,
    OR,
    TRI_TO_STR,
    TRISTATE,
    Kconfig,
    expr_str,
    expr_value,
    split_expr,
)


def main():
    args = parse_args()

    if args.zephyr_base:
        os.environ['ZEPHYR_BASE'] = args.zephyr_base

    print("Parsing " + args.kconfig_file)
    kconf = Kconfig(args.kconfig_file, warn_to_stderr=False,
                    suppress_traceback=True)

    if args.handwritten_input_configs:
        # Warn for assignments to undefined symbols, but only for handwritten
        # fragments, to avoid warnings-turned-errors when using an old
        # configuration file together with updated Kconfig files
        kconf.warn_assign_undef = True

        # prj.conf may override settings from the board configuration, so
        # disable warnings about symbols being assigned more than once
        kconf.warn_assign_override = False
        kconf.warn_assign_redun = False

    if args.forced_input_configs:
        # Do not warn on a redundant config.
        # The reason is that a regular .config will be followed by the forced
        # config which under normal circumstances should be identical to the
        # configured setting.
        # Only if user has modified to a value that gets overruled by the forced
        # a warning shall be issued.
        kconf.warn_assign_redun = False

    # Load files
    print(kconf.load_config(args.configs_in[0]))
    for config in args.configs_in[1:]:
        # replace=False creates a merged configuration
        print(kconf.load_config(config, replace=False))

    if args.handwritten_input_configs:
        # Check that there are no assignments to promptless symbols, which
        # have no effect.
        #
        # This only makes sense when loading handwritten fragments and not when
        # loading zephyr/.config, because zephyr/.config is configuration
        # output and also assigns promptless symbols.
        check_no_promptless_assign(kconf)

        # Print warnings for symbols that didn't get the assigned value. Only
        # do this for handwritten input too, to avoid likely unhelpful warnings
        # when using an old configuration and updating Kconfig files.
        check_assigned_sym_values(kconf)
        check_assigned_choice_values(kconf)

    if kconf.syms.get('WARN_DEPRECATED', kconf.y).tri_value == 2:
        check_deprecated(kconf)

    if kconf.syms.get('WARN_EXPERIMENTAL', kconf.y).tri_value == 2:
        check_experimental(kconf)

    check_not_secure(kconf)

    # Hack: Force all symbols to be evaluated, to catch warnings generated
    # during evaluation. Wait till the end to write the actual output files, so
    # that we don't generate any output if there are warnings-turned-errors.
    #
    # Kconfiglib caches calculated symbol values internally, so this is still
    # fast.
    kconf.write_config(os.devnull)

    warn_only = r"warning:.*set more than once."

    if kconf.warnings:
        if args.forced_input_configs:
            error_out = False
        else:
            error_out = True

        # Put a blank line between warnings to make them easier to read
        for warning in kconf.warnings:
            print("\n" + warning, file=sys.stderr)

            if not error_out and not re.search(warn_only, warning):
                # The warning is not a warn_only, fail the Kconfig.
                error_out = True

        # Turn all warnings into errors, so that e.g. assignments to undefined
        # Kconfig symbols become errors.
        #
        # A warning is generated by this script whenever a symbol gets a
        # different value than the one it was assigned. Keep that one as just a
        # warning for now.
        if error_out:
            err("Aborting due to Kconfig warnings")

    # Write the merged configuration and the C header
    print(kconf.write_config(args.config_out))
    print(kconf.write_autoconf(args.header_out))

    # Write the list of parsed Kconfig files to a file
    write_kconfig_filenames(kconf, args.kconfig_list_out)


def check_no_promptless_assign(kconf):
    # Checks that no promptless symbols are assigned

    for sym in kconf.unique_defined_syms:
        if sym.user_value is not None and promptless(sym):
            err(f"""\
{sym.name_and_loc} is assigned in a configuration file, but is not directly
user-configurable (has no prompt). It gets its value indirectly from other
symbols. """ + SYM_INFO_HINT.format(sym))


def check_assigned_sym_values(kconf):
    # Verifies that the values assigned to symbols "took" (matches the value
    # the symbols actually got), printing warnings otherwise. Choice symbols
    # are checked separately, in check_assigned_choice_values().

    for sym in kconf.unique_defined_syms:
        if sym.choice:
            continue

        user_value = sym.user_value
        if user_value is None:
            continue

        # Tristate values are represented as 0, 1, 2. Having them as "n", "m",
        # "y" is more convenient here, so convert.
        if sym.type in (BOOL, TRISTATE):
            user_value = TRI_TO_STR[user_value]

        if user_value != sym.str_value:
            msg = f"{sym.name_and_loc} was assigned the value '{user_value}'" \
                  f" but got the value '{sym.str_value}'. "

            # List any unsatisfied 'depends on' dependencies in the warning
            mdeps = missing_deps(sym)
            if mdeps:
                expr_strs = []
                for expr in mdeps:
                    estr = expr_str(expr)
                    if isinstance(expr, tuple):
                        # Add () around dependencies that aren't plain symbols.
                        # Gives '(FOO || BAR) (=n)' instead of
                        # 'FOO || BAR (=n)', which might be clearer.
                        estr = f"({estr})"
                    expr_strs.append(f"{estr} "
                                     f"(={TRI_TO_STR[expr_value(expr)]})")

                msg += "Check these unsatisfied dependencies: " + \
                    ", ".join(expr_strs) + ". "

            warn(msg + SYM_INFO_HINT.format(sym))


def missing_deps(sym):
    # check_assigned_sym_values() helper for finding unsatisfied dependencies.
    #
    # Given direct dependencies
    #
    #     depends on <expr> && <expr> && ... && <expr>
    #
    # on 'sym' (which can also come from e.g. a surrounding 'if'), returns a
    # list of all <expr>s with a value less than the value 'sym' was assigned
    # ("less" instead of "not equal" just to be general and handle tristates,
    # even though Zephyr doesn't use them).
    #
    # For string/int/hex symbols, just looks for <expr> = n.
    #
    # Note that <expr>s can be something more complicated than just a symbol,
    # like 'FOO || BAR' or 'FOO = "string"'.

    deps = split_expr(sym.direct_dep, AND)

    if sym.type in (BOOL, TRISTATE):
        return [dep for dep in deps if expr_value(dep) < sym.user_value]
    # string/int/hex
    return [dep for dep in deps if expr_value(dep) == 0]


def check_assigned_choice_values(kconf):
    # Verifies that any choice symbols that were selected (by setting them to
    # y) ended up as the selection, printing warnings otherwise.
    #
    # We check choice symbols separately to avoid warnings when two different
    # choice symbols within the same choice are set to y. This might happen if
    # a choice selection from a board defconfig is overridden in a prj.conf,
    # for example. The last choice symbol set to y becomes the selection (and
    # all other choice symbols get the value n).
    #
    # Without special-casing choices, we'd detect that the first symbol set to
    # y ended up as n, and print a spurious warning.

    for choice in kconf.unique_choices:
        if choice.user_selection and \
           choice.user_selection is not choice.selection:

            warn(f"""\
The choice symbol {choice.user_selection.name_and_loc} was selected (set =y),
but {choice.selection.name_and_loc if choice.selection else "no symbol"} ended
up as the choice selection. """ + SYM_INFO_HINT.format(choice.user_selection))


# Hint on where to find symbol information. Used like
# SYM_INFO_HINT.format(sym).
SYM_INFO_HINT = """\
See http://docs.zephyrproject.org/latest/kconfig.html#CONFIG_{0.name} and/or
look up {0.name} in the menuconfig/guiconfig interface. The Application
Development Primer, Setting Configuration Values, and Kconfig - Tips and Best
Practices sections of the manual might be helpful too.\
"""


def check_deprecated(kconf):
    deprecated = kconf.syms.get('DEPRECATED')
    dep_expr = kconf.n if deprecated is None else deprecated.rev_dep

    if dep_expr is not kconf.n:
        selectors = [s for s in split_expr(dep_expr, OR) if expr_value(s) == 2]
        for selector in selectors:
            selector_name = split_expr(selector, AND)[0].name
            warn(f'Deprecated symbol {selector_name} is enabled.')


def check_experimental(kconf):
    experimental = kconf.syms.get('EXPERIMENTAL')
    dep_expr = kconf.n if experimental is None else experimental.rev_dep

    if dep_expr is not kconf.n:
        selectors = [s for s in split_expr(dep_expr, OR) if expr_value(s) == 2]
        for selector in selectors:
            selector_name = split_expr(selector, AND)[0].name
            warn(f'Experimental symbol {selector_name} is enabled.')

def check_not_secure(kconf):
    not_secure = kconf.syms.get('NOT_SECURE')
    dep_expr = kconf.n if not_secure is None else not_secure.rev_dep

    if dep_expr is not kconf.n:
        selectors = [s for s in split_expr(dep_expr, OR) if expr_value(s) == 2]
        for selector in selectors:
            selector_name = split_expr(selector, AND)[0].name
            warn(f'Not secure symbol {selector_name} is enabled.')


def promptless(sym):
    # Returns True if 'sym' has no prompt. Since the symbol might be defined in
    # multiple locations, we need to check all locations.

    return not any(node.prompt for node in sym.nodes)


def write_kconfig_filenames(kconf, kconfig_list_path):
    # Writes a sorted list with the absolute paths of all parsed Kconfig files
    # to 'kconfig_list_path'. The paths are realpath()'d, and duplicates are
    # removed. This file is used by CMake to look for changed Kconfig files. It
    # needs to be deterministic.

    with open(kconfig_list_path, 'w') as out:
        for path in sorted({os.path.realpath(os.path.join(kconf.srctree, path))
                            for path in set(kconf.kconfig_filenames)}):
            print(path, file=out)


def parse_args():
    parser = argparse.ArgumentParser(allow_abbrev=False)

    parser.add_argument("--handwritten-input-configs",
                        action="store_true",
                        help="Assume the input configuration fragments are "
                             "handwritten fragments and do additional checks "
                             "on them, like no promptless symbols being "
                             "assigned")
    parser.add_argument("--forced-input-configs",
                        action="store_true",
                        help="Indicate the input configuration files are "
                             "followed by an forced configuration file."
                             "The forced configuration is used to forcefully "
                             "set specific configuration settings to a "
                             "pre-defined value and thereby remove any user "
                             " adjustments.")
    parser.add_argument("--zephyr-base",
                        help="Path to current Zephyr installation")
    parser.add_argument("kconfig_file",
                        help="Top-level Kconfig file")
    parser.add_argument("config_out",
                        help="Output configuration file")
    parser.add_argument("header_out",
                        help="Output header file")
    parser.add_argument("kconfig_list_out",
                        help="Output file for list of parsed Kconfig files")
    parser.add_argument("configs_in",
                        nargs="+",
                        help="Input configuration fragments. Will be merged "
                             "together.")

    return parser.parse_args()


def warn(msg):
    # Use a large fill() width to try to avoid linebreaks in the symbol
    # reference link, and add some extra newlines to set the message off from
    # surrounding text (this usually gets printed as part of spammy CMake
    # output)
    print("\n" + textwrap.fill("warning: " + msg, 100) + "\n", file=sys.stderr)


def err(msg):
    sys.exit("\n" + textwrap.fill("error: " + msg, 100) + "\n")


if __name__ == "__main__":
    main()
