#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0+
#
# Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
#

"""
Converter from Kconfig and MAINTAINERS to a board database.

Run 'tools/genboardscfg.py' to create a board database.

Run 'tools/genboardscfg.py -h' for available options.

Python 2.6 or later, but not Python 3.x is necessary to run this script.
"""

import errno
import fnmatch
import glob
import multiprocessing
import optparse
import os
import sys
import tempfile
import time

sys.path.insert(1, os.path.join(os.path.dirname(__file__), 'buildman'))
import kconfiglib

### constant variables ###
OUTPUT_FILE = 'boards.cfg'
CONFIG_DIR = 'configs'
SLEEP_TIME = 0.03
COMMENT_BLOCK = '''#
# List of boards
#   Automatically generated by %s: don't edit
#
# Status, Arch, CPU, SoC, Vendor, Board, Target, Options, Maintainers

''' % __file__

### helper functions ###
def try_remove(f):
    """Remove a file ignoring 'No such file or directory' error."""
    try:
        os.remove(f)
    except OSError as exception:
        # Ignore 'No such file or directory' error
        if exception.errno != errno.ENOENT:
            raise

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

def output_is_new(output):
    """Check if the output file is up to date.

    Returns:
      True if the given output file exists and is newer than any of
      *_defconfig, MAINTAINERS and Kconfig*.  False otherwise.
    """
    try:
        ctime = os.path.getctime(output)
    except OSError as exception:
        if exception.errno == errno.ENOENT:
            # return False on 'No such file or directory' error
            return False
        else:
            raise

    for (dirpath, dirnames, filenames) in os.walk(CONFIG_DIR):
        for filename in fnmatch.filter(filenames, '*_defconfig'):
            if fnmatch.fnmatch(filename, '.*'):
                continue
            filepath = os.path.join(dirpath, filename)
            if ctime < os.path.getctime(filepath):
                return False

    for (dirpath, dirnames, filenames) in os.walk('.'):
        for filename in filenames:
            if (fnmatch.fnmatch(filename, '*~') or
                not fnmatch.fnmatch(filename, 'Kconfig*') and
                not filename == 'MAINTAINERS'):
                continue
            filepath = os.path.join(dirpath, filename)
            if ctime < os.path.getctime(filepath):
                return False

    # Detect a board that has been removed since the current board database
    # was generated
    with open(output, encoding="utf-8") as f:
        for line in f:
            if line[0] == '#' or line == '\n':
                continue
            defconfig = line.split()[6] + '_defconfig'
            if not os.path.exists(os.path.join(CONFIG_DIR, defconfig)):
                return False

    return True

### classes ###
class KconfigScanner:

    """Kconfig scanner."""

    ### constant variable only used in this class ###
    _SYMBOL_TABLE = {
        'arch' : 'SYS_ARCH',
        'cpu' : 'SYS_CPU',
        'soc' : 'SYS_SOC',
        'vendor' : 'SYS_VENDOR',
        'board' : 'SYS_BOARD',
        'config' : 'SYS_CONFIG_NAME',
        'options' : 'SYS_EXTRA_OPTIONS'
    }

    def __init__(self):
        """Scan all the Kconfig files and create a Kconfig object."""
        # Define environment variables referenced from Kconfig
        os.environ['srctree'] = os.getcwd()
        os.environ['UBOOTVERSION'] = 'dummy'
        os.environ['KCONFIG_OBJDIR'] = ''
        self._conf = kconfiglib.Kconfig(warn=False)

    def __del__(self):
        """Delete a leftover temporary file before exit.

        The scan() method of this class creates a temporay file and deletes
        it on success.  If scan() method throws an exception on the way,
        the temporary file might be left over.  In that case, it should be
        deleted in this destructor.
        """
        if hasattr(self, '_tmpfile') and self._tmpfile:
            try_remove(self._tmpfile)

    def scan(self, defconfig):
        """Load a defconfig file to obtain board parameters.

        Arguments:
          defconfig: path to the defconfig file to be processed

        Returns:
          A dictionary of board parameters.  It has a form of:
          {
              'arch': <arch_name>,
              'cpu': <cpu_name>,
              'soc': <soc_name>,
              'vendor': <vendor_name>,
              'board': <board_name>,
              'target': <target_name>,
              'config': <config_header_name>,
              'options': <extra_options>
          }
        """
        # strip special prefixes and save it in a temporary file
        fd, self._tmpfile = tempfile.mkstemp()
        with os.fdopen(fd, 'w') as f:
            for line in open(defconfig):
                colon = line.find(':CONFIG_')
                if colon == -1:
                    f.write(line)
                else:
                    f.write(line[colon + 1:])

        self._conf.load_config(self._tmpfile)
        try_remove(self._tmpfile)
        self._tmpfile = None

        params = {}

        # Get the value of CONFIG_SYS_ARCH, CONFIG_SYS_CPU, ... etc.
        # Set '-' if the value is empty.
        for key, symbol in list(self._SYMBOL_TABLE.items()):
            value = self._conf.syms.get(symbol).str_value
            if value:
                params[key] = value
            else:
                params[key] = '-'

        defconfig = os.path.basename(defconfig)
        params['target'], match, rear = defconfig.partition('_defconfig')
        assert match and not rear, '%s : invalid defconfig' % defconfig

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

        # fix-up options field. It should have the form:
        # <config name>[:comma separated config options]
        if params['options'] != '-':
            params['options'] = params['config'] + ':' + \
                                params['options'].replace(r'\"', '"')
        elif params['config'] != params['target']:
            params['options'] = params['config']

        return params

