import os
import platform
import subprocess
import sys
import tempfile
def remove_file_if_exists(filename):
if not filename:
return
try:
os.remove(filename)
except OSError:
pass
def create_c_file(file_label):
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):
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):
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,
):
if include_path is None:
include_path = []
c_name = None
exe_name = None
obj_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')
cmd = [cc]
proc = subprocess.Popen(cmd,
stdout=subprocess.DEVNULL,
stderr=subprocess.PIPE,
universal_newlines=True)
cc_is_msvc = 'Microsoft (R) C/C++ Optimizing Compiler' in \
proc.communicate()[1]
cmd += ['-I' + dir for dir in include_path]
if cc_is_msvc:
obj_name = exe_name[:-4] + '.obj'
cmd += ['-Fe' + exe_name, '-Fo' + obj_name]
else:
cmd += ['-o' + exe_name]
subprocess.check_call(cmd + [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)
remove_file_if_exists(obj_name)