# -*- coding: utf-8 -*-
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
""" This module implements the 'scan-build' command API.

To run the static analyzer against a build is done in multiple steps:

 -- Intercept: capture the compilation command during the build,
 -- Analyze:   run the analyzer against the captured commands,
 -- Report:    create a cover report from the analyzer outputs.  """

import re
import os
import os.path
import json
import logging
import multiprocessing
import tempfile
import functools
import subprocess
import contextlib
import datetime
import shutil
import glob
from collections import defaultdict

from libscanbuild import command_entry_point, compiler_wrapper, \
    wrapper_environment, run_build, run_command, CtuConfig
from libscanbuild.arguments import parse_args_for_scan_build, \
    parse_args_for_analyze_build
from libscanbuild.intercept import capture
from libscanbuild.report import document
from libscanbuild.compilation import split_command, classify_source, \
    compiler_language
from libscanbuild.clang import get_version, get_arguments, get_triple_arch, \
    ClangErrorException
from libscanbuild.shell import decode

__all__ = ['scan_build', 'analyze_build', 'analyze_compiler_wrapper']

scanbuild_dir = os.path.dirname(os.path.realpath(__import__('sys').argv[0]))

COMPILER_WRAPPER_CC = os.path.join(scanbuild_dir, '..', 'libexec', 'analyze-cc')
COMPILER_WRAPPER_CXX = os.path.join(scanbuild_dir, '..', 'libexec', 'analyze-c++')

CTU_EXTDEF_MAP_FILENAME = 'externalDefMap.txt'
CTU_TEMP_DEFMAP_FOLDER = 'tmpExternalDefMaps'


@command_entry_point
def scan_build():
    """ Entry point for scan-build command. """

    args = parse_args_for_scan_build()
    # will re-assign the report directory as new output
    with report_directory(
            args.output, args.keep_empty, args.output_format) as args.output:
        # Run against a build command. there are cases, when analyzer run
        # is not required. But we need to set up everything for the
        # wrappers, because 'configure' needs to capture the CC/CXX values
        # for the Makefile.
        if args.intercept_first:
            # Run build command with intercept module.
            exit_code = capture(args)
            # Run the analyzer against the captured commands.
            if need_analyzer(args.build):
                govern_analyzer_runs(args)
        else:
            # Run build command and analyzer with compiler wrappers.
            environment = setup_environment(args)
            exit_code = run_build(args.build, env=environment)
        # Cover report generation and bug counting.
        number_of_bugs = document(args)
        # Set exit status as it was requested.
        return number_of_bugs if args.status_bugs else exit_code


@command_entry_point
def analyze_build():
    """ Entry point for analyze-build command. """

    args = parse_args_for_analyze_build()
    # will re-assign the report directory as new output
    with report_directory(args.output, args.keep_empty, args.output_format) as args.output:
        # Run the analyzer against a compilation db.
        govern_analyzer_runs(args)
        # Cover report generation and bug counting.
        number_of_bugs = document(args)
        # Set exit status as it was requested.
        return number_of_bugs if args.status_bugs else 0


def need_analyzer(args):
    """ Check the intent of the build command.

    When static analyzer run against project configure step, it should be
    silent and no need to run the analyzer or generate report.

    To run `scan-build` against the configure step might be necessary,
    when compiler wrappers are used. That's the moment when build setup
    check the compiler and capture the location for the build process. """

    return len(args) and not re.search(r'configure|autogen', args[0])


def prefix_with(constant, pieces):
    """ From a sequence create another sequence where every second element
    is from the original sequence and the odd elements are the prefix.

    eg.: prefix_with(0, [1,2,3]) creates [0, 1, 0, 2, 0, 3] """

    return [elem for piece in pieces for elem in [constant, piece]]


def get_ctu_config_from_args(args):
    """ CTU configuration is created from the chosen phases and dir. """

    return (
        CtuConfig(collect=args.ctu_phases.collect,
                  analyze=args.ctu_phases.analyze,
                  dir=args.ctu_dir,
                  extdef_map_cmd=args.extdef_map_cmd)
        if hasattr(args, 'ctu_phases') and hasattr(args.ctu_phases, 'dir')
        else CtuConfig(collect=False, analyze=False, dir='', extdef_map_cmd=''))


