#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0+

"""Build and query a Kconfig database for boards.

See doc/develop/qconfig.rst for documentation.

Author: Masahiro Yamada <yamada.masahiro@socionext.com>
Author: Simon Glass <sjg@chromium.org>
"""

from argparse import ArgumentParser
import collections
from contextlib import ExitStack
import doctest
import filecmp
import fnmatch
import glob
import multiprocessing
import os
import queue
import re
import shutil
import subprocess
import sys
import tempfile
import threading
import time
import unittest

from buildman import bsettings
from buildman import kconfiglib
from buildman import toolchain
from u_boot_pylib import terminal

SHOW_GNU_MAKE = 'scripts/show-gnu-make'
SLEEP_TIME=0.03

STATE_IDLE = 0
STATE_DEFCONFIG = 1
STATE_AUTOCONF = 2
STATE_SAVEDEFCONFIG = 3

AUTO_CONF_PATH = 'include/config/auto.conf'
CONFIG_DATABASE = 'qconfig.db'
FAILED_LIST = 'qconfig.failed'

CONFIG_LEN = len('CONFIG_')

SIZES = {
    'SZ_1':    0x00000001, 'SZ_2':    0x00000002,
    'SZ_4':    0x00000004, 'SZ_8':    0x00000008,
    'SZ_16':   0x00000010, 'SZ_32':   0x00000020,
    'SZ_64':   0x00000040, 'SZ_128':  0x00000080,
    'SZ_256':  0x00000100, 'SZ_512':  0x00000200,
    'SZ_1K':   0x00000400, 'SZ_2K':   0x00000800,
    'SZ_4K':   0x00001000, 'SZ_8K':   0x00002000,
    'SZ_16K':  0x00004000, 'SZ_32K':  0x00008000,
    'SZ_64K':  0x00010000, 'SZ_128K': 0x00020000,
    'SZ_256K': 0x00040000, 'SZ_512K': 0x00080000,
    'SZ_1M':   0x00100000, 'SZ_2M':   0x00200000,
    'SZ_4M':   0x00400000, 'SZ_8M':   0x00800000,
    'SZ_16M':  0x01000000, 'SZ_32M':  0x02000000,
    'SZ_64M':  0x04000000, 'SZ_128M': 0x08000000,
    'SZ_256M': 0x10000000, 'SZ_512M': 0x20000000,
    'SZ_1G':   0x40000000, 'SZ_2G':   0x80000000,
    'SZ_4G':  0x100000000
}

RE_REMOVE_DEFCONFIG = re.compile(r'(.*)_defconfig')

# CONFIG symbols present in the build system (from Linux) but not actually used
# in U-Boot; KCONFIG symbols
IGNORE_SYMS = ['DEBUG_SECTION_MISMATCH', 'FTRACE_MCOUNT_RECORD', 'GCOV_KERNEL',
               'GCOV_PROFILE_ALL', 'KALLSYMS', 'KASAN', 'MODVERSIONS', 'SHELL',
               'TPL_BUILD', 'VPL_BUILD', 'IS_ENABLED', 'FOO', 'IF_ENABLED_INT',
               'IS_ENABLED_', 'IS_ENABLED_1', 'IS_ENABLED_2', 'IS_ENABLED_3',
               'SPL_', 'TPL_', 'SPL_FOO', 'TPL_FOO', 'TOOLS_FOO',
               'ACME', 'SPL_ACME', 'TPL_ACME', 'TRACE_BRANCH_PROFILING',
               'VAL', '_UNDEFINED', 'SPL_BUILD', 'XPL_BUILD', ]

SPL_PREFIXES = ['SPL_', 'TPL_', 'VPL_', 'TOOLS_']

### helper functions ###
def check_top_directory():
    """Exit if we are not at the top of source directory."""
    for fname in 'README', 'Licenses':
        if not os.path.exists(fname):
            sys.exit('Please run at the top of source directory.')

def check_clean_directory():
    """Exit if the source tree is not clean."""
    for fname in '.config', 'include/config':
        if os.path.exists(fname):
            sys.exit("source tree is not clean, please run 'make mrproper'")

def get_make_cmd():
    """Get the command name of GNU Make.

    U-Boot needs GNU Make for building, but the command name is not
    necessarily "make". (for example, "gmake" on FreeBSD).
    Returns the most appropriate command name on your system.
    """
    with subprocess.Popen([SHOW_GNU_MAKE], stdout=subprocess.PIPE) as proc:
        ret = proc.communicate()
        if proc.returncode:
            sys.exit('GNU Make not found')
    return ret[0].rstrip()

def get_matched_defconfig(line):
    """Get the defconfig files that match a pattern

    Args:
        line (str): Path or filename to match, e.g. 'configs/snow_defconfig' or
            'k2*_defconfig'. If no directory is provided, 'configs/' is
            prepended

    Returns:
        list of str: a list of matching defconfig files
    """
    dirname = os.path.dirname(line)
    if dirname:
        pattern = line
    else:
        pattern = os.path.join('configs', line)
    return glob.glob(pattern) + glob.glob(pattern + '_defconfig')

def get_matched_defconfigs(defconfigs_file):
    """Get all the defconfig files that match the patterns in a file.

    Args:
        defconfigs_file (str): File containing a list of defconfigs to process,
            or '-' to read the list from stdin

    Returns:
        list of str: A list of paths to defconfig files, with no duplicates
    """
    defconfigs = []
    with ExitStack() as stack:
        if defconfigs_file == '-':
            inf = sys.stdin
            defconfigs_file = 'stdin'
        else:
            inf = stack.enter_context(open(defconfigs_file, encoding='utf-8'))
        for i, line in enumerate(inf):
            line = line.strip()
            if not line:
                continue # skip blank lines silently
            if ' ' in line:
                line = line.split(' ')[0]  # handle 'git log' input
            matched = get_matched_defconfig(line)
            if not matched:
                print(f"warning: {defconfigs_file}:{i + 1}: no defconfig matched '{line}'",
                      file=sys.stderr)

            defconfigs += matched

    # use set() to drop multiple matching
    return [defconfig[len('configs') + 1:]  for defconfig in set(defconfigs)]

def get_all_defconfigs():
    """Get all the defconfig files under the configs/ directory.

    Returns:
        list of str: List of paths to defconfig files
    """
    defconfigs = []
    for (dirpath, _, filenames) in os.walk('configs'):
        dirpath = dirpath[len('configs') + 1:]
        for filename in fnmatch.filter(filenames, '*_defconfig'):
            defconfigs.append(os.path.join(dirpath, filename))

    return defconfigs

def write_file(fname, data):
    """Write data to a file

    Args:
        fname (str): Filename to write to
        data (list of str): Lines to write (with or without trailing newline);
            or str to write
    """
    with open(fname, 'w', encoding='utf-8') as out:
        if isinstance(data, list):
            for line in data:
                print(line.rstrip('\n'), file=out)
        else:
            out.write(data)

