#!/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 json
import os
import pickle
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,
    TYPE_TO_STR,
    Kconfig,
    Symbol,
    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 value origin information for the merged configuration
    trace_data = collect_trace_data(kconf)
    with open(args.config_out + '-trace.pickle', 'wb') as f:
        pickle.dump(trace_data, f)
    with open(args.config_out + '-trace.json', 'w') as f:
        json.dump(trace_data, f, indent=2)

    # 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 collect_trace_data(kconf):
    """
    Collects trace data for all symbols in 'kconf'. The output is currently a
    list of 6-tuples with one entry per symbol definition, with the following
    layout:

        (name, visibility, type, value, kind, location)

    where the first 4 entries are the string representation of the symbol's
    properties, and 'kind' and 'location' are taken from its 'origin'
    attribute.
    """

    # NOTE: this data is used by scripts/kconfig/traceconfig.py and the tests
    # under tests/kconfig/tracing. Make sure to keep them aligned if the
    # format changes in any way.

    trace_data = []
    for node in kconf.node_iter(True):
        item = node.item
        if not isinstance(item, Symbol):
            continue

        origin = item.origin
        if origin is None:
            continue

        name = kconf.config_prefix + item.name
        kind, loc = origin
        value = None if kind == "unset" else item.str_value

        trace_entry = (name, TRI_TO_STR[item.visibility],
                       TYPE_TO_STR[item.type], value, kind, loc)
        trace_data.append(trace_entry)

    return trace_data


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()