def get_ctu_config_from_json(ctu_conf_json):
    """ CTU configuration is created from the chosen phases and dir. """

    ctu_config = json.loads(ctu_conf_json)
    # Recover namedtuple from json when coming from analyze-cc or analyze-c++
    return CtuConfig(collect=ctu_config[0],
                     analyze=ctu_config[1],
                     dir=ctu_config[2],
                     extdef_map_cmd=ctu_config[3])


def create_global_ctu_extdef_map(extdef_map_lines):
    """ Takes iterator of individual external definition maps and creates a
    global map keeping only unique names. We leave conflicting names out of
    CTU.

    :param extdef_map_lines: Contains the id of a definition (mangled name) and
    the originating source (the corresponding AST file) name.
    :type extdef_map_lines: Iterator of str.
    :returns: Mangled name - AST file pairs.
    :rtype: List of (str, str) tuples.
    """

    mangled_to_asts = defaultdict(set)

    for line in extdef_map_lines:
        mangled_name, ast_file = line.strip().split(' ', 1)
        mangled_to_asts[mangled_name].add(ast_file)

    mangled_ast_pairs = []

    for mangled_name, ast_files in mangled_to_asts.items():
        if len(ast_files) == 1:
            mangled_ast_pairs.append((mangled_name, next(iter(ast_files))))

    return mangled_ast_pairs


def merge_ctu_extdef_maps(ctudir):
    """ Merge individual external definition maps into a global one.

    As the collect phase runs parallel on multiple threads, all compilation
    units are separately mapped into a temporary file in CTU_TEMP_DEFMAP_FOLDER.
    These definition maps contain the mangled names and the source
    (AST generated from the source) which had their definition.
    These files should be merged at the end into a global map file:
    CTU_EXTDEF_MAP_FILENAME."""

    def generate_extdef_map_lines(extdefmap_dir):
        """ Iterate over all lines of input files in a determined order. """

        files = glob.glob(os.path.join(extdefmap_dir, '*'))
        files.sort()
        for filename in files:
            with open(filename, 'r') as in_file:
                for line in in_file:
                    yield line

    def write_global_map(arch, mangled_ast_pairs):
        """ Write (mangled name, ast file) pairs into final file. """

        extern_defs_map_file = os.path.join(ctudir, arch,
                                           CTU_EXTDEF_MAP_FILENAME)
        with open(extern_defs_map_file, 'w') as out_file:
            for mangled_name, ast_file in mangled_ast_pairs:
                out_file.write('%s %s\n' % (mangled_name, ast_file))

    triple_arches = glob.glob(os.path.join(ctudir, '*'))
    for triple_path in triple_arches:
        if os.path.isdir(triple_path):
            triple_arch = os.path.basename(triple_path)
            extdefmap_dir = os.path.join(ctudir, triple_arch,
                                     CTU_TEMP_DEFMAP_FOLDER)

            extdef_map_lines = generate_extdef_map_lines(extdefmap_dir)
            mangled_ast_pairs = create_global_ctu_extdef_map(extdef_map_lines)
            write_global_map(triple_arch, mangled_ast_pairs)

            # Remove all temporary files
            shutil.rmtree(extdefmap_dir, ignore_errors=True)


def run_analyzer_parallel(args):
    """ Runs the analyzer against the given compilation database. """

    def exclude(filename, directory):
        """ Return true when any excluded directory prefix the filename. """
        if not os.path.isabs(filename):
            # filename is either absolute or relative to directory. Need to turn
            # it to absolute since 'args.excludes' are absolute paths.
            filename = os.path.normpath(os.path.join(directory, filename))
        return any(re.match(r'^' + exclude_directory, filename)
                   for exclude_directory in args.excludes)

    consts = {
        'clang': args.clang,
        'output_dir': args.output,
        'output_format': args.output_format,
        'output_failures': args.output_failures,
        'direct_args': analyzer_params(args),
        'force_debug': args.force_debug,
        'ctu': get_ctu_config_from_args(args)
    }

    logging.debug('run analyzer against compilation database')
    with open(args.cdb, 'r') as handle:
        generator = (dict(cmd, **consts)
                     for cmd in json.load(handle) if not exclude(
                            cmd['file'], cmd['directory']))
        # when verbose output requested execute sequentially
        pool = multiprocessing.Pool(1 if args.verbose > 2 else None)
        for current in pool.imap_unordered(run, generator):
            if current is not None:
                # display error message from the static analyzer
                for line in current['error_output']:
                    logging.info(line.rstrip())
        pool.close()
        pool.join()


