"""Generate and run C code.
"""

# Copyright The Mbed TLS Contributors
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
import platform
import subprocess
import sys
import tempfile

def remove_file_if_exists(filename):
    """Remove the specified file, ignoring errors."""
    if not filename:
        return
    try:
        os.remove(filename)
    except OSError:
        pass

def create_c_file(file_label):
    """Create a temporary C file.

    * ``file_label``: a string that will be included in the file name.

    Return ```(c_file, c_name, exe_name)``` where ``c_file`` is a Python
    stream open for writing to the file, ``c_name`` is the name of the file
    and ``exe_name`` is the name of the executable that will be produced
    by compiling the file.
    """
    c_fd, c_name = tempfile.mkstemp(prefix='tmp-{}-'.format(file_label),
                                    suffix='.c')
    exe_suffix = '.exe' if platform.system() == 'Windows' else ''
    exe_name = c_name[:-2] + exe_suffix
    remove_file_if_exists(exe_name)
    c_file = os.fdopen(c_fd, 'w', encoding='ascii')
    return c_file, c_name, exe_name

def generate_c_printf_expressions(c_file, cast_to, printf_format, expressions):
    """Generate C instructions to print the value of ``expressions``.

    Write the code with ``c_file``'s ``write`` method.

    Each expression is cast to the type ``cast_to`` and printed with the
    printf format ``printf_format``.
    """
    for expr in expressions:
        c_file.write('    printf("{}\\n", ({}) {});\n'
                     .format(printf_format, cast_to, expr))

def generate_c_file(c_file,
                    caller, header,
                    main_generator):
    """Generate a temporary C source file.

    * ``c_file`` is an open stream on the C source file.
    * ``caller``: an informational string written in a comment at the top
      of the file.
    * ``header``: extra code to insert before any function in the generated
      C file.
    * ``main_generator``: a function called with ``c_file`` as its sole argument
      to generate the body of the ``main()`` function.
    """
    c_file.write('/* Generated by {} */'
                 .format(caller))
    c_file.write('''
#include <stdio.h>
''')
    c_file.write(header)
    c_file.write('''
int main(void)
{
''')
    main_generator(c_file)
    c_file.write('''    return 0;
}
''')

def get_c_expression_values(
        cast_to, printf_format,
        expressions,
        caller=__name__, file_label='',
        header='', include_path=None,
        keep_c=False,
): # pylint: disable=too-many-arguments
    """Generate and run a program to print out numerical values for expressions.

    * ``cast_to``: a C type.
    * ``printf_format``: a printf format suitable for the type ``cast_to``.
    * ``header``: extra code to insert before any function in the generated
      C file.
    * ``expressions``: a list of C language expressions that have the type
      ``cast_to``.
    * ``include_path``: a list of directories containing header files.
    * ``keep_c``: if true, keep the temporary C file (presumably for debugging
      purposes).

    Return the list of values of the ``expressions``.
    """
    if include_path is None:
        include_path = []
    c_name = None
    exe_name = None
    try:
        c_file, c_name, exe_name = create_c_file(file_label)
        generate_c_file(
            c_file, caller, header,
            lambda c_file: generate_c_printf_expressions(c_file,
                                                         cast_to, printf_format,
                                                         expressions)
        )
        c_file.close()
        cc = os.getenv('CC', 'cc')
        subprocess.check_call([cc] +
                              ['-I' + dir for dir in include_path] +
                              ['-o', exe_name, c_name])
        if keep_c:
            sys.stderr.write('List of {} tests kept at {}\n'
                             .format(caller, c_name))
        else:
            os.remove(c_name)
        output = subprocess.check_output([exe_name])
        return output.decode('ascii').strip().split('\n')
    finally:
        remove_file_if_exists(exe_name)