def read_file(fname, as_lines=True, skip_unicode=False):
    """Read a file and return the contents

    Args:
        fname (str): Filename to read from
        as_lines (bool): Return file contents as a list of lines
        skip_unicode (bool): True to report unicode errors and continue

    Returns:
        iter of str: List of ;ines from the file with newline removed; str if
            as_lines is False with newlines intact; or None if a unicode error
            occurred

    Raises:
        UnicodeDecodeError: Unicode error occurred when reading
    """
    with open(fname, encoding='utf-8') as inf:
        try:
            if as_lines:
                return [line.rstrip('\n') for line in inf.readlines()]
            return inf.read()
        except UnicodeDecodeError as exc:
            if not skip_unicode:
                raise
            print(f"Failed on file '{fname}: {exc}")
            return None


### classes ###
class Progress:
    """Progress Indicator"""

    def __init__(self, col, total):
        """Create a new progress indicator.

        Args:
            col (terminal.Color): Colour-output class
            total (int): A number of defconfig files to process.

            current (int): Number of boards processed so far
            failed (int): Number of failed boards
            failure_msg (str): Message indicating number of failures, '' if none
        """
        self.col = col
        self.total = total

        self.current = 0
        self.good = 0
        self.failed = None
        self.failure_msg = None

    def inc(self, success):
        """Increment the number of processed defconfig files.

        Args:
            success (bool): True if processing succeeded
        """
        self.good += success
        self.current += 1

    def show(self):
        """Display the progress."""
        if self.current != self.total:
            line = self.col.build(self.col.GREEN, f'{self.good:5d}')
            line += self.col.build(self.col.RED,
                                   f'{self.current - self.good:5d}')
            line += self.col.build(self.col.MAGENTA,
                                   f'/{self.total - self.current}')
            print(f'{line}  \r', end='')
        sys.stdout.flush()

    def completed(self):
        """Set up extra properties when completed"""
        self.failed = self.total - self.good
        self.failure_msg = f'{self.failed} failed, ' if self.failed else ''


def scan_kconfig():
    """Scan all the Kconfig files and create a Config object

    Returns:
        Kconfig object
    """
    # Define environment variables referenced from Kconfig
    os.environ['srctree'] = os.getcwd()
    os.environ['UBOOTVERSION'] = 'dummy'
    os.environ['KCONFIG_OBJDIR'] = ''
    os.environ['CC'] = 'gcc'
    return kconfiglib.Kconfig()


# pylint: disable=R0903
class KconfigParser:
    """A parser of .config and include/autoconf.mk."""

    re_arch = re.compile(r'CONFIG_SYS_ARCH="(.*)"')
    re_cpu = re.compile(r'CONFIG_SYS_CPU="(.*)"')

    def __init__(self, args, build_dir):
        """Create a new parser.

        Args:
          args (Namespace): program arguments
          build_dir: Build directory.
        """
        self.args = args
        self.dotconfig = os.path.join(build_dir, '.config')
        self.autoconf = os.path.join(build_dir, 'include', 'autoconf.mk')
        self.spl_autoconf = os.path.join(build_dir, 'spl', 'include',
                                         'autoconf.mk')
        self.config_autoconf = os.path.join(build_dir, AUTO_CONF_PATH)
        self.defconfig = os.path.join(build_dir, 'defconfig')

    def get_arch(self):
        """Parse .config file and return the architecture.

        Returns:
          Architecture name (e.g. 'arm').
        """
        arch = ''
        cpu = ''
        for line in read_file(self.dotconfig):
            m_arch = self.re_arch.match(line)
            if m_arch:
                arch = m_arch.group(1)
                continue
            m_cpu = self.re_cpu.match(line)
            if m_cpu:
                cpu = m_cpu.group(1)

        if not arch:
            return None

        # fix-up for aarch64
        if arch == 'arm' and cpu == 'armv8':
            arch = 'aarch64'

        return arch


class DatabaseThread(threading.Thread):
    """This thread processes results from Slot threads.

    It collects the data in the master config directary. There is only one
    result thread, and this helps to serialise the build output.
    """
    def __init__(self, config_db, db_queue):
        """Set up a new result thread

        Args:
            builder: Builder which will be sent each result
        """
        threading.Thread.__init__(self)
        self.config_db = config_db
        self.db_queue= db_queue

    def run(self):
        """Called to start up the result thread.

        We collect the next result job and pass it on to the build.
        """
        while True:
            defconfig, configs = self.db_queue.get()
            self.config_db[defconfig] = configs
            self.db_queue.task_done()