def govern_analyzer_runs(args):
    """ Governs multiple runs in CTU mode or runs once in normal mode. """

    ctu_config = get_ctu_config_from_args(args)
    # If we do a CTU collect (1st phase) we remove all previous collection
    # data first.
    if ctu_config.collect:
        shutil.rmtree(ctu_config.dir, ignore_errors=True)

    # If the user asked for a collect (1st) and analyze (2nd) phase, we do an
    # all-in-one run where we deliberately remove collection data before and
    # also after the run. If the user asks only for a single phase data is
    # left so multiple analyze runs can use the same data gathered by a single
    # collection run.
    if ctu_config.collect and ctu_config.analyze:
        # CTU strings are coming from args.ctu_dir and extdef_map_cmd,
        # so we can leave it empty
        args.ctu_phases = CtuConfig(collect=True, analyze=False,
                                    dir='', extdef_map_cmd='')
        run_analyzer_parallel(args)
        merge_ctu_extdef_maps(ctu_config.dir)
        args.ctu_phases = CtuConfig(collect=False, analyze=True,
                                    dir='', extdef_map_cmd='')
        run_analyzer_parallel(args)
        shutil.rmtree(ctu_config.dir, ignore_errors=True)
    else:
        # Single runs (collect or analyze) are launched from here.
        run_analyzer_parallel(args)
        if ctu_config.collect:
            merge_ctu_extdef_maps(ctu_config.dir)


def setup_environment(args):
    """ Set up environment for build command to interpose compiler wrapper. """

    environment = dict(os.environ)
    environment.update(wrapper_environment(args))
    environment.update({
        'CC': COMPILER_WRAPPER_CC,
        'CXX': COMPILER_WRAPPER_CXX,
        'ANALYZE_BUILD_CLANG': args.clang if need_analyzer(args.build) else '',
        'ANALYZE_BUILD_REPORT_DIR': args.output,
        'ANALYZE_BUILD_REPORT_FORMAT': args.output_format,
        'ANALYZE_BUILD_REPORT_FAILURES': 'yes' if args.output_failures else '',
        'ANALYZE_BUILD_PARAMETERS': ' '.join(analyzer_params(args)),
        'ANALYZE_BUILD_FORCE_DEBUG': 'yes' if args.force_debug else '',
        'ANALYZE_BUILD_CTU': json.dumps(get_ctu_config_from_args(args))
    })
    return environment


@command_entry_point
def analyze_compiler_wrapper():
    """ Entry point for `analyze-cc` and `analyze-c++` compiler wrappers. """

    return compiler_wrapper(analyze_compiler_wrapper_impl)


def analyze_compiler_wrapper_impl(result, execution):
    """ Implements analyzer compiler wrapper functionality. """

    # don't run analyzer when compilation fails. or when it's not requested.
    if result or not os.getenv('ANALYZE_BUILD_CLANG'):
        return

    # check is it a compilation?
    compilation = split_command(execution.cmd)
    if compilation is None:
        return
    # collect the needed parameters from environment, crash when missing
    parameters = {
        'clang': os.getenv('ANALYZE_BUILD_CLANG'),
        'output_dir': os.getenv('ANALYZE_BUILD_REPORT_DIR'),
        'output_format': os.getenv('ANALYZE_BUILD_REPORT_FORMAT'),
        'output_failures': os.getenv('ANALYZE_BUILD_REPORT_FAILURES'),
        'direct_args': os.getenv('ANALYZE_BUILD_PARAMETERS',
                                 '').split(' '),
        'force_debug': os.getenv('ANALYZE_BUILD_FORCE_DEBUG'),
        'directory': execution.cwd,
        'command': [execution.cmd[0], '-c'] + compilation.flags,
        'ctu': get_ctu_config_from_json(os.getenv('ANALYZE_BUILD_CTU'))
    }
    # call static analyzer against the compilation
    for source in compilation.files:
        parameters.update({'file': source})
        logging.debug('analyzer parameters %s', parameters)
        current = run(parameters)
        # display error message from the static analyzer
        if current is not None:
            for line in current['error_output']:
                logging.info(line.rstrip())