def scan_defconfigs_for_multiprocess(queue, defconfigs):
    """Scan defconfig files and queue their board parameters

    This function is intended to be passed to
    multiprocessing.Process() constructor.

    Arguments:
      queue: An instance of multiprocessing.Queue().
             The resulting board parameters are written into it.
      defconfigs: A sequence of defconfig files to be scanned.
    """
    kconf_scanner = KconfigScanner()
    for defconfig in defconfigs:
        queue.put(kconf_scanner.scan(defconfig))

def read_queues(queues, params_list):
    """Read the queues and append the data to the paramers list"""
    for q in queues:
        while not q.empty():
            params_list.append(q.get())

def scan_defconfigs(jobs=1):
    """Collect board parameters for all defconfig files.

    This function invokes multiple processes for faster processing.

    Arguments:
      jobs: The number of jobs to run simultaneously
    """
    all_defconfigs = []
    for (dirpath, dirnames, filenames) in os.walk(CONFIG_DIR):
        for filename in fnmatch.filter(filenames, '*_defconfig'):
            if fnmatch.fnmatch(filename, '.*'):
                continue
            all_defconfigs.append(os.path.join(dirpath, filename))

    total_boards = len(all_defconfigs)
    processes = []
    queues = []
    for i in range(jobs):
        defconfigs = all_defconfigs[total_boards * i // jobs :
                                    total_boards * (i + 1) // jobs]
        q = multiprocessing.Queue(maxsize=-1)
        p = multiprocessing.Process(target=scan_defconfigs_for_multiprocess,
                                    args=(q, defconfigs))
        p.start()
        processes.append(p)
        queues.append(q)

    # The resulting data should be accumulated to this list
    params_list = []

    # Data in the queues should be retrieved preriodically.
    # Otherwise, the queues would become full and subprocesses would get stuck.
    while any([p.is_alive() for p in processes]):
        read_queues(queues, params_list)
        # sleep for a while until the queues are filled
        time.sleep(SLEEP_TIME)

    # Joining subprocesses just in case
    # (All subprocesses should already have been finished)
    for p in processes:
        p.join()

    # retrieve leftover data
    read_queues(queues, params_list)

    return params_list

class MaintainersDatabase:

    """The database of board status and maintainers."""

    def __init__(self):
        """Create an empty database."""
        self.database = {}

    def get_status(self, target):
        """Return the status of the given board.

        The board status is generally either 'Active' or 'Orphan'.
        Display a warning message and return '-' if status information
        is not found.

        Returns:
          'Active', 'Orphan' or '-'.
        """
        if not target in self.database:
            print("WARNING: no status info for '%s'" % target, file=sys.stderr)
            return '-'

        tmp = self.database[target][0]
        if tmp.startswith('Maintained'):
            return 'Active'
        elif tmp.startswith('Supported'):
            return 'Active'
        elif tmp.startswith('Orphan'):
            return 'Orphan'
        else:
            print(("WARNING: %s: unknown status for '%s'" %
                                  (tmp, target)), file=sys.stderr)
            return '-'

    def get_maintainers(self, target):
        """Return the maintainers of the given board.

        Returns:
          Maintainers of the board.  If the board has two or more maintainers,
          they are separated with colons.
        """
        if not target in self.database:
            print("WARNING: no maintainers for '%s'" % target, file=sys.stderr)
            return ''

        return ':'.join(self.database[target][1])

    def parse_file(self, file):
        """Parse a MAINTAINERS file.

        Parse a MAINTAINERS file and accumulates board status and
        maintainers information.

        Arguments:
          file: MAINTAINERS file to be parsed
        """
        targets = []
        maintainers = []
        status = '-'
        for line in open(file, encoding="utf-8"):
            # Check also commented maintainers
            if line[:3] == '#M:':
                line = line[1:]
            tag, rest = line[:2], line[2:].strip()
            if tag == 'M:':
                maintainers.append(rest)
            elif tag == 'F:':
                # expand wildcard and filter by 'configs/*_defconfig'
                for f in glob.glob(rest):
                    front, match, rear = f.partition('configs/')
                    if not front and match:
                        front, match, rear = rear.rpartition('_defconfig')
                        if match and not rear:
                            targets.append(front)
            elif tag == 'S:':
                status = rest
            elif line == '\n':
                for target in targets:
                    self.database[target] = (status, maintainers)
                targets = []
                maintainers = []
                status = '-'
        if targets:
            for target in targets:
                self.database[target] = (status, maintainers)

def insert_maintainers_info(params_list):
    """Add Status and Maintainers information to the board parameters list.

    Arguments:
      params_list: A list of the board parameters
    """
    database = MaintainersDatabase()
    for (dirpath, dirnames, filenames) in os.walk('.'):
        if 'MAINTAINERS' in filenames:
            database.parse_file(os.path.join(dirpath, 'MAINTAINERS'))

    for i, params in enumerate(params_list):
        target = params['target']
        params['status'] = database.get_status(target)
        params['maintainers'] = database.get_maintainers(target)
        params_list[i] = params

def format_and_output(params_list, output):
    """Write board parameters into a file.

    Columnate the board parameters, sort lines alphabetically,
    and then write them to a file.

    Arguments:
      params_list: The list of board parameters
      output: The path to the output file
    """
    FIELDS = ('status', 'arch', 'cpu', 'soc', 'vendor', 'board', 'target',
              'options', 'maintainers')

    # First, decide the width of each column
    max_length = dict([ (f, 0) for f in FIELDS])
    for params in params_list:
        for f in FIELDS:
            max_length[f] = max(max_length[f], len(params[f]))

    output_lines = []
    for params in params_list:
        line = ''
        for f in FIELDS:
            # insert two spaces between fields like column -t would
            line += '  ' + params[f].ljust(max_length[f])
        output_lines.append(line.strip())

    # ignore case when sorting
    output_lines.sort(key=str.lower)

    with open(output, 'w', encoding="utf-8") as f:
        f.write(COMMENT_BLOCK + '\n'.join(output_lines) + '\n')

def gen_boards_cfg(output, jobs=1, force=False):
    """Generate a board database file.

    Arguments:
      output: The name of the output file
      jobs: The number of jobs to run simultaneously
      force: Force to generate the output even if it is new
    """
    check_top_directory()

    if not force and output_is_new(output):
        print("%s is up to date. Nothing to do." % output)
        sys.exit(0)

    params_list = scan_defconfigs(jobs)
    insert_maintainers_info(params_list)
    format_and_output(params_list, output)

def main():
    try:
        cpu_count = multiprocessing.cpu_count()
    except NotImplementedError:
        cpu_count = 1

    parser = optparse.OptionParser()
    # Add options here
    parser.add_option('-f', '--force', action="store_true", default=False,
                      help='regenerate the output even if it is new')
    parser.add_option('-j', '--jobs', type='int', default=cpu_count,
                      help='the number of jobs to run simultaneously')
    parser.add_option('-o', '--output', default=OUTPUT_FILE,
                      help='output file [default=%s]' % OUTPUT_FILE)
    (options, args) = parser.parse_args()

    gen_boards_cfg(options.output, jobs=options.jobs, force=options.force)

if __name__ == '__main__':
    main()
