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

"""
Converter from Kconfig and MAINTAINERS to boards.cfg

Run 'tools/genboardscfg.py' to create boards.cfg file.

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

import errno
import fnmatch
import glob
import optparse
import os
import re
import shutil
import subprocess
import sys
import tempfile
import time

BOARD_FILE = 'boards.cfg'
CONFIG_DIR = 'configs'
REFORMAT_CMD = [os.path.join('tools', 'reformat.py'),
                '-i', '-d', '-', '-s', '8']
SHOW_GNU_MAKE = 'scripts/show-gnu-make'
SLEEP_TIME=0.03

COMMENT_BLOCK = '''#
# List of boards
#   Automatically generated by %s: don't edit
#
# Status, Arch, CPU(:SPLCPU), SoC, Vendor, Board, Target, Options, Maintainers

''' % __file__

### helper functions ###
def get_terminal_columns():
    """Get the width of the terminal.

    Returns:
      The width of the terminal, or zero if the stdout is not
      associated with tty.
    """
    try:
        return shutil.get_terminal_size().columns # Python 3.3~
    except AttributeError:
        import fcntl
        import termios
        import struct
        arg = struct.pack('hhhh', 0, 0, 0, 0)
        try:
            ret = fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ, arg)
        except IOError as exception:
            if exception.errno != errno.ENOTTY:
                raise
            # If 'Inappropriate ioctl for device' error occurs,
            # stdout is probably redirected. Return 0.
            return 0
        return struct.unpack('hhhh', ret)[1]

def get_devnull():
    """Get the file object of '/dev/null' device."""
    try:
        devnull = subprocess.DEVNULL # py3k
    except AttributeError:
        devnull = open(os.devnull, 'wb')
    return devnull

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):
            print >> sys.stderr, 'Please run at the top of source directory.'
            sys.exit(1)

def get_make_cmd():
    """Get the command name of GNU Make."""
    process = subprocess.Popen([SHOW_GNU_MAKE], stdout=subprocess.PIPE)
    ret = process.communicate()
    if process.returncode:
        print >> sys.stderr, 'GNU Make not found'
        sys.exit(1)
    return ret[0].rstrip()

### classes ###
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.

        Returns:
          Either 'Active' or 'Orphan'
        """
        tmp = self.database[target][0]
        if tmp.startswith('Maintained'):
            return 'Active'
        elif tmp.startswith('Orphan'):
            return 'Orphan'
        else:
            print >> sys.stderr, 'Error: %s: unknown status' % tmp

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

        If the board has two or more maintainers, they are separated
        with colons.
        """
        return ':'.join(self.database[target][1])

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

        This method parses MAINTAINERS and add board status and
        maintainers information to the database.

        Arguments:
          file: MAINTAINERS file to be parsed
        """
        targets = []
        maintainers = []
        status = '-'
        for line in open(file):
            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' and targets:
                for target in targets:
                    self.database[target] = (status, maintainers)
                targets = []
                maintainers = []
                status = '-'
        if targets:
            for target in targets:
                self.database[target] = (status, maintainers)