@contextlib.contextmanager
def report_directory(hint, keep, output_format):
    """ Responsible for the report directory.

    hint -- could specify the parent directory of the output directory.
    keep -- a boolean value to keep or delete the empty report directory. """

    stamp_format = 'scan-build-%Y-%m-%d-%H-%M-%S-%f-'
    stamp = datetime.datetime.now().strftime(stamp_format)
    parent_dir = os.path.abspath(hint)
    if not os.path.exists(parent_dir):
        os.makedirs(parent_dir)
    name = tempfile.mkdtemp(prefix=stamp, dir=parent_dir)

    logging.info('Report directory created: %s', name)

    try:
        yield name
    finally:
        args = (name,)
        if os.listdir(name):
            if output_format not in ['sarif', 'sarif-html']: # FIXME:
                # 'scan-view' currently does not support sarif format.
                msg = "Run 'scan-view %s' to examine bug reports."
            elif output_format == 'sarif-html':
                msg = "Run 'scan-view %s' to examine bug reports or see " \
                    "merged sarif results at %s/results-merged.sarif."
                args = (name, name)
            else:
                msg = "View merged sarif results at %s/results-merged.sarif."
            keep = True
        else:
            if keep:
                msg = "Report directory '%s' contains no report, but kept."
            else:
                msg = "Removing directory '%s' because it contains no report."
        logging.warning(msg, *args)

        if not keep:
            os.rmdir(name)


def analyzer_params(args):
    """ A group of command line arguments can mapped to command
    line arguments of the analyzer. This method generates those. """

    result = []

    if args.constraints_model:
        result.append('-analyzer-constraints={0}'.format(
            args.constraints_model))
    if args.internal_stats:
        result.append('-analyzer-stats')
    if args.analyze_headers:
        result.append('-analyzer-opt-analyze-headers')
    if args.stats:
        result.append('-analyzer-checker=debug.Stats')
    if args.maxloop:
        result.extend(['-analyzer-max-loop', str(args.maxloop)])
    if args.output_format:
        result.append('-analyzer-output={0}'.format(args.output_format))
    if args.analyzer_config:
        result.extend(['-analyzer-config', args.analyzer_config])
    if args.verbose >= 4:
        result.append('-analyzer-display-progress')
    if args.plugins:
        result.extend(prefix_with('-load', args.plugins))
    if args.enable_checker:
        checkers = ','.join(args.enable_checker)
        result.extend(['-analyzer-checker', checkers])
    if args.disable_checker:
        checkers = ','.join(args.disable_checker)
        result.extend(['-analyzer-disable-checker', checkers])

    return prefix_with('-Xclang', result)


def require(required):
    """ Decorator for checking the required values in state.

    It checks the required attributes in the passed state and stop when
    any of those is missing. """

    def decorator(function):
        @functools.wraps(function)
        def wrapper(*args, **kwargs):
            for key in required:
                if key not in args[0]:
                    raise KeyError('{0} not passed to {1}'.format(
                        key, function.__name__))

            return function(*args, **kwargs)

        return wrapper

    return decorator


@require(['command',  # entry from compilation database
          'directory',  # entry from compilation database
          'file',  # entry from compilation database
          'clang',  # clang executable name (and path)
          'direct_args',  # arguments from command line
          'force_debug',  # kill non debug macros
          'output_dir',  # where generated report files shall go
          'output_format',  # it's 'plist', 'html', 'plist-html', 'plist-multi-file', 'sarif', or 'sarif-html'
          'output_failures',  # generate crash reports or not
          'ctu'])  # ctu control options
def run(opts):
    """ Entry point to run (or not) static analyzer against a single entry
    of the compilation database.

    This complex task is decomposed into smaller methods which are calling
    each other in chain. If the analysis is not possible the given method
    just return and break the chain.

    The passed parameter is a python dictionary. Each method first check
    that the needed parameters received. (This is done by the 'require'
    decorator. It's like an 'assert' to check the contract between the
    caller and the called method.) """

    try:
        command = opts.pop('command')
        command = command if isinstance(command, list) else decode(command)
        logging.debug("Run analyzer against '%s'", command)
        opts.update(classify_parameters(command))

        return arch_check(opts)
    except Exception:
        logging.error("Problem occurred during analysis.", exc_info=1)
        return None


