#!/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 Kconfig, split_expr, expr_value, expr_str, BOOL, \
                       TRISTATE, TRI_TO_STR, AND, OR


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['WARN_DEPRECATED'].tri_value == 2:
        check_deprecated(kconf)

    if kconf.syms['WARN_EXPERIMENTAL'].tri_value == 2:
        check_experimental(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['DEPRECATED']
    dep_expr = 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['EXPERIMENTAL']
    dep_expr = 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 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 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()