class Slot:

    """A slot to store a subprocess.

    Each instance of this class handles one subprocess.
    This class is useful to control multiple threads
    for faster processing.
    """

    def __init__(self, toolchains, args, progress, devnull, make_cmd,
                 reference_src_dir, db_queue):
        """Create a new process slot.

        Args:
          toolchains: Toolchains object containing toolchains.
          args: Program arguments
          progress: A progress indicator.
          devnull: A file object of '/dev/null'.
          make_cmd: command name of GNU Make.
          reference_src_dir: Determine the true starting config state from this
                             source tree.
          db_queue: output queue to write config info for the database
          col (terminal.Color): Colour object
        """
        self.toolchains = toolchains
        self.args = args
        self.progress = progress
        self.build_dir = tempfile.mkdtemp()
        self.devnull = devnull
        self.make_cmd = (make_cmd, 'O=' + self.build_dir)
        self.reference_src_dir = reference_src_dir
        self.db_queue = db_queue
        self.col = progress.col
        self.parser = KconfigParser(args, self.build_dir)
        self.state = STATE_IDLE
        self.failed_boards = set()
        self.defconfig = None
        self.log = []
        self.current_src_dir = None
        self.proc = None

    def __del__(self):
        """Delete the working directory

        This function makes sure the temporary directory is cleaned away
        even if Python suddenly dies due to error.  It should be done in here
        because it is guaranteed the destructor is always invoked when the
        instance of the class gets unreferenced.

        If the subprocess is still running, wait until it finishes.
        """
        if self.state != STATE_IDLE:
            while self.proc.poll() is None:
                pass
        shutil.rmtree(self.build_dir)

    def add(self, defconfig):
        """Assign a new subprocess for defconfig and add it to the slot.

        If the slot is vacant, create a new subprocess for processing the
        given defconfig and add it to the slot.  Just returns False if
        the slot is occupied (i.e. the current subprocess is still running).

        Args:
          defconfig (str): defconfig name.

        Returns:
          Return True on success or False on failure
        """
        if self.state != STATE_IDLE:
            return False

        self.defconfig = defconfig
        self.log = []
        self.current_src_dir = self.reference_src_dir
        self.do_defconfig()
        return True

    def poll(self):
        """Check the status of the subprocess and handle it as needed.

        Returns True if the slot is vacant (i.e. in idle state).
        If the configuration is successfully finished, assign a new
        subprocess to build include/autoconf.mk.
        If include/autoconf.mk is generated, invoke the parser to
        parse the .config and the include/autoconf.mk, moving
        config options to the .config as needed.
        If the .config was updated, run "make savedefconfig" to sync
        it, update the original defconfig, and then set the slot back
        to the idle state.

        Returns:
          Return True if the subprocess is terminated, False otherwise
        """
        if self.state == STATE_IDLE:
            return True

        if self.proc.poll() is None:
            return False

        if self.proc.poll() != 0:
            self.handle_error()
        elif self.state == STATE_DEFCONFIG:
            if self.reference_src_dir and not self.current_src_dir:
                self.do_savedefconfig()
            else:
                self.do_autoconf()
        elif self.state == STATE_AUTOCONF:
            if self.current_src_dir:
                self.current_src_dir = None
                self.do_defconfig()
            elif self.args.build_db:
                self.do_build_db()
            else:
                self.do_savedefconfig()
        elif self.state == STATE_SAVEDEFCONFIG:
            self.update_defconfig()
        else:
            sys.exit('Internal Error. This should not happen.')

        return self.state == STATE_IDLE

    def handle_error(self):
        """Handle error cases."""

        self.log.append(self.col.build(self.col.RED, 'Failed to process',
                                       bright=True))
        if self.args.verbose:
            for line in self.proc.stderr.read().decode().splitlines():
                self.log.append(self.col.build(self.col.CYAN, line, True))
        self.finish(False)

    def do_defconfig(self):
        """Run 'make <board>_defconfig' to create the .config file."""

        cmd = list(self.make_cmd)
        cmd.append(self.defconfig)
        # pylint: disable=R1732
        self.proc = subprocess.Popen(cmd, stdout=self.devnull,
                                     stderr=subprocess.PIPE,
                                     cwd=self.current_src_dir)
        self.state = STATE_DEFCONFIG

    def do_autoconf(self):
        """Run 'make AUTO_CONF_PATH'."""

        arch = self.parser.get_arch()
        try:
            tchain = self.toolchains.Select(arch)
        except ValueError:
            self.log.append(self.col.build(
                self.col.YELLOW,
                f"Tool chain for '{arch}' is missing: do nothing"))
            self.finish(False)
            return
        env = tchain.MakeEnvironment(False)

        cmd = list(self.make_cmd)
        cmd.append('KCONFIG_IGNORE_DUPLICATES=1')
        cmd.append(AUTO_CONF_PATH)
        # pylint: disable=R1732
        self.proc = subprocess.Popen(cmd, stdout=self.devnull, env=env,
                                     stderr=subprocess.PIPE,
                                     cwd=self.current_src_dir)
        self.state = STATE_AUTOCONF

    def do_build_db(self):
        """Add the board to the database"""
        configs = {}
        for line in read_file(os.path.join(self.build_dir, AUTO_CONF_PATH)):
            if line.startswith('CONFIG'):
                config, value = line.split('=', 1)
                configs[config] = value.rstrip()
        self.db_queue.put([self.defconfig, configs])
        self.finish(True)

    def do_savedefconfig(self):
        """Update the .config and run 'make savedefconfig'."""
        if not self.args.force_sync:
            self.finish(True)
            return

        cmd = list(self.make_cmd)
        cmd.append('savedefconfig')
        # pylint: disable=R1732
        self.proc = subprocess.Popen(cmd, stdout=self.devnull,
                                     stderr=subprocess.PIPE)
        self.state = STATE_SAVEDEFCONFIG

    def update_defconfig(self):
        """Update the input defconfig and go back to the idle state."""
        orig_defconfig = os.path.join('configs', self.defconfig)
        new_defconfig = os.path.join(self.build_dir, 'defconfig')
        updated = not filecmp.cmp(orig_defconfig, new_defconfig)

        if updated:
            self.log.append(
                self.col.build(self.col.BLUE, 'defconfig updated', bright=True))

        if not self.args.dry_run and updated:
            shutil.move(new_defconfig, orig_defconfig)
        self.finish(True)

    def finish(self, success):
        """Display log along with progress and go to the idle state.

        Args:
          success (bool): Should be True when the defconfig was processed
                   successfully, or False when it fails.
        """
        # output at least 30 characters to hide the "* defconfigs out of *".
        name = self.defconfig[:-len('_defconfig')]
        if self.log:

            # Put the first log line on the first line
            log = name.ljust(20) + ' ' + self.log[0]

            if len(self.log) > 1:
                log += '\n' + '\n'.join(['    ' + s for s in self.log[1:]])
            # Some threads are running in parallel.
            # Print log atomically to not mix up logs from different threads.
            print(log, file=(sys.stdout if success else sys.stderr))

        if not success:
            if self.args.exit_on_error:
                sys.exit('Exit on error.')
            # If --exit-on-error flag is not set, skip this board and continue.
            # Record the failed board.
            self.failed_boards.add(name)

        self.progress.inc(success)
        self.progress.show()
        self.state = STATE_IDLE

    def get_failed_boards(self):
        """Returns a set of failed boards (defconfigs) in this slot.
        """
        return self.failed_boards

class Slots:
    """Controller of the array of subprocess slots."""

    def __init__(self, toolchains, args, progress, reference_src_dir, db_queue):
        """Create a new slots controller.

        Args:
            toolchains (Toolchains): Toolchains object containing toolchains
            args (Namespace): Program arguments
            progress (Progress): A progress indicator.
            reference_src_dir (str): Determine the true starting config state
                from this source tree (None for none)
            db_queue (Queue): output queue to write config info for the database
        """
        self.args = args
        self.slots = []
        self.progress = progress
        self.col = progress.col
        devnull = subprocess.DEVNULL
        make_cmd = get_make_cmd()
        for _ in range(args.jobs):
            self.slots.append(Slot(toolchains, args, progress, devnull,
                                   make_cmd, reference_src_dir, db_queue))

    def add(self, defconfig):
        """Add a new subprocess if a vacant slot is found.

        Args:
          defconfig (str): defconfig name to be put into.

        Returns:
          Return True on success or False on failure
        """
        for slot in self.slots:
            if slot.add(defconfig):
                return True
        return False

    def available(self):
        """Check if there is a vacant slot.

        Returns:
          Return True if at lease one vacant slot is found, False otherwise.
        """
        for slot in self.slots:
            if slot.poll():
                return True
        return False

    def empty(self):
        """Check if all slots are vacant.

        Returns:
          Return True if all the slots are vacant, False otherwise.
        """
        ret = True
        for slot in self.slots:
            if not slot.poll():
                ret = False
        return ret

    def write_failed_boards(self):
        """Show the results of processing"""
        boards = set()

        for slot in self.slots:
            boards |= slot.get_failed_boards()

        if boards:
            boards = '\n'.join(sorted(boards)) + '\n'
            write_file(FAILED_LIST, boards)