@require(['clang', 'directory', 'flags', 'file', 'output_dir', 'language',
          'error_output', 'exit_code'])
def report_failure(opts):
    """ Create report when analyzer failed.

    The major report is the preprocessor output. The output filename generated
    randomly. The compiler output also captured into '.stderr.txt' file.
    And some more execution context also saved into '.info.txt' file. """

    def extension():
        """ Generate preprocessor file extension. """

        mapping = {'objective-c++': '.mii', 'objective-c': '.mi', 'c++': '.ii'}
        return mapping.get(opts['language'], '.i')

    def destination():
        """ Creates failures directory if not exits yet. """

        failures_dir = os.path.join(opts['output_dir'], 'failures')
        if not os.path.isdir(failures_dir):
            os.makedirs(failures_dir)
        return failures_dir

    # Classify error type: when Clang terminated by a signal it's a 'Crash'.
    # (python subprocess Popen.returncode is negative when child terminated
    # by signal.) Everything else is 'Other Error'.
    error = 'crash' if opts['exit_code'] < 0 else 'other_error'
    # Create preprocessor output file name. (This is blindly following the
    # Perl implementation.)
    (handle, name) = tempfile.mkstemp(suffix=extension(),
                                      prefix='clang_' + error + '_',
                                      dir=destination())
    os.close(handle)
    # Execute Clang again, but run the syntax check only.
    cwd = opts['directory']
    cmd = [opts['clang'], '-fsyntax-only', '-E'] + opts['flags'] + \
        [opts['file'], '-o', name]
    try:
        cmd = get_arguments(cmd, cwd)
        run_command(cmd, cwd=cwd)
    except subprocess.CalledProcessError:
        pass
    except ClangErrorException:
        pass
    # write general information about the crash
    with open(name + '.info.txt', 'w') as handle:
        handle.write(opts['file'] + os.linesep)
        handle.write(error.title().replace('_', ' ') + os.linesep)
        handle.write(' '.join(cmd) + os.linesep)
        handle.write(' '.join(os.uname()) + os.linesep)
        handle.write(get_version(opts['clang']))
        handle.close()
    # write the captured output too
    with open(name + '.stderr.txt', 'w') as handle:
        handle.writelines(opts['error_output'])
        handle.close()


@require(['clang', 'directory', 'flags', 'direct_args', 'file', 'output_dir',
          'output_format'])
def run_analyzer(opts, continuation=report_failure):
    """ It assembles the analysis command line and executes it. Capture the
    output of the analysis and returns with it. If failure reports are
    requested, it calls the continuation to generate it. """

    def target():
        """ Creates output file name for reports. """
        if opts['output_format'] in {
                'plist',
                'plist-html',
                'plist-multi-file'}:
            (handle, name) = tempfile.mkstemp(prefix='report-',
                                              suffix='.plist',
                                              dir=opts['output_dir'])
            os.close(handle)
            return name
        elif opts['output_format'] in {
                'sarif',
                'sarif-html'}:
            (handle, name) = tempfile.mkstemp(prefix='result-',
                                              suffix='.sarif',
                                              dir=opts['output_dir'])
            os.close(handle)
            return name
        return opts['output_dir']

    try:
        cwd = opts['directory']
        cmd = get_arguments([opts['clang'], '--analyze'] +
                            opts['direct_args'] + opts['flags'] +
                            [opts['file'], '-o', target()],
                            cwd)
        output = run_command(cmd, cwd=cwd)
        return {'error_output': output, 'exit_code': 0}
    except subprocess.CalledProcessError as ex:
        result = {'error_output': ex.output, 'exit_code': ex.returncode}
        if opts.get('output_failures', False):
            opts.update(result)
            continuation(opts)
        return result
    except ClangErrorException as ex:
        result = {'error_output': ex.error, 'exit_code': 0}
        if opts.get('output_failures', False):
            opts.update(result)
            continuation(opts)
        return result


