forked from Mbed-TLS/mbedtls
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move get_c_expression_values into a separate module
Create a directory mbedtls_dev intended to contain various Python module for use by Python scripts located anywhere in the Mbed TLS source tree. Move get_c_expression_values and its auxiliary functions into a new Python module mbedtls_dev.c_build_helper. Signed-off-by: Gilles Peskine <[email protected]>
- Loading branch information
1 parent
fc62211
commit 2adebc8
Showing
2 changed files
with
142 additions
and
118 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
"""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 | ||
``type``. | ||
* ``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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters