# -*- Python -*-

# Configuration file for the 'lit' test runner.

import os

# name: The name of this test suite.
config.name = 'LLVM'

# testFormat: The test format to use to interpret tests.
config.test_format = lit.formats.TclTest()

# suffixes: A list of file extensions to treat as test files, this is actually
# set by on_clone().
config.suffixes = []

# test_source_root: The root path where tests are located.
config.test_source_root = os.path.dirname(__file__)

# test_exec_root: The root path where tests should be run.
llvm_obj_root = getattr(config, 'llvm_obj_root', None)
if llvm_obj_root is not None:
    config.test_exec_root = os.path.join(llvm_obj_root, 'test')

# Tweak the PATH to include the scripts dir, the tools dir, and the llvm-gcc bin
# dir (if available).
if llvm_obj_root is not None:
    llvm_src_root = getattr(config, 'llvm_src_root', None)
    if not llvm_src_root:
        lit.fatal('No LLVM source root set!')
    path = os.path.pathsep.join((os.path.join(llvm_src_root, 'test',
                                              'Scripts'),
                                 config.environment['PATH']))
    config.environment['PATH'] = path

    llvm_tools_dir = getattr(config, 'llvm_tools_dir', None)
    if not llvm_tools_dir:
        lit.fatal('No LLVM tools dir set!')
    path = os.path.pathsep.join((llvm_tools_dir, config.environment['PATH']))
    config.environment['PATH'] = path

    llvmgcc_dir = getattr(config, 'llvmgcc_dir', None)
    if not llvm_tools_dir:
        lit.fatal('No llvm-gcc dir set!')
    if llvmgcc_dir:
        path = os.path.pathsep.join((os.path.join(llvmgcc_dir, 'bin'),
                                     config.environment['PATH']))
        config.environment['PATH'] = path

###

import os

# Check that the object root is known.
if config.test_exec_root is None:
    # Otherwise, we haven't loaded the site specific configuration (the user is
    # probably trying to run on a test file directly, and either the site
    # configuration hasn't been created by the build system, or we are in an
    # out-of-tree build situation).

    # Try to detect the situation where we are using an out-of-tree build by
    # looking for 'llvm-config'.
    #
    # FIXME: I debated (i.e., wrote and threw away) adding logic to
    # automagically generate the lit.site.cfg if we are in some kind of fresh
    # build situation. This means knowing how to invoke the build system
    # though, and I decided it was too much magic.

    llvm_config = lit.util.which('llvm-config', config.environment['PATH'])
    if not llvm_config:
        lit.fatal('No site specific configuration available!')

    # Get the source and object roots.
    llvm_src_root = lit.util.capture(['llvm-config', '--src-root']).strip()
    llvm_obj_root = lit.util.capture(['llvm-config', '--obj-root']).strip()

    # Validate that we got a tree which points to here.
    this_src_root = os.path.dirname(config.test_source_root)
    if os.path.realpath(llvm_src_root) != os.path.realpath(this_src_root):
        lit.fatal('No site specific configuration available!')

    # Check that the site specific configuration exists.
    site_cfg = os.path.join(llvm_obj_root, 'test', 'lit.site.cfg')
    if not os.path.exists(site_cfg):
        lit.fatal('No site specific configuration available!')

    # Okay, that worked. Notify the user of the automagic, and reconfigure.
    lit.note('using out-of-tree build at %r' % llvm_obj_root)
    lit.load_config(config, site_cfg)
    raise SystemExit

###

# Load site data from DejaGNU's site.exp.
import re
site_exp = {}
# FIXME: Implement lit.site.cfg.
for line in open(os.path.join(config.llvm_obj_root, 'test', 'site.exp')):
    m = re.match('set ([^ ]+) "([^"]*)"', line)
    if m:
        site_exp[m.group(1)] = m.group(2)

# Add substitutions.
config.substitutions.append(('%llvmgcc_only', site_exp['llvmgcc']))
for sub in ['llvmgcc', 'llvmgxx', 'compile_cxx', 'compile_c',
            'link', 'shlibext', 'ocamlopt', 'llvmdsymutil', 'llvmlibsdir',
            'bugpoint_topts']:
    if sub in ('llvmgcc', 'llvmgxx'):
        config.substitutions.append(('%' + sub,
                                     site_exp[sub] + ' -emit-llvm -w'))
    else:
        config.substitutions.append(('%' + sub, site_exp[sub]))

excludes = []

# Provide target_triple for use in XFAIL and XTARGET.
config.target_triple = site_exp['target_triplet']

# Provide llvm_supports_target for use in local configs.
targets = set(site_exp["TARGETS_TO_BUILD"].split())
def llvm_supports_target(name):
    return name in targets

langs = set(site_exp['llvmgcc_langs'].split(','))
def llvm_gcc_supports(name):
    return name in langs

bindings = set(site_exp['llvm_bindings'].split(','))
def llvm_supports_binding(name):
    return name in langs

# Provide on_clone hook for reading 'dg.exp'.
import os
simpleLibData = re.compile(r"""load_lib llvm.exp

RunLLVMTests \[lsort \[glob -nocomplain \$srcdir/\$subdir/\*\.(.*)\]\]""",
                           re.MULTILINE)
conditionalLibData = re.compile(r"""load_lib llvm.exp

if.*\[ ?(llvm[^ ]*) ([^ ]*) ?\].*{
 *RunLLVMTests \[lsort \[glob -nocomplain \$srcdir/\$subdir/\*\.(.*)\]\]
\}""", re.MULTILINE)
def on_clone(parent, cfg, for_path):
    def addSuffixes(match):
        if match[0] == '{' and match[-1] == '}':
            cfg.suffixes = ['.' + s for s in match[1:-1].split(',')]
        else:
            cfg.suffixes = ['.' + match]

    libPath = os.path.join(os.path.dirname(for_path),
                           'dg.exp')
    if not os.path.exists(libPath):
        cfg.unsupported = True
        return

    # Reset unsupported, in case we inherited it.
    cfg.unsupported = False
    lib = open(libPath).read().strip()

    # Check for a simple library.
    m = simpleLibData.match(lib)
    if m:
        addSuffixes(m.group(1))
        return

    # Check for a conditional test set.
    m = conditionalLibData.match(lib)
    if m:
        funcname,arg,match = m.groups()
        addSuffixes(match)

        func = globals().get(funcname)
        if not func:
            lit.error('unsupported predicate %r' % funcname)
        elif not func(arg):
            cfg.unsupported = True
        return
    # Otherwise, give up.
    lit.error('unable to understand %r:\n%s' % (libPath, lib))

config.on_clone = on_clone
