#!/usr/bin/env python3
#
# Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
#
# SPDX-License-Identifier: GPL-2.0-only
#
"""
Extract information of interest to the seL4 image build process from the
`platform_gen.yaml` file.

THIS IS NOT A STABLE API.  Use as a script, not a module.
"""

import argparse
import sys
import yaml

from typing import Any, Dict, List, Tuple

program_name = sys.argv[0]


# You can run the doctests with `python3 -m doctest $THIS_FILE`.
def is_valid(data: Dict[str, Any]) -> Tuple[bool, List[str]]:
    """
    Verify that the `data` (which should be obtained from a YAML file using
    `load_data()` contains a well-formed List of disjunct memory regions ordered
    by increasing addresses.

    Returns a tuple of a `bool` and a list of strings.  The list is empty if
    there were no problems, and describes one validation issue per element
    otherwise.

    >>> is_valid(None)
    (False, ['no data in file'])
    >>> is_valid({'devices': [{'end': 9699328, 'start': 9437184}]})
    (False, ['no description of memory in file (no "memory" key)'])
    >>> is_valid({'memory': 1})
    (False, ['bad description of memory in file ("memory" is not a list)'])
    >>> is_valid({'memory': []})
    (False, ['memory described as empty in file (list is zero-length)'])
    >>> is_valid({'memory': [{'end': 1342177280, 'start': 268435456}]})
    (True, [])
    >>> is_valid({'memory': [{'end': 1342177280}]})
    (False, ['region 0 is missing its start bound'])
    >>> is_valid({'memory': [{'start': 268435456}]})
    (False, ['region 0 is missing its end bound'])
    >>> is_valid({'memory': [{'junk': 'foo'}]})
    (False, ['region 0 is missing its start bound', 'region 0 is missing its end bound'])
    >>> is_valid({'memory': [{'start': 'foo'}]})
    (False, ['region start "foo" is not an integer', 'region 0 is missing its end bound'])
    >>> is_valid({'memory': [{'start': 'foo', 'end': 'bar'}]})
    (False, ['region start "foo" is not an integer', 'region end "bar" is not an integer'])
    >>> is_valid({'memory': [{'start': 2048, 'end': 1024}]})
    (False, ['region bounds are not in strictly increasing order (1024 not > 2048)'])
    >>> is_valid({'memory': [{'end': 4095, 'start': 0}, {'end': 65535, 'start': 32768}, {'end': 1342177280, 'start': 268435456}]})
    (True, [])
    >>> is_valid({'memory': [{'end': 4095, 'start': 0}, {'end': 65535, 'start': 32768}, {'end': 1342177280, 'start': 268435456}, {'end': 16384, 'start': 32768}]})
    (False, ['region bounds are not in strictly increasing order (32768 not > 1342177280)', 'region bounds are not in strictly increasing order (16384 not > 1342177280)'])
    """
    problems = []

    if data is None:
        problems.append('no data in file')
    elif 'memory' not in data:
        problems.append('no description of memory in file (no "memory" key)')
    elif not isinstance(data['memory'], list):
        problems.append('bad description of memory in file'
                        ' ("memory" is not a list)')
    elif len(data['memory']) == 0:
        problems.append('memory described as empty in file'
                        ' (list is zero-length)')
    else:
        # The initialization of last_seen_bound works with the "increasing
        # bounds" comparison below to require that all addresses be nonnegative.
        last_seen_bound = -1
        region_counter = 0

        for region in data['memory']:
            for bound in ('start', 'end'):
                if bound not in region:
                    problems.append('region {n} is missing its {name} bound'
                                    .format(n=region_counter, name=bound))
                elif not isinstance(region[bound], int):
                    problems.append('region {name} "{value}" is not an integer'
                                    .format(name=bound, value=region[bound]))
                elif not region[bound] > last_seen_bound:
                    problems.append('region bounds are not in strictly'
                                    ' increasing order ({this} not > {last})'
                                    .format(this=region[bound],
                                            last=last_seen_bound))
                else:
                    last_seen_bound = region[bound]

            region_counter += 1

    if problems:
        return (False, problems)

    return (True, [])