class ReferenceSource:

    """Reference source against which original configs should be parsed."""

    def __init__(self, commit):
        """Create a reference source directory based on a specified commit.

        Args:
          commit: commit to git-clone
        """
        self.src_dir = tempfile.mkdtemp()
        print('Cloning git repo to a separate work directory...')
        subprocess.check_output(['git', 'clone', os.getcwd(), '.'],
                                cwd=self.src_dir)
        rev = subprocess.check_output(['git', 'rev-parse', '--short',
                                       commit]).strip()
        print(f"Checkout '{rev}' to build the original autoconf.mk.")
        subprocess.check_output(['git', 'checkout', commit],
                                stderr=subprocess.STDOUT, cwd=self.src_dir)

    def __del__(self):
        """Delete the reference source directory

        This function makes sure the temporary directory is cleaned away
        even if Python suddenly dies due to error.  It should be done in here
        because it is guaranteed the destructor is always invoked when the
        instance of the class gets unreferenced.
        """
        shutil.rmtree(self.src_dir)

    def get_dir(self):
        """Return the absolute path to the reference source directory."""

        return self.src_dir

def move_config(args):
    """Build database or sync config options to defconfig files.

    Args:
        args (Namespace): Program arguments

    Returns:
        tuple:
            config_db (dict of configs for each defconfig):
                key: defconfig name, e.g. "MPC8548CDS_legacy_defconfig"
                value: dict:
                    key: CONFIG option
                    value: Value of option
            Progress: Progress indicator
    """
    config_db = {}
    db_queue = queue.Queue()
    dbt = DatabaseThread(config_db, db_queue)
    dbt.daemon = True
    dbt.start()

    check_clean_directory()
    bsettings.setup('')

    # Get toolchains to use
    toolchains = toolchain.Toolchains()
    toolchains.GetSettings()
    toolchains.Scan(verbose=False)

    if args.git_ref:
        reference_src = ReferenceSource(args.git_ref)
        reference_src_dir = reference_src.get_dir()
    else:
        reference_src_dir = None

    if args.defconfigs:
        defconfigs = get_matched_defconfigs(args.defconfigs)
    else:
        defconfigs = get_all_defconfigs()

    col = terminal.Color(terminal.COLOR_NEVER if args.nocolour
                         else terminal.COLOR_IF_TERMINAL)
    progress = Progress(col, len(defconfigs))
    slots = Slots(toolchains, args, progress, reference_src_dir, db_queue)

    # Main loop to process defconfig files:
    #  Add a new subprocess into a vacant slot.
    #  Sleep if there is no available slot.
    for defconfig in defconfigs:
        while not slots.add(defconfig):
            while not slots.available():
                # No available slot: sleep for a while
                time.sleep(SLEEP_TIME)

    # wait until all the subprocesses finish
    while not slots.empty():
        time.sleep(SLEEP_TIME)

    slots.write_failed_boards()
    db_queue.join()
    progress.completed()
    return config_db, progress

def find_kconfig_rules(kconf, config, imply_config):
    """Check whether a config has a 'select' or 'imply' keyword

    Args:
        kconf (Kconfiglib.Kconfig): Kconfig object
        config (str): Name of config to check (without CONFIG_ prefix)
        imply_config (str): Implying config (without CONFIG_ prefix) which may
            or may not have an 'imply' for 'config')

    Returns:
        Symbol object for 'config' if found, else None
    """
    sym = kconf.syms.get(imply_config)
    if sym:
        for sel, _ in (sym.selects + sym.implies):
            if sel.name == config:
                return sym
    return None

def check_imply_rule(kconf, imply_config):
    """Check if we can add an 'imply' option

    This finds imply_config in the Kconfig and looks to see if it is possible
    to add an 'imply' for 'config' to that part of the Kconfig.

    Args:
        kconf (Kconfiglib.Kconfig): Kconfig object
        imply_config (str): Implying config (without CONFIG_ prefix) which may
            or may not have an 'imply' for 'config')

    Returns:
        tuple:
            str: filename of Kconfig file containing imply_config, or None if
                none
            int: line number within the Kconfig file, or 0 if none
            str: message indicating the result
    """
    sym = kconf.syms.get(imply_config)
    if not sym:
        return 'cannot find sym'
    nodes = sym.nodes
    if len(nodes) != 1:
        return f'{len(nodes)} locations'
    node = nodes[0]
    fname, linenum = node.filename, node.linenr
    cwd = os.getcwd()
    if cwd and fname.startswith(cwd):
        fname = fname[len(cwd) + 1:]
    file_line = f' at {fname}:{linenum}'
    data = read_file(fname)
    if data[linenum - 1] != f'config {imply_config}':
        return None, 0, f'bad sym format {data[linenum]}{file_line})'
    return fname, linenum, f'adding{file_line}'

def add_imply_rule(config, fname, linenum):
    """Add a new 'imply' option to a Kconfig

    Args:
        config (str): config option to add an imply for (without CONFIG_ prefix)
        fname (str): Kconfig filename to update
        linenum (int): Line number to place the 'imply' before

    Returns:
        Message indicating the result
    """
    file_line = f' at {fname}:{linenum}'
    data = read_file(fname)
    linenum -= 1

    for offset, line in enumerate(data[linenum:]):
        if line.strip().startswith('help') or not line:
            data.insert(linenum + offset, f'\timply {config}')
            write_file(fname, data)
            return f'added{file_line}'

    return 'could not insert%s'

(IMPLY_MIN_2, IMPLY_TARGET, IMPLY_CMD, IMPLY_NON_ARCH_BOARD) = (
    1, 2, 4, 8)

IMPLY_FLAGS = {
    'min2': [IMPLY_MIN_2, 'Show options which imply >2 boards (normally >5)'],
    'target': [IMPLY_TARGET, 'Allow CONFIG_TARGET_... options to imply'],
    'cmd': [IMPLY_CMD, 'Allow CONFIG_CMD_... to imply'],
    'non-arch-board': [
        IMPLY_NON_ARCH_BOARD,
        'Allow Kconfig options outside arch/ and /board/ to imply'],
}


def read_database():
    """Read in the config database

    Returns:
        tuple:
            set of all config options seen (each a str)
            set of all defconfigs seen (each a str)
            dict of configs for each defconfig:
                key: defconfig name, e.g. "MPC8548CDS_legacy_defconfig"
                value: dict:
                    key: CONFIG option
                    value: Value of option
            dict of defconfigs for each config:
                key: CONFIG option
                value: set of boards using that option

    """
    configs = {}

    # key is defconfig name, value is dict of (CONFIG_xxx, value)
    config_db = {}

    # Set of all config options we have seen
    all_configs = set()

    # Set of all defconfigs we have seen
    all_defconfigs = set()

    defconfig_db = collections.defaultdict(set)
    defconfig = None
    for line in read_file(CONFIG_DATABASE):
        line = line.rstrip()
        if not line:  # Separator between defconfigs
            config_db[defconfig] = configs
            all_defconfigs.add(defconfig)
            configs = {}
        elif line[0] == ' ':  # CONFIG line
            config, value = line.strip().split('=', 1)
            configs[config] = value
            defconfig_db[config].add(defconfig)
            all_configs.add(config)
        else:  # New defconfig
            defconfig = line

    return all_configs, all_defconfigs, config_db, defconfig_db