class DotConfigParser:

    """A parser of .config file.

    Each line of the output should have the form of:
    Status, Arch, CPU, SoC, Vendor, Board, Target, Options, Maintainers
    Most of them are extracted from .config file.
    MAINTAINERS files are also consulted for Status and Maintainers fields.
    """

    re_arch = re.compile(r'CONFIG_SYS_ARCH="(.*)"')
    re_cpu = re.compile(r'CONFIG_SYS_CPU="(.*)"')
    re_soc = re.compile(r'CONFIG_SYS_SOC="(.*)"')
    re_vendor = re.compile(r'CONFIG_SYS_VENDOR="(.*)"')
    re_board = re.compile(r'CONFIG_SYS_BOARD="(.*)"')
    re_config = re.compile(r'CONFIG_SYS_CONFIG_NAME="(.*)"')
    re_options = re.compile(r'CONFIG_SYS_EXTRA_OPTIONS="(.*)"')
    re_list = (('arch', re_arch), ('cpu', re_cpu), ('soc', re_soc),
               ('vendor', re_vendor), ('board', re_board),
               ('config', re_config), ('options', re_options))
    must_fields = ('arch', 'config')

    def __init__(self, build_dir, output, maintainers_database):
        """Create a new .config perser.

        Arguments:
          build_dir: Build directory where .config is located
          output: File object which the result is written to
          maintainers_database: An instance of class MaintainersDatabase
        """
        self.dotconfig = os.path.join(build_dir, '.config')
        self.output = output
        self.database = maintainers_database

    def parse(self, defconfig):
        """Parse .config file and output one-line database for the given board.

        Arguments:
          defconfig: Board (defconfig) name
        """
        fields = {}
        for line in open(self.dotconfig):
            if not line.startswith('CONFIG_SYS_'):
                continue
            for (key, pattern) in self.re_list:
                m = pattern.match(line)
                if m and m.group(1):
                    fields[key] = m.group(1)
                    break

        # sanity check of '.config' file
        for field in self.must_fields:
            if not field in fields:
                print >> sys.stderr, 'Error: %s is not defined in %s' % \
                                                            (field, defconfig)
                sys.exit(1)

        # fix-up for aarch64 and tegra
        if fields['arch'] == 'arm' and 'cpu' in fields:
            if fields['cpu'] == 'armv8':
                fields['arch'] = 'aarch64'
            if 'soc' in fields and re.match('tegra[0-9]*$', fields['soc']):
                fields['cpu'] += ':arm720t'

        target, match, rear = defconfig.partition('_defconfig')
        assert match and not rear, \
                                '%s : invalid defconfig file name' % defconfig

        fields['status'] = self.database.get_status(target)
        fields['maintainers'] = self.database.get_maintainers(target)

        if 'options' in fields:
            options = fields['config'] + ':' + \
                      fields['options'].replace(r'\"', '"')
        elif fields['config'] != target:
            options = fields['config']
        else:
            options = '-'

        self.output.write((' '.join(['%s'] * 9) + '\n')  %
                          (fields['status'],
                           fields['arch'],
                           fields.get('cpu', '-'),
                           fields.get('soc', '-'),
                           fields.get('vendor', '-'),
                           fields.get('board', '-'),
                           target,
                           options,
                           fields['maintainers']))

class Slot:

    """A slot to store a subprocess.

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

    def __init__(self, output, maintainers_database, devnull, make_cmd):
        """Create a new slot.

        Arguments:
          output: File object which the result is written to
          maintainers_database: An instance of class MaintainersDatabase
        """
        self.occupied = False
        self.build_dir = tempfile.mkdtemp()
        self.devnull = devnull
        self.make_cmd = make_cmd
        self.parser = DotConfigParser(self.build_dir, output,
                                      maintainers_database)

    def __del__(self):
        """Delete the working directory"""
        shutil.rmtree(self.build_dir)

    def add(self, defconfig):
        """Add a new subprocess to the slot.

        Fails if the slot is occupied, that is, the current subprocess
        is still running.

        Arguments:
          defconfig: Board (defconfig) name

        Returns:
          Return True on success or False on fail
        """
        if self.occupied:
            return False
        o = 'O=' + self.build_dir
        self.ps = subprocess.Popen([self.make_cmd, o, defconfig],
                                   stdout=self.devnull)
        self.defconfig = defconfig
        self.occupied = True
        return True

    def poll(self):
        """Check if the subprocess is running and invoke the .config
        parser if the subprocess is terminated.

        Returns:
          Return True if the subprocess is terminated, False otherwise
        """
        if not self.occupied:
            return True
        if self.ps.poll() == None:
            return False
        self.parser.parse(self.defconfig)
        self.occupied = False
        return True

class Slots:

    """Controller of the array of subprocess slots."""

    def __init__(self, jobs, output, maintainers_database):
        """Create a new slots controller.

        Arguments:
          jobs: A number of slots to instantiate
          output: File object which the result is written to
          maintainers_database: An instance of class MaintainersDatabase
        """
        self.slots = []
        devnull = get_devnull()
        make_cmd = get_make_cmd()
        for i in range(jobs):
            self.slots.append(Slot(output, maintainers_database,
                                   devnull, make_cmd))

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

        Arguments:
          defconfig: Board (defconfig) name

        Returns:
          Return True on success or False on fail
        """
        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 a vacant slot is found, False if all slots are full
        """
        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 slots are vacant, False if at least one slot
          is running
        """
        ret = True
        for slot in self.slots:
            if not slot.poll():
                ret = False
        return ret