def extdef_map_list_src_to_ast(extdef_src_list):
    """ Turns textual external definition map list with source files into an
    external definition map list with ast files. """

    extdef_ast_list = []
    for extdef_src_txt in extdef_src_list:
        mangled_name, path = extdef_src_txt.split(" ", 1)
        # Normalize path on windows as well
        path = os.path.splitdrive(path)[1]
        # Make relative path out of absolute
        path = path[1:] if path[0] == os.sep else path
        ast_path = os.path.join("ast", path + ".ast")
        extdef_ast_list.append(mangled_name + " " + ast_path)
    return extdef_ast_list


@require(['clang', 'directory', 'flags', 'direct_args', 'file', 'ctu'])
def ctu_collect_phase(opts):
    """ Preprocess source by generating all data needed by CTU analysis. """

    def generate_ast(triple_arch):
        """ Generates ASTs for the current compilation command. """

        args = opts['direct_args'] + opts['flags']
        ast_joined_path = os.path.join(opts['ctu'].dir, triple_arch, 'ast',
                                       os.path.realpath(opts['file'])[1:] +
                                       '.ast')
        ast_path = os.path.abspath(ast_joined_path)
        ast_dir = os.path.dirname(ast_path)
        if not os.path.isdir(ast_dir):
            try:
                os.makedirs(ast_dir)
            except OSError:
                # In case an other process already created it.
                pass
        ast_command = [opts['clang'], '-emit-ast']
        ast_command.extend(args)
        ast_command.append('-w')
        ast_command.append(opts['file'])
        ast_command.append('-o')
        ast_command.append(ast_path)
        logging.debug("Generating AST using '%s'", ast_command)
        run_command(ast_command, cwd=opts['directory'])

    def map_extdefs(triple_arch):
        """ Generate external definition map file for the current source. """

        args = opts['direct_args'] + opts['flags']
        extdefmap_command = [opts['ctu'].extdef_map_cmd]
        extdefmap_command.append(opts['file'])
        extdefmap_command.append('--')
        extdefmap_command.extend(args)
        logging.debug("Generating external definition map using '%s'",
                      extdefmap_command)
        extdef_src_list = run_command(extdefmap_command, cwd=opts['directory'])
        extdef_ast_list = extdef_map_list_src_to_ast(extdef_src_list)
        extern_defs_map_folder = os.path.join(opts['ctu'].dir, triple_arch,
                                             CTU_TEMP_DEFMAP_FOLDER)
        if not os.path.isdir(extern_defs_map_folder):
            try:
                os.makedirs(extern_defs_map_folder)
            except OSError:
                # In case an other process already created it.
                pass
        if extdef_ast_list:
            with tempfile.NamedTemporaryFile(mode='w',
                                             dir=extern_defs_map_folder,
                                             delete=False) as out_file:
                out_file.write("\n".join(extdef_ast_list) + "\n")

    cwd = opts['directory']
    cmd = [opts['clang'], '--analyze'] + opts['direct_args'] + opts['flags'] \
        + [opts['file']]
    triple_arch = get_triple_arch(cmd, cwd)
    generate_ast(triple_arch)
    map_extdefs(triple_arch)


@require(['ctu'])
def dispatch_ctu(opts, continuation=run_analyzer):
    """ Execute only one phase of 2 phases of CTU if needed. """

    ctu_config = opts['ctu']

    if ctu_config.collect or ctu_config.analyze:
        assert ctu_config.collect != ctu_config.analyze
        if ctu_config.collect:
            return ctu_collect_phase(opts)
        if ctu_config.analyze:
            cwd = opts['directory']
            cmd = [opts['clang'], '--analyze'] + opts['direct_args'] \
                + opts['flags'] + [opts['file']]
            triarch = get_triple_arch(cmd, cwd)
            ctu_options = ['ctu-dir=' + os.path.join(ctu_config.dir, triarch),
                           'experimental-enable-naive-ctu-analysis=true']
            analyzer_options = prefix_with('-analyzer-config', ctu_options)
            direct_options = prefix_with('-Xanalyzer', analyzer_options)
            opts['direct_args'].extend(direct_options)

    return continuation(opts)