def do_imply_config(config_list, add_imply, imply_flags, skip_added,
                    check_kconfig=True, find_superset=False):
    """Find CONFIG options which imply those in the list

    Some CONFIG options can be implied by others and this can help to reduce
    the size of the defconfig files. For example, CONFIG_X86 implies
    CONFIG_CMD_IRQ, so we can put 'imply CMD_IRQ' under 'config X86' and
    all x86 boards will have that option, avoiding adding CONFIG_CMD_IRQ to
    each of the x86 defconfig files.

    This function uses the qconfig database to find such options. It
    displays a list of things that could possibly imply those in the list.
    The algorithm ignores any that start with CONFIG_TARGET since these
    typically refer to only a few defconfigs (often one). It also does not
    display a config with less than 5 defconfigs.

    The algorithm works using sets. For each target config in config_list:
        - Get the set 'defconfigs' which use that target config
        - For each config (from a list of all configs):
            - Get the set 'imply_defconfig' of defconfigs which use that config
            -
            - If imply_defconfigs contains anything not in defconfigs then
              this config does not imply the target config

    Args:
        config_list (list of str): List of CONFIG options to check
        add_imply (bool): Automatically add an 'imply' for each config.
        imply_flags (int): Flags which control which implying configs are allowed
           (IMPLY_...)
        skip_added (bool): Don't show options which already have an imply added.
        check_kconfig (bool): Check if implied symbols already have an 'imply' or
            'select' for the target config, and show this information if so.
        find_superset (bool): True to look for configs which are a superset of those
            already found. So for example if CONFIG_EXYNOS5 implies an option,
            but CONFIG_EXYNOS covers a larger set of defconfigs and also
            implies that option, this will drop the former in favour of the
            latter. In practice this option has not proved very used.

    Note the terminoloy:
        config - a CONFIG_XXX options (a string, e.g. 'CONFIG_CMD_EEPROM')
        defconfig - a defconfig file (a string, e.g. 'configs/snow_defconfig')
    """
    kconf = scan_kconfig() if check_kconfig else None
    if add_imply and add_imply != 'all':
        add_imply = add_imply.split(',')

    all_configs, all_defconfigs, _, defconfig_db = read_database()

    # Work through each target config option in turn, independently
    for config in config_list:
        defconfigs = defconfig_db.get(config)
        if not defconfigs:
            print(f'{config} not found in any defconfig')
            continue

        # Get the set of defconfigs without this one (since a config cannot
        # imply itself)
        non_defconfigs = all_defconfigs - defconfigs
        num_defconfigs = len(defconfigs)
        print(f'{config} found in {num_defconfigs}/{len(all_configs)} defconfigs')

        # This will hold the results: key=config, value=defconfigs containing it
        imply_configs = {}
        rest_configs = all_configs - set([config])

        # Look at every possible config, except the target one
        for imply_config in rest_configs:
            if 'ERRATUM' in imply_config:
                continue
            if not imply_flags & IMPLY_CMD:
                if 'CONFIG_CMD' in imply_config:
                    continue
            if not imply_flags & IMPLY_TARGET:
                if 'CONFIG_TARGET' in imply_config:
                    continue

            # Find set of defconfigs that have this config
            imply_defconfig = defconfig_db[imply_config]

            # Get the intersection of this with defconfigs containing the
            # target config
            common_defconfigs = imply_defconfig & defconfigs

            # Get the set of defconfigs containing this config which DO NOT
            # also contain the taret config. If this set is non-empty it means
            # that this config affects other defconfigs as well as (possibly)
            # the ones affected by the target config. This means it implies
            # things we don't want to imply.
            not_common_defconfigs = imply_defconfig & non_defconfigs
            if not_common_defconfigs:
                continue

            # If there are common defconfigs, imply_config may be useful
            if common_defconfigs:
                skip = False
                if find_superset:
                    for prev in list(imply_configs.keys()):
                        prev_count = len(imply_configs[prev])
                        count = len(common_defconfigs)
                        if (prev_count > count and
                            (imply_configs[prev] & common_defconfigs ==
                            common_defconfigs)):
                            # skip imply_config because prev is a superset
                            skip = True
                            break
                        if count > prev_count:
                            # delete prev because imply_config is a superset
                            del imply_configs[prev]
                if not skip:
                    imply_configs[imply_config] = common_defconfigs

        # Now we have a dict imply_configs of configs which imply each config
        # The value of each dict item is the set of defconfigs containing that
        # config. Rank them so that we print the configs that imply the largest
        # number of defconfigs first.
        ranked_iconfigs = sorted(imply_configs,
                            key=lambda k: len(imply_configs[k]), reverse=True)
        kconfig_info = ''
        cwd = os.getcwd()
        add_list = collections.defaultdict(list)
        for iconfig in ranked_iconfigs:
            num_common = len(imply_configs[iconfig])

            # Don't bother if there are less than 5 defconfigs affected.
            if num_common < (2 if imply_flags & IMPLY_MIN_2 else 5):
                continue
            missing = defconfigs - imply_configs[iconfig]
            missing_str = ', '.join(missing) if missing else 'all'
            missing_str = ''
            show = True
            if kconf:
                sym = find_kconfig_rules(kconf, config[CONFIG_LEN:],
                                         iconfig[CONFIG_LEN:])
                kconfig_info = ''
                if sym:
                    nodes = sym.nodes
                    if len(nodes) == 1:
                        fname, linenum = nodes[0].filename, nodes[0].linenr
                        if cwd and fname.startswith(cwd):
                            fname = fname[len(cwd) + 1:]
                        kconfig_info = f'{fname}:{linenum}'
                        if skip_added:
                            show = False
                else:
                    sym = kconf.syms.get(iconfig[CONFIG_LEN:])
                    fname = ''
                    if sym:
                        nodes = sym.nodes
                        if len(nodes) == 1:
                            fname, linenum = nodes[0].filename, nodes[0].linenr
                            if cwd and fname.startswith(cwd):
                                fname = fname[len(cwd) + 1:]
                    in_arch_board = not sym or (fname.startswith('arch') or
                                                fname.startswith('board'))
                    if (not in_arch_board and
                        not imply_flags & IMPLY_NON_ARCH_BOARD):
                        continue

                    if add_imply and (add_imply == 'all' or
                                      iconfig in add_imply):
                        fname, linenum, kconfig_info = (check_imply_rule(kconf,
                                iconfig[CONFIG_LEN:]))
                        if fname:
                            add_list[fname].append(linenum)

            if show and kconfig_info != 'skip':
                print(f'{num_common:5} : '
                      f'{iconfig.ljust(30)}{kconfig_info.ljust(25)} {missing_str}')

        # Having collected a list of things to add, now we add them. We process
        # each file from the largest line number to the smallest so that
        # earlier additions do not affect our line numbers. E.g. if we added an
        # imply at line 20 it would change the position of each line after
        # that.
        for fname, linenums in add_list.items():
            for linenum in sorted(linenums, reverse=True):
                add_imply_rule(config[CONFIG_LEN:], fname, linenum)