class Indicator:

    """A class to control the progress indicator."""

    MIN_WIDTH = 15
    MAX_WIDTH = 70

    def __init__(self, total):
        """Create an instance.

        Arguments:
          total: A number of boards
        """
        self.total = total
        self.cur = 0
        width = get_terminal_columns()
        width = min(width, self.MAX_WIDTH)
        width -= self.MIN_WIDTH
        if width > 0:
            self.enabled = True
        else:
            self.enabled = False
        self.width = width

    def inc(self):
        """Increment the counter and show the progress bar."""
        if not self.enabled:
            return
        self.cur += 1
        arrow_len = self.width * self.cur // self.total
        msg = '%4d/%d [' % (self.cur, self.total)
        msg += '=' * arrow_len + '>' + ' ' * (self.width - arrow_len) + ']'
        sys.stdout.write('\r' + msg)
        sys.stdout.flush()

def __gen_boards_cfg(jobs):
    """Generate boards.cfg file.

    Arguments:
      jobs: The number of jobs to run simultaneously

    Note:
      The incomplete boards.cfg is left over when an error (including 
      the termination by the keyboard interrupt) occurs on the halfway.
    """
    check_top_directory()
    print 'Generating %s ...  (jobs: %d)' % (BOARD_FILE, jobs)

    # All the defconfig files to be processed
    defconfigs = []
    for (dirpath, dirnames, filenames) in os.walk(CONFIG_DIR):
        dirpath = dirpath[len(CONFIG_DIR) + 1:]
        for filename in fnmatch.filter(filenames, '*_defconfig'):
            defconfigs.append(os.path.join(dirpath, filename))

    # Parse all the MAINTAINERS files
    maintainers_database = MaintainersDatabase()
    for (dirpath, dirnames, filenames) in os.walk('.'):
        if 'MAINTAINERS' in filenames:
            maintainers_database.parse_file(os.path.join(dirpath,
                                                         'MAINTAINERS'))

    # Output lines should be piped into the reformat tool
    reformat_process = subprocess.Popen(REFORMAT_CMD, stdin=subprocess.PIPE,
                                        stdout=open(BOARD_FILE, 'w'))
    pipe = reformat_process.stdin
    pipe.write(COMMENT_BLOCK)

    indicator = Indicator(len(defconfigs))
    slots = Slots(jobs, pipe, maintainers_database)

    # 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)
        indicator.inc()

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

    # wait until the reformat tool finishes
    reformat_process.communicate()
    if reformat_process.returncode != 0:
        print >> sys.stderr, '"%s" failed' % REFORMAT_CMD[0]
        sys.exit(1)

def gen_boards_cfg(jobs):
    """Generate boards.cfg file.

    The incomplete boards.cfg is deleted if an error (including
    the termination by the keyboard interrupt) occurs on the halfway.

    Arguments:
      jobs: The number of jobs to run simultaneously
    """
    try:
        __gen_boards_cfg(jobs)
    except:
        # We should remove incomplete boards.cfg
        try:
            os.remove(BOARD_FILE)
        except OSError as exception:
            # Ignore 'No such file or directory' error
            if exception.errno != errno.ENOENT:
                raise
        raise

def main():
    parser = optparse.OptionParser()
    # Add options here
    parser.add_option('-j', '--jobs',
                      help='the number of jobs to run simultaneously')
    (options, args) = parser.parse_args()
    if options.jobs:
        try:
            jobs = int(options.jobs)
        except ValueError:
            print >> sys.stderr, 'Option -j (--jobs) takes a number'
            sys.exit(1)
    else:
        try:
            jobs = int(subprocess.Popen(['getconf', '_NPROCESSORS_ONLN'],
                                     stdout=subprocess.PIPE).communicate()[0])
        except (OSError, ValueError):
            print 'info: failed to get the number of CPUs. Set jobs to 1'
            jobs = 1
    gen_boards_cfg(jobs)

if __name__ == '__main__':
    main()
