# -*- coding: utf-8 -*-
#                     The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
""" 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
from libscanbuild.shell import decode

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

COMPILER_WRAPPER_CC = 'analyze-cc'
COMPILER_WRAPPER_CXX = 'analyze-c++'

CTU_FUNCTION_MAP_FILENAME = 'externalFnMap.txt'
CTU_TEMP_FNMAP_FOLDER = 'tmpExternalFnMaps'


@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) 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) 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('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,
                  func_map_cmd=args.func_map_cmd)
        if hasattr(args, 'ctu_phases') and hasattr(args.ctu_phases, 'dir')
        else CtuConfig(collect=False, analyze=False, dir='', func_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],
                     func_map_cmd=ctu_config[3])


def create_global_ctu_function_map(func_map_lines):
    """ Takes iterator of individual function maps and creates a global map
    keeping only unique names. We leave conflicting names out of CTU.

    :param func_map_lines: Contains the id of a function (mangled name) and
    the originating source (the corresponding AST file) name.
    :type func_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 func_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_func_maps(ctudir):
    """ Merge individual function 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_FNMAP_FOLDER.
    These function maps contain the mangled names of functions and the source
    (AST generated from the source) which had them.
    These files should be merged at the end into a global map file:
    CTU_FUNCTION_MAP_FILENAME."""

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

        files = glob.glob(os.path.join(fnmap_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 function name, ast file) pairs into final file. """

        extern_fns_map_file = os.path.join(ctudir, arch,
                                           CTU_FUNCTION_MAP_FILENAME)
        with open(extern_fns_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)
            fnmap_dir = os.path.join(ctudir, triple_arch,
                                     CTU_TEMP_FNMAP_FOLDER)

            func_map_lines = generate_func_map_lines(fnmap_dir)
            mangled_ast_pairs = create_global_ctu_function_map(func_map_lines)
            write_global_map(triple_arch, mangled_ast_pairs)

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


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

    def exclude(filename):
        """ Return true when any excluded directory prefix the filename. """
        return any(re.match(r'^' + directory, filename)
                   for 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']))
        # 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 func_map_cmd,
        # so we can leave it empty
        args.ctu_phases = CtuConfig(collect=True, analyze=False,
                                    dir='', func_map_cmd='')
        run_analyzer_parallel(args)
        merge_ctu_func_maps(ctu_config.dir)
        args.ctu_phases = CtuConfig(collect=False, analyze=True,
                                    dir='', func_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_func_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):
    """ 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:
        if os.listdir(name):
            msg = "Run 'scan-view %s' to examine bug reports."
            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, name)

        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.store_model:
        result.append('-analyzer-store={0}'.format(args.store_model))
    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', both or plist-multi-file
          '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 analyzis 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 analyzis.", 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 = get_arguments(
        [opts['clang'], '-fsyntax-only', '-E'
         ] + opts['flags'] + [opts['file'], '-o', name], cwd)
    run_command(cmd, cwd=cwd)
    # 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
        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


def func_map_list_src_to_ast(func_src_list):
    """ Turns textual function map list with source files into a
    function map list with ast files. """

    func_ast_list = []
    for fn_src_txt in func_src_list:
        mangled_name, path = fn_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")
        func_ast_list.append(mangled_name + " " + ast_path)
    return func_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_functions(triple_arch):
        """ Generate function map file for the current source. """

        args = opts['direct_args'] + opts['flags']
        funcmap_command = [opts['ctu'].func_map_cmd]
        funcmap_command.append(opts['file'])
        funcmap_command.append('--')
        funcmap_command.extend(args)
        logging.debug("Generating function map using '%s'", funcmap_command)
        func_src_list = run_command(funcmap_command, cwd=opts['directory'])
        func_ast_list = func_map_list_src_to_ast(func_src_list)
        extern_fns_map_folder = os.path.join(opts['ctu'].dir, triple_arch,
                                             CTU_TEMP_FNMAP_FOLDER)
        if not os.path.isdir(extern_fns_map_folder):
            try:
                os.makedirs(extern_fns_map_folder)
            except OSError:
                # In case an other process already created it.
                pass
        if func_ast_list:
            with tempfile.NamedTemporaryFile(mode='w',
                                             dir=extern_fns_map_folder,
                                             delete=False) as out_file:
                out_file.write("\n".join(func_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_functions(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