def defconfig_matches(configs, re_match, re_val):
    """Check if any CONFIG option matches a regex

    The match must be complete, i.e. from the start to end of the CONFIG option.

    Args:
        configs (dict): Dict of CONFIG options:
            key: CONFIG option
            value: Value of option
        re_match (re.Pattern): Match to check
        re_val (re.Pattern): Regular expression to check against value (or None)

    Returns:
        bool: True if any CONFIG matches the regex
    """
    for cfg, val in configs.items():
        if re_match.fullmatch(cfg):
            if not re_val or re_val.fullmatch(val):
                return True
    return False

def do_find_config(config_list, list_format):
    """Find boards with a given combination of CONFIGs

    Args:
        config_list (list of str): List of CONFIG options to check (each a regex
            consisting of a config option, with or without a CONFIG_ prefix. If
            an option is preceded by a tilde (~) then it must be false,
            otherwise it must be true)
        list_format (bool): True to write in 'list' format, one board name per
            line

    Returns:
        int: exit code (0 for success)
    """
    _, all_defconfigs, config_db, _ = read_database()

    # Start with all defconfigs
    out = all_defconfigs

    # Work through each config in turn
    for item in config_list:
        # Get the real config name and whether we want this config or not
        cfg = item
        want = True
        if cfg[0] == '~':
            want = False
            cfg = cfg[1:]
        val = None
        re_val = None
        if '=' in cfg:
            cfg, val = cfg.split('=', maxsplit=1)
            re_val = re.compile(val)

        # Search everything that is still in the running. If it has a config
        # that we want, or doesn't have one that we don't, add it into the
        # running for the next stage
        in_list = out
        out = set()
        re_match = re.compile(cfg)
        for defc in in_list:
            has_cfg = defconfig_matches(config_db[defc], re_match, re_val)
            if has_cfg == want:
                out.add(defc)
    if not list_format:
        print(f'{len(out)} matches')
    sep = '\n' if list_format else ' '
    print(sep.join(item.split('_defconfig')[0] for item in sorted(list(out))))
    return 0


def prefix_config(cfg):
    """Prefix a config with CONFIG_ if needed

    This handles ~ operator, which indicates that the CONFIG should be disabled

    >>> prefix_config('FRED')
    'CONFIG_FRED'
    >>> prefix_config('CONFIG_FRED')
    'CONFIG_FRED'
    >>> prefix_config('~FRED')
    '~CONFIG_FRED'
    >>> prefix_config('~CONFIG_FRED')
    '~CONFIG_FRED'
    >>> prefix_config('A123')
    'CONFIG_A123'
    """
    oper = ''
    if cfg[0] == '~':
        oper = cfg[0]
        cfg = cfg[1:]
    if not cfg.startswith('CONFIG_'):
        cfg = 'CONFIG_' + cfg
    return oper + cfg


RE_MK_CONFIGS = re.compile(r'CONFIG_(\$\(PHASE_\))?([A-Za-z0-9_]*)')
RE_IFDEF = re.compile(r'(ifdef|ifndef)')
RE_C_CONFIGS = re.compile(r'CONFIG_([A-Za-z0-9_]*)')
RE_CONFIG_IS = re.compile(r'CONFIG_IS_ENABLED\(([A-Za-z0-9_]*)\)')

class ConfigUse:
    """Tracks whether a config relates to SPL or not"""
    def __init__(self, cfg, is_spl, fname, rest):
        """Set up a new ConfigUse

        Args:
            cfg (str): CONFIG option, without any CONFIG_ or xPL_ prefix
            is_spl (bool): True if this option relates to SPL
            fname (str): Makefile filename where the CONFIG option was found
            rest (str): Line of the Makefile
        """
        self.cfg = cfg
        self.is_spl = is_spl
        self.fname = fname
        self.rest = rest

    def __hash__(self):
        return hash((self.cfg, self.is_spl))

def scan_makefiles(fnames):
    """Scan Makefiles looking for Kconfig options

    Looks for uses of CONFIG options in Makefiles

    Args:
        fnames (list of tuple):
            str: Makefile filename where the option was found
            str: Line of the Makefile

    Returns:
        tuple:
            dict: all_uses
                key (ConfigUse): object
                value (list of str): matching lines
            dict: Uses by filename
                key (str): filename
                value (set of ConfigUse): uses in that filename

    >>> RE_MK_CONFIGS.search('CONFIG_FRED').groups()
    (None, 'FRED')
    >>> RE_MK_CONFIGS.search('CONFIG_$(PHASE_)MARY').groups()
    ('$(PHASE_)', 'MARY')
    """
    all_uses = collections.defaultdict(list)
    fname_uses = {}
    for fname, rest in fnames:
        m_iter = RE_MK_CONFIGS.finditer(rest)
        for mat in m_iter:
            real_opt = mat.group(2)
            if real_opt == '':
                continue
            is_spl = False
            if mat.group(1):
                is_spl = True
            use = ConfigUse(real_opt, is_spl, fname, rest)
            if fname not in fname_uses:
                fname_uses[fname] = set()
            fname_uses[fname].add(use)
            all_uses[use].append(rest)
    return all_uses, fname_uses


def scan_src_files(fnames):
    """Scan source files (other than Makefiles) looking for Kconfig options

    Looks for uses of CONFIG options

    Args:
        fnames (list of tuple):
            str: Makefile filename where the option was found
            str: Line of the Makefile

    Returns:
        tuple:
            dict: all_uses
                key (ConfigUse): object
                value (list of str): matching lines
            dict: Uses by filename
                key (str): filename
                value (set of ConfigUse): uses in that filename

    >>> RE_C_CONFIGS.search('CONFIG_FRED').groups()
    ('FRED',)
    >>> RE_CONFIG_IS.search('CONFIG_IS_ENABLED(MARY)').groups()
    ('MARY',)
    >>> RE_CONFIG_IS.search('#if CONFIG_IS_ENABLED(OF_PLATDATA)').groups()
    ('OF_PLATDATA',)
    """
    fname = None
    rest = None

    def add_uses(m_iter, is_spl):
        for mat in m_iter:
            real_opt = mat.group(1)
            if real_opt == '':
                continue
            use = ConfigUse(real_opt, is_spl, fname, rest)
            if fname not in fname_uses:
                fname_uses[fname] = set()
            fname_uses[fname].add(use)
            all_uses[use].append(rest)

    all_uses = collections.defaultdict(list)
    fname_uses = {}
    for fname, rest in fnames:
        m_iter = RE_C_CONFIGS.finditer(rest)
        add_uses(m_iter, False)

        m_iter2 = RE_CONFIG_IS.finditer(rest)
        add_uses(m_iter2, True)

    return all_uses, fname_uses