@require(['flags', 'force_debug'])
def filter_debug_flags(opts, continuation=dispatch_ctu):
    """ Filter out nondebug macros when requested. """

    if opts.pop('force_debug'):
        # lazy implementation just append an undefine macro at the end
        opts.update({'flags': opts['flags'] + ['-UNDEBUG']})

    return continuation(opts)


@require(['language', 'compiler', 'file', 'flags'])
def language_check(opts, continuation=filter_debug_flags):
    """ Find out the language from command line parameters or file name
    extension. The decision also influenced by the compiler invocation. """

    accepted = frozenset({
        'c', 'c++', 'objective-c', 'objective-c++', 'c-cpp-output',
        'c++-cpp-output', 'objective-c-cpp-output'
    })

    # language can be given as a parameter...
    language = opts.pop('language')
    compiler = opts.pop('compiler')
    # ... or find out from source file extension
    if language is None and compiler is not None:
        language = classify_source(opts['file'], compiler == 'c')

    if language is None:
        logging.debug('skip analysis, language not known')
        return None
    elif language not in accepted:
        logging.debug('skip analysis, language not supported')
        return None
    else:
        logging.debug('analysis, language: %s', language)
        opts.update({'language': language,
                     'flags': ['-x', language] + opts['flags']})
        return continuation(opts)


@require(['arch_list', 'flags'])
def arch_check(opts, continuation=language_check):
    """ Do run analyzer through one of the given architectures. """

    disabled = frozenset({'ppc', 'ppc64'})

    received_list = opts.pop('arch_list')
    if received_list:
        # filter out disabled architectures and -arch switches
        filtered_list = [a for a in received_list if a not in disabled]
        if filtered_list:
            # There should be only one arch given (or the same multiple
            # times). If there are multiple arch are given and are not
            # the same, those should not change the pre-processing step.
            # But that's the only pass we have before run the analyzer.
            current = filtered_list.pop()
            logging.debug('analysis, on arch: %s', current)

            opts.update({'flags': ['-arch', current] + opts['flags']})
            return continuation(opts)
        else:
            logging.debug('skip analysis, found not supported arch')
            return None
    else:
        logging.debug('analysis, on default arch')
        return continuation(opts)


# To have good results from static analyzer certain compiler options shall be
# omitted. The compiler flag filtering only affects the static analyzer run.
#
# Keys are the option name, value number of options to skip
IGNORED_FLAGS = {
    '-c': 0,  # compile option will be overwritten
    '-fsyntax-only': 0,  # static analyzer option will be overwritten
    '-o': 1,  # will set up own output file
    # flags below are inherited from the perl implementation.
    '-g': 0,
    '-save-temps': 0,
    '-install_name': 1,
    '-exported_symbols_list': 1,
    '-current_version': 1,
    '-compatibility_version': 1,
    '-init': 1,
    '-e': 1,
    '-seg1addr': 1,
    '-bundle_loader': 1,
    '-multiply_defined': 1,
    '-sectorder': 3,
    '--param': 1,
    '--serialize-diagnostics': 1
}


def classify_parameters(command):
    """ Prepare compiler flags (filters some and add others) and take out
    language (-x) and architecture (-arch) flags for future processing. """

    result = {
        'flags': [],  # the filtered compiler flags
        'arch_list': [],  # list of architecture flags
        'language': None,  # compilation language, None, if not specified
        'compiler': compiler_language(command)  # 'c' or 'c++'
    }

    # iterate on the compile options
    args = iter(command[1:])
    for arg in args:
        # take arch flags into a separate basket
        if arg == '-arch':
            result['arch_list'].append(next(args))
        # take language
        elif arg == '-x':
            result['language'] = next(args)
        # parameters which looks source file are not flags
        elif re.match(r'^[^-].+', arg) and classify_source(arg):
            pass
        # ignore some flags
        elif arg in IGNORED_FLAGS:
            count = IGNORED_FLAGS[arg]
            for _ in range(count):
                next(args)
        # we don't care about extra warnings, but we should suppress ones
        # that we don't want to see.
        elif re.match(r'^-W.+', arg) and not re.match(r'^-Wno-.+', arg):
            pass
        # and consider everything else as compilation flag.
        else:
            result['flags'].append(arg)

    return result
