#!/usr/bin/env python
#
# This tool queries a ninja build file for the test-suite to figure out details
# about the build like the sourcefiles involved in a target or the assembly
# files output when clang is invoked with -save-temps=obj.
# It comes with an additional mode that given two build directories invokes the
# diff tool for each pair of files.
#
# Examples:
#
# List .stats files for the build in the current directory (assuming
# -save-stats=obj in CFLAGS):
#   $ tdiff.py --stats all
#
# Compare assembly files of the 176.gcc benchmark between two test-suite build
# directories (assuming -save-temps=obj in CFLAGS):
#   $ tdiff.py -a path/dir_before -b path/dir_after --s_files 176.gcc | less
#
# Ninja query code based on ninja/src/browse.py (apache license version 2.0).
import sys
import subprocess
import argparse
import os
from collections import namedtuple


Node = namedtuple('Node', ['inputs', 'rule', 'target', 'outputs'])


def match_strip(line, prefix):
    if not line.startswith(prefix):
        return (False, line)
    return (True, line[len(prefix):])


def parse(text):
    text = text.strip()
    lines = iter(text.split('\n'))

    rule = None
    inputs = []
    outputs = []

    try:
        line = None
        while True:
            target = None
            if line is None:
                line = next(lines)
            target = line[:-1]  # strip trailing colon

            line = next(lines)
            (match, rule) = match_strip(line, '  input: ')
            if match:
                (match, line) = match_strip(next(lines), '    ')
                while match:
                    type = None
                    (match, line) = match_strip(line, '| ')
                    if match:
                        type = 'implicit'
                    (match, line) = match_strip(line, '|| ')
                    if match:
                        type = 'order-only'
                    inputs.append((line, type))
                    (match, line) = match_strip(next(lines), '    ')

            match, _ = match_strip(line, '  outputs:')
            if match:
                (match, line) = match_strip(next(lines), '    ')
                while match:
                    outputs.append(line)
                    (match, line) = match_strip(next(lines), '    ')
            yield Node(inputs, rule, target, outputs)
    except StopIteration:
        pass

    if target is not None:
        yield Node(inputs, rule, target, outputs)


def query_ninja(targets, cwd):
    # Query ninja for a node in its build dependency tree.
    proc = subprocess.Popen(['ninja', '-t', 'query'] + targets, cwd=cwd,
                            stdout=subprocess.PIPE, universal_newlines=True)
    out, _ = proc.communicate()
    if proc.returncode != 0:
        raise Exception("Failed to query ninja for targets: %s" % (targets,))
    return parse(out)


def determine_max_commandline_len():
    """Determine maximum length of commandline possible"""
    # See also http://www.in-ulm.de/~mascheck/various/argmax/
    sc_arg_max = os.sysconf('SC_ARG_MAX')
    if sc_arg_max <= 0:
        return 10000 # wild guess
    env_len = 0
    for key,val in os.environ.items():
        env_len += len(key) + len(val) + 10
    return sc_arg_max - env_len


def get_inputs_rec(target, cwd):
    worklist = [target]

    result = dict()
    maxquerylen = determine_max_commandline_len() - 100
    while len(worklist) > 0:
        querylist = []
        querylen = 0
        while len(worklist) > 0:
            w = worklist.pop()
            if w in result:
                continue
            querylen += 9 + len(w)
            if querylen > maxquerylen:
                break
            querylist.append(w)
        if querylist == []:
            break

        queryres = query_ninja(querylist, cwd)
        for res in queryres:
            result[res.target] = res
            for inp,typ in res.inputs:
                if typ == 'order-only':
                    continue
                worklist.append(inp)
    return result


def replace_ext(filename, newext):
    # Note that os.path.splitext() does not work here: We want '.c.o' -> '.xxx'
    dirname, basename = os.path.split(filename)
    return dirname + "/" + basename.split(".", 1)[0] + newext


def filelist(mode, target, cwd, config):
    tree = get_inputs_rec(config.target[0], cwd)

    if config.mode == 'sources':
        # Take leafs in the dependency tree
        for target, depnode in tree.items():
            if len(depnode.inputs) == 0:
                yield target
    else:
        # Take files ending in '.o'
        for target, depnode in tree.items():
            if target.endswith(".o"):
                # Determine .s/.stats ending used by -save-temps=obj or
                # -save-stats=obj
                if config.mode == 's_files':
                    target = replace_ext(target, '.s')
                elif config.mode == 'stats':
                    target = replace_ext(target, '.stats')
                else:
                    assert config.mode == 'objects'
                yield target


def diff_file(dir0, dir1, target, config):
    u_args = ['-u']
    if config.diff_U is not None:
        u_args = ['-U' + config.diff_U]
    files = ["%s/%s" % (dir0, target), "%s/%s" % (dir1, target)]
    rescode = subprocess.call(['diff'] + u_args + files)
    return rescode


def main(argv):
    parser = argparse.ArgumentParser(prog=argv[0])
    parser.add_argument('-s', '--s_files', dest='mode', action='store_const',
                        const='s_files', help="Select assembly files")
    parser.add_argument('-i', '--sources', dest='mode', action='store_const',
                        const='sources', help="Select source files")
    parser.add_argument('-o', '--objects', dest='mode', action='store_const',
                        const='objects', help="Select object files")
    parser.add_argument('-S', '--stats', dest='mode', action='store_const',
                        const='stats', help="Select statistics files")
    parser.add_argument('-a', '--dir0', dest='dir0')
    parser.add_argument('-b', '--dir1', dest='dir1')
    parser.add_argument('-U', dest='diff_U')
    parser.add_argument('target', metavar='TARGET', nargs=1)
    config = parser.parse_args()
    if config.mode is None:
        parser.print_usage(sys.stderr)
        sys.stderr.write("%s: error: Must specify a mode\n" % (argv[0], ))
        sys.exit(1)
    if (config.dir0 is None) != (config.dir1 is None):
        sys.stderr.write("%s: error: Must specify dir0+dir1 (or none)")
        sys.exit(1)

    files = filelist(config.mode, config.target[0], config.dir0, config)

    if config.dir0:
        global_rc = 0
        for target in files:
            rc = diff_file(config.dir0, config.dir1, target, config)
            if rc != 0:
                global_rc = rc
        sys.exit(global_rc)
    else:
        # Simply print file list
        for f in files:
            print(f)


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