def report(data=None, c_symbols: Dict[str, str] = {}, use_c=False) -> str:
    """
    Return a (typically multi-line) string with information about memory regions
    described in `data`.  The string is empty if `is_valid()` rejects the data.

    The default string contents are human-readable; if `use_c` is `True`, C
    syntax is emitted instead.  The `c_symbols` dict describes the C symbol
    names to be emitted.
    """
    if not is_valid(data):
        return ''

    n = len(data['memory'])

    if use_c:
        # Extract C symbol names from the dict for convenience.
        (array, length, tag) = (
            c_symbols['array_symbol'],
            c_symbols['array_length_symbol'],
            c_symbols['structure_tag_symbol']
        )

        # We want to mark generated code with a comment.  For best comprehension
        # (by the reader of the generated code), we want to clearly indicate (1)
        # what generated the code and (2) where the generated section begins and
        # ends.  We also want the comments to otherwise be as similar as
        # possible to facilitate any desired post-processing.  To avoid
        # repeating ourselves here (in Python), we generate a _template_
        # string containing a C comment with the name of the generating program
        # embedded.  The tag ("BEGIN" or "END") is then expanded when written to
        # the appropriate place in the generated code.
        comment_template = '/* generated by {} {{tag}} */'.format(program_name)
        head = '''{comment_begin}
int {length} = {n};

struct {tag} {{
    size_t start;
    size_t end;
}} {array}[{n}] = {{
'''.format(comment_begin=comment_template.format(tag='BEGIN'),
           length=length,
           tag=tag,
           array=array,
           n=n)
        regions = []

        for r in range(n):
            regions.append('''\t{{ .start = {start}, .end = {end} }},\
'''.format(start=data['memory'][r]['start'], end=data['memory'][r]['end']))

        body = '\n'.join(regions)
        tail = '\n}};\n{}'''.format(comment_template.format(tag='END'))
        report = '{head}{body}{tail}'.format(head=head, body=body, tail=tail)
    else:
        head = 'number of memory regions: {}\n'.format(n)
        regions = []

        for r in range(n):
            regions.append('''region {r}:
\tstart: {start}
\tend: {end}'''.format(r=r, start=data['memory'][r]['start'],
                       end=data['memory'][r]['end']))

        report = '{head}{body}'.format(head=head, body='\n'.join(regions))

    return report


def load_data(yaml_filename: str) -> Dict[str, Any]:
    """
    Call `yaml_load()` (from `pyyaml`) on `yaml_filename` and return a Dict
    containing what was found there.
    """
    with open(yaml_filename, 'r') as f:
        data = yaml.safe_load(f)

    return data


def _process_operand(yaml_filename: str, c_symbols: Dict[str, str],
                     use_c: bool) -> bool:
    """
    Handle one non-optional command-line argument; called by `main()`.
    """
    data = load_data(yaml_filename)
    (is_good_data, problems) = is_valid(data)

    if is_good_data:
        print(report(data, c_symbols, use_c=use_c))
    else:
        # Set up a prefix for diagnostic messages.  Diagnostics should always
        # identify who is talking (`program_name`) and if operating on a file,
        # should name the file in which trouble is encountered.  Both of these
        # make grep more effective.
        prefix = "{pn}: file \"{fn}\":".format(pn=program_name,
                                               fn=yaml_filename)

        if len(problems) == 1:
            sys.stderr.write("{} {}\n".format(prefix, problems[0]))
        else:
            sys.stderr.write("{} has multiple problems:\n".format(prefix))
            [sys.stderr.write('{}\t{}\n'.format(prefix, p)) for p in problems]

        return False

    return True


def main() -> int:
    """
    Executable entry point.
    """
    parser = argparse.ArgumentParser(
        formatter_class=argparse.RawDescriptionHelpFormatter,
        description="""
Extract information of interest to the seL4 image build process from one or more
files generated by `platform_gen.yaml`.

If a YAML file lacks a description of memory, or fails to parse, a diagnostic is
emitted and an exit status of 1 returned.  Exit status 2 indicates a problem
while attempting to parse arguments.

Note that when `--emit-c-syntax` is specified, C99 designated initialisers are
used in the generated code.  This code can be used directly (e.g., inside a
function body) or in a header file.

An example of usage follows.  Note the symbol names used, including those of the
structure members.  An array of structures is always used, even if there is only
one region and therefore array element.  The length of the array is explicitly
exposed, rather than using values like "NULL, NULL" to mark the end of the list.

```
#include "output_of_this_tool.h"

int main(int argc, char *argv[]) {
    for (int i = 0; i < num_memory_regions; i++) {
        (void) printf("memory region %d: 0x%08lx - 0x%08lx\\n",
                      i, memory_region[i].start, memory_region[i].end);
    }
}
```
""")
    parser.add_argument('platform_filename', nargs='+', type=str,
                        help='YAML description of platform parameters')
    parser.add_argument('--emit-c-syntax', action='store_true',
                        help='emit C syntax instead of human-readable output')
    parser.add_argument('--array_symbol', type=str,
                        default='memory_region',
                        help='desired C identifier for struct array')
    parser.add_argument('--array_length_symbol', type=str,
                        default='num_memory_regions',
                        help='desired C identifier for length of struct array')
    parser.add_argument('--structure_tag_symbol', type=str,
                        default='memory_region',
                        help='desired C identifier for structure tag')
    args = parser.parse_args()
    there_was_any_trouble = False

    c_symbols = {
        'array_symbol': args.array_symbol,
        'array_length_symbol': args.array_length_symbol,
        'structure_tag_symbol': args.structure_tag_symbol,
    }

    for yaml_filename in args.platform_filename:
        if not _process_operand(yaml_filename, c_symbols,
                                use_c=args.emit_c_syntax):
            there_was_any_trouble = True

    return 1 if there_was_any_trouble else 0


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