MODE_NORMAL, MODE_SPL, MODE_PROPER = range(3)

def do_scan_source(path, do_update):
    """Scan the source tree for Kconfig inconsistencies

    Args:
        path (str): Path to source tree
        do_update (bool) : True to write to scripts/kconf_... files
    """
    def is_not_proper(name):
        for prefix in SPL_PREFIXES:
            if name.startswith(prefix):
                return name[len(prefix):]
        return False

    def check_not_found(all_uses, spl_mode):
        """Check for Kconfig options mentioned in the source but not in Kconfig

        Args:
            all_uses (dict):
                key (ConfigUse): object
                value (list of str): matching lines
            spl_mode (int): If MODE_SPL, look at source code which implies
                an xPL_ option, but for which there is none;
                for MOD_PROPER, look at source code which implies a Proper
                option (i.e. use of CONFIG_IS_ENABLED() or $(PHASE_) but for
                which there none;
                if MODE_NORMAL, ignore SPL

        Returns:
            dict:
                key (str): CONFIG name (without 'CONFIG_' prefix
                value (list of ConfigUse): List of uses of this CONFIG
        """
        # Make sure we know about all the options
        not_found = collections.defaultdict(list)
        for use, _ in all_uses.items():
            name = use.cfg
            if name in IGNORE_SYMS:
                continue
            check = True

            if spl_mode == MODE_SPL:
                check = use.is_spl

                # If it is an SPL symbol, try prepending all xPL_ prefixes to
                # find at least one SPL symbol
                if use.is_spl:
                    for prefix in SPL_PREFIXES:
                        try_name = prefix + name
                        sym = kconf.syms.get(try_name)
                        if sym:
                            break
                    if not sym:
                        not_found[f'SPL_{name}'].append(use)
                    continue
            elif spl_mode == MODE_PROPER:
                # Try to find the Proper version of this symbol, i.e. without
                # the xPL_ prefix
                proper_name = is_not_proper(name)
                if proper_name:
                    name = proper_name
                elif not use.is_spl:
                    check = False
            else: # MODE_NORMAL
                sym = kconf.syms.get(name)
                if not sym:
                    proper_name = is_not_proper(name)
                    if proper_name:
                        name = proper_name
                    sym = kconf.syms.get(name)
                if not sym:
                    for prefix in SPL_PREFIXES:
                        try_name = prefix + name
                        sym = kconf.syms.get(try_name)
                        if sym:
                            break
                if not sym:
                    not_found[name].append(use)
                continue

            sym = kconf.syms.get(name)
            if not sym and check:
                not_found[name].append(use)
        return not_found

    def show_uses(uses):
        """Show a list of uses along with their filename and code snippet

        Args:
            uses (dict):
                key (str): CONFIG name (without 'CONFIG_' prefix
                value (list of ConfigUse): List of uses of this CONFIG
        """
        for name in sorted(uses):
            print(f'{name}: ', end='')
            for i, use in enumerate(uses[name]):
                print(f'{"   " if i else ""}{use.fname}: {use.rest.strip()}')


    print('Scanning Kconfig')
    kconf = scan_kconfig()
    print(f'Scanning source in {path}')
    args = ['git', 'grep', '-E', r'IS_ENABLED|\bCONFIG']
    with subprocess.Popen(args, stdout=subprocess.PIPE) as proc:
        out, _ = proc.communicate()
    lines = out.splitlines()
    re_fname = re.compile('^([^:]*):(.*)')
    src_list = []
    mk_list = []
    for line in lines:
        linestr = line.decode('utf-8')
        m_fname = re_fname.search(linestr)
        if not m_fname:
            continue
        fname, rest = m_fname.groups()
        dirname, leaf = os.path.split(fname)
        root, ext = os.path.splitext(leaf)
        if ext == '.autoconf':
            pass
        elif ext in ['.c', '.h', '.S', '.lds', '.dts', '.dtsi', '.asl', '.cfg',
                     '.env', '.tmpl']:
            src_list.append([fname, rest])
        elif 'Makefile' in root or ext == '.mk':
            mk_list.append([fname, rest])
        elif ext in ['.yml', '.sh', '.py', '.awk', '.pl', '.rst', '', '.sed']:
            pass
        elif 'Kconfig' in root or 'Kbuild' in root:
            pass
        elif 'README' in root:
            pass
        elif dirname in ['configs']:
            pass
        elif dirname.startswith('doc') or dirname.startswith('scripts/kconfig'):
            pass
        else:
            print(f'Not sure how to handle file {fname}')

    # Scan the Makefiles
    all_uses, _ = scan_makefiles(mk_list)

    spl_not_found = set()
    proper_not_found = set()

    # Make sure we know about all the options
    print('\nCONFIG options present in Makefiles but not Kconfig:')
    not_found = check_not_found(all_uses, MODE_NORMAL)
    show_uses(not_found)

    print('\nCONFIG options present in Makefiles but not Kconfig (SPL):')
    not_found = check_not_found(all_uses, MODE_SPL)
    show_uses(not_found)
    spl_not_found |= {is_not_proper(key) or key for key in not_found.keys()}

    print('\nCONFIG options used as Proper in Makefiles but without a non-xPL_ variant:')
    not_found = check_not_found(all_uses, MODE_PROPER)
    show_uses(not_found)
    proper_not_found |= not_found.keys()

    # Scan the source code
    all_uses, _ = scan_src_files(src_list)

    # Make sure we know about all the options
    print('\nCONFIG options present in source but not Kconfig:')
    not_found = check_not_found(all_uses, MODE_NORMAL)
    show_uses(not_found)

    print('\nCONFIG options present in source but not Kconfig (SPL):')
    not_found = check_not_found(all_uses, MODE_SPL)
    show_uses(not_found)
    spl_not_found |= {is_not_proper(key) or key for key in not_found.keys()}

    print('\nCONFIG options used as Proper in source but without a non-xPL_ variant:')
    not_found = check_not_found(all_uses, MODE_PROPER)
    show_uses(not_found)
    proper_not_found |= not_found.keys()

    print('\nCONFIG options used as SPL but without an xPL_ variant:')
    for item in sorted(spl_not_found):
        print(f'   {item}')

    print('\nCONFIG options used as Proper but without a non-xPL_ variant:')
    for item in sorted(proper_not_found):
        print(f'   {item}')

    # Write out the updated information
    if do_update:
        with open(os.path.join(path, 'scripts', 'conf_nospl'), 'w',
                  encoding='utf-8') as out:
            print('# These options should not be enabled in SPL builds\n',
                  file=out)
            for item in sorted(spl_not_found):
                print(item, file=out)
        with open(os.path.join(path, 'scripts', 'conf_noproper'), 'w',
                  encoding='utf-8') as out:
            print('# These options should not be enabled in Proper builds\n',
                  file=out)
            for item in sorted(proper_not_found):
                print(item, file=out)
    return 0


def parse_args():
    """Parse the program arguments

    Returns:
        tuple:
            argparse.ArgumentParser: parser
            argparse.Namespace: Parsed arguments
    """
    try:
        cpu_count = multiprocessing.cpu_count()
    except NotImplementedError:
        cpu_count = 1

    epilog = '''Move config options from headers to defconfig files. See
doc/develop/moveconfig.rst for documentation.'''

    parser = ArgumentParser(epilog=epilog)
    # Add arguments here
    parser.add_argument('-a', '--add-imply', type=str, default='',
                      help='comma-separated list of CONFIG options to add '
                      "an 'imply' statement to for the CONFIG in -i")
    parser.add_argument('-A', '--skip-added', action='store_true', default=False,
                      help="don't show options which are already marked as "
                      'implying others')
    parser.add_argument('-b', '--build-db', action='store_true', default=False,
                      help='build a CONFIG database')
    parser.add_argument('-C', '--commit', action='store_true', default=False,
                      help='Create a git commit for the operation')
    parser.add_argument('--nocolour', action='store_true', default=False,
                      help="don't display the log in colour")
    parser.add_argument('-d', '--defconfigs', type=str,
                      help='a file containing a list of defconfigs to move, '
                      "one per line (for example 'snow_defconfig') "
                      "or '-' to read from stdin")
    parser.add_argument('-e', '--exit-on-error', action='store_true',
                      default=False,
                      help='exit immediately on any error')
    parser.add_argument('-f', '--find', action='store_true', default=False,
                      help='Find boards with a given config combination')
    parser.add_argument('-i', '--imply', action='store_true', default=False,
                      help='find options which imply others')
    parser.add_argument('-l', '--list', action='store_true', default=False,
                      help='Show a sorted list of board names, one per line')
    parser.add_argument('-I', '--imply-flags', type=str, default='',
                      help="control the -i option ('help' for help")
    parser.add_argument('-j', '--jobs', type=int, default=cpu_count,
                      help='the number of jobs to run simultaneously')
    parser.add_argument('-n', '--dry-run', action='store_true', default=False,
                      help='perform a trial run (show log with no changes)')
    parser.add_argument('-r', '--git-ref', type=str,
                      help='the git ref to clone for building the autoconf.mk')
    parser.add_argument('-s', '--force-sync', action='store_true', default=False,
                      help='force sync by savedefconfig')
    parser.add_argument('-S', '--spl', action='store_true', default=False,
                      help='parse config options defined for SPL build')
    parser.add_argument('--scan-source', action='store_true', default=False,
                      help='scan source for uses of CONFIG options')
    parser.add_argument('-t', '--test', action='store_true', default=False,
                      help='run unit tests')
    parser.add_argument('-y', '--yes', action='store_true', default=False,
                      help="respond 'yes' to any prompts")
    parser.add_argument('-u', '--update', action='store_true', default=False,
                      help="update scripts/ files (use with --scan-source)")
    parser.add_argument('-v', '--verbose', action='store_true', default=False,
                      help='show any build errors as boards are built')
    parser.add_argument('configs', nargs='*')

    args = parser.parse_args()
    if not any((args.force_sync, args.build_db, args.imply, args.find,
                args.scan_source, args.test)):
        parser.print_usage()
        sys.exit(1)

    return parser, args


def imply(args):
    """Handle checking for flags which imply others

    Args:
        args (argparse.Namespace): Program arguments

    Returns:
        int: exit code (0 for success)
    """
    imply_flags = 0
    if args.imply_flags == 'all':
        imply_flags = -1

    elif args.imply_flags:
        for flag in args.imply_flags.split(','):
            bad = flag not in IMPLY_FLAGS
            if bad:
                print(f"Invalid flag '{flag}'")
            if flag == 'help' or bad:
                print("Imply flags: (separate with ',')")
                for name, info in IMPLY_FLAGS.items():
                    print(f' {name.ljust(15)}: {info[1]}')
                return 1
            imply_flags |= IMPLY_FLAGS[flag][0]

    do_imply_config(args.configs, args.add_imply, imply_flags, args.skip_added)
    return 0


def add_commit(configs):
    """Add a commit indicating which CONFIG options were converted

    Args:
        configs (list of str) List of CONFIG_... options to process
    """
    subprocess.call(['git', 'add', '-u'])
    if configs:
        part = 'et al ' if len(configs) > 1 else ''
        msg = f'Convert {configs[0]} {part}to Kconfig'
        msg += ('\n\nThis converts the following to Kconfig:\n   %s\n' %
                '\n   '.join(configs))
    else:
        msg = 'configs: Resync with savedefconfig'
        msg += '\n\nResync all defconfig files using qconfig.py'
    subprocess.call(['git', 'commit', '-s', '-m', msg])


def write_db(config_db, progress):
    """Write the database to a file

    Args:
        config_db (dict of dict): configs for each defconfig
            key: defconfig name, e.g. "MPC8548CDS_legacy_defconfig"
            value: dict:
                key: CONFIG option
                value: Value of option
        progress (Progress): Progress indicator.

    Returns:
        int: exit code (0 for success)
    """
    col = progress.col
    with open(CONFIG_DATABASE, 'w', encoding='utf-8') as outf:
        for defconfig, configs in config_db.items():
            outf.write(f'{defconfig}\n')
            for config in sorted(configs.keys()):
                outf.write(f'   {config}={configs[config]}\n')
            outf.write('\n')
    print(col.build(
        col.RED if progress.failed else col.GREEN,
        f'{progress.failure_msg}{len(config_db)} boards written to {CONFIG_DATABASE}'))
    return 0


def move_done(progress):
    """Write a message indicating that the move is done

    Args:
        progress (Progress): Progress indicator.

    Returns:
        int: exit code (0 for success)
    """
    col = progress.col
    if progress.failed:
        print(col.build(col.RED, f'{progress.failure_msg}see {FAILED_LIST}', True))
    else:
        # Add enough spaces to overwrite the progress indicator
        print(col.build(
            col.GREEN, f'{progress.total} processed        ', bright=True))
    return 0

def do_tests():
    """Run doctests and unit tests (so far there are no unit tests)"""
    sys.argv = [sys.argv[0]]
    fail, _ = doctest.testmod()
    if fail:
        return 1
    unittest.main()
    return 0


def main():
    """Main program"""
    parser, args = parse_args()
    check_top_directory()

    # prefix the option name with CONFIG_ if missing
    args.configs = [prefix_config(cfg) for cfg in args.configs]

    if args.test:
        return do_tests()
    if args.scan_source:
        return do_scan_source(os.getcwd(), args.update)
    if args.imply:
        if imply(args):
            parser.print_usage()
            sys.exit(1)
        return 0
    if args.find:
        return do_find_config(args.configs, args.list)

    config_db, progress = move_config(args)

    if args.commit:
        add_commit(args.configs)

    if args.build_db:
        return write_db(config_db, progress)
    return move_done(progress)


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