123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649 |
- #!/usr/bin/python
- # Generate tests for <tgmath.h> macros.
- # Copyright (C) 2017-2019 Free Software Foundation, Inc.
- # This file is part of the GNU C Library.
- #
- # The GNU C Library is free software; you can redistribute it and/or
- # modify it under the terms of the GNU Lesser General Public
- # License as published by the Free Software Foundation; either
- # version 2.1 of the License, or (at your option) any later version.
- #
- # The GNU C Library is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- # Lesser General Public License for more details.
- #
- # You should have received a copy of the GNU Lesser General Public
- # License along with the GNU C Library; if not, see
- # <http://www.gnu.org/licenses/>.
- # As glibc does not support decimal floating point, the types to
- # consider for generic parameters are standard and binary
- # floating-point types, and integer types which are treated as double.
- # The corresponding complex types may also be used (including complex
- # integer types, which are a GNU extension, but are currently disabled
- # here because they do not work properly with tgmath.h).
- # The proposed resolution to TS 18661-1 DR#9
- # <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2149.htm#dr_9>
- # makes the <tgmath.h> rules for selecting a function to call
- # correspond to the usual arithmetic conversions (applied successively
- # to the arguments for generic parameters in order), which choose the
- # type whose set of values contains that of the other type (undefined
- # behavior if neither type's set of values is a superset of the
- # other), with interchange types being preferred to standard types
- # (long double, double, float), being preferred to extended types
- # (_Float128x, _Float64x, _Float32x).
- # For the standard and binary floating-point types supported by GCC 7
- # on any platform, this means the resulting type is the last of the
- # given types in one of the following orders, or undefined behavior if
- # types with both ibm128 and binary128 representation are specified.
- # If double = long double: _Float16, float, _Float32, _Float32x,
- # double, long double, _Float64, _Float64x, _Float128.
- # Otherwise: _Float16, float, _Float32, _Float32x, double, _Float64,
- # _Float64x, long double, _Float128.
- # We generate tests to verify the return type is exactly as expected.
- # We also verify that the function called is real or complex as
- # expected, and that it is called for the right floating-point format
- # (but it is OK to call a double function instead of a long double one
- # if they have the same format, for example). For all the formats
- # supported on any given configuration of glibc, the MANT_DIG value
- # uniquely determines the format.
- import string
- import sys
- class Type(object):
- """A type that may be used as an argument for generic parameters."""
- # All possible argument or result types.
- all_types_list = []
- # All argument types.
- argument_types_list = []
- # All real argument types.
- real_argument_types_list = []
- # Real argument types that correspond to a standard floating type
- # (float, double or long double; not _FloatN or _FloatNx).
- standard_real_argument_types_list = []
- # The real floating types by their order properties (which are
- # tuples giving the positions in both the possible orders above).
- real_types_order = {}
- # The type double.
- double_type = None
- # The type _Complex double.
- complex_double_type = None
- # The type _Float64.
- float64_type = None
- # The type _Float64x.
- float64x_type = None
- def __init__(self, name, suffix=None, mant_dig=None, condition='1',
- order=None, integer=False, complex=False, real_type=None):
- """Initialize a Type object, creating any corresponding complex type
- in the process."""
- self.name = name
- self.suffix = suffix
- self.mant_dig = mant_dig
- self.condition = condition
- self.order = order
- self.integer = integer
- self.complex = complex
- if complex:
- self.complex_type = self
- self.real_type = real_type
- else:
- # complex_type filled in by the caller once created.
- self.complex_type = None
- self.real_type = self
- def register_type(self, internal):
- """Record a type in the lists of all types."""
- Type.all_types_list.append(self)
- if not internal:
- Type.argument_types_list.append(self)
- if not self.complex:
- Type.real_argument_types_list.append(self)
- if not self.name.startswith('_Float'):
- Type.standard_real_argument_types_list.append(self)
- if self.order is not None:
- Type.real_types_order[self.order] = self
- if self.name == 'double':
- Type.double_type = self
- if self.name == '_Complex double':
- Type.complex_double_type = self
- if self.name == '_Float64':
- Type.float64_type = self
- if self.name == '_Float64x':
- Type.float64x_type = self
- @staticmethod
- def create_type(name, suffix=None, mant_dig=None, condition='1', order=None,
- integer=False, complex_name=None, complex_ok=True,
- internal=False):
- """Create and register a Type object for a real type, creating any
- corresponding complex type in the process."""
- real_type = Type(name, suffix=suffix, mant_dig=mant_dig,
- condition=condition, order=order, integer=integer,
- complex=False)
- if complex_ok:
- if complex_name is None:
- complex_name = '_Complex %s' % name
- complex_type = Type(complex_name, condition=condition,
- integer=integer, complex=True,
- real_type=real_type)
- else:
- complex_type = None
- real_type.complex_type = complex_type
- real_type.register_type(internal)
- if complex_type is not None:
- complex_type.register_type(internal)
- def floating_type(self):
- """Return the corresponding floating type."""
- if self.integer:
- return (Type.complex_double_type
- if self.complex
- else Type.double_type)
- else:
- return self
- def real_floating_type(self):
- """Return the corresponding real floating type."""
- return self.real_type.floating_type()
- def __str__(self):
- """Return string representation of a type."""
- return self.name
- @staticmethod
- def init_types():
- """Initialize all the known types."""
- Type.create_type('_Float16', 'f16', 'FLT16_MANT_DIG',
- complex_name='__CFLOAT16',
- condition='defined HUGE_VAL_F16', order=(0, 0))
- Type.create_type('float', 'f', 'FLT_MANT_DIG', order=(1, 1))
- Type.create_type('_Float32', 'f32', 'FLT32_MANT_DIG',
- complex_name='__CFLOAT32',
- condition='defined HUGE_VAL_F32', order=(2, 2))
- Type.create_type('_Float32x', 'f32x', 'FLT32X_MANT_DIG',
- complex_name='__CFLOAT32X',
- condition='defined HUGE_VAL_F32X', order=(3, 3))
- Type.create_type('double', '', 'DBL_MANT_DIG', order=(4, 4))
- Type.create_type('long double', 'l', 'LDBL_MANT_DIG', order=(5, 7))
- Type.create_type('_Float64', 'f64', 'FLT64_MANT_DIG',
- complex_name='__CFLOAT64',
- condition='defined HUGE_VAL_F64', order=(6, 5))
- Type.create_type('_Float64x', 'f64x', 'FLT64X_MANT_DIG',
- complex_name='__CFLOAT64X',
- condition='defined HUGE_VAL_F64X', order=(7, 6))
- Type.create_type('_Float128', 'f128', 'FLT128_MANT_DIG',
- complex_name='__CFLOAT128',
- condition='defined HUGE_VAL_F128', order=(8, 8))
- Type.create_type('char', integer=True)
- Type.create_type('signed char', integer=True)
- Type.create_type('unsigned char', integer=True)
- Type.create_type('short int', integer=True)
- Type.create_type('unsigned short int', integer=True)
- Type.create_type('int', integer=True)
- Type.create_type('unsigned int', integer=True)
- Type.create_type('long int', integer=True)
- Type.create_type('unsigned long int', integer=True)
- Type.create_type('long long int', integer=True)
- Type.create_type('unsigned long long int', integer=True)
- Type.create_type('__int128', integer=True,
- condition='defined __SIZEOF_INT128__')
- Type.create_type('unsigned __int128', integer=True,
- condition='defined __SIZEOF_INT128__')
- Type.create_type('enum e', integer=True, complex_ok=False)
- Type.create_type('_Bool', integer=True, complex_ok=False)
- Type.create_type('bit_field', integer=True, complex_ok=False)
- # Internal types represent the combination of long double with
- # _Float64 or _Float64x, for which the ordering depends on
- # whether long double has the same format as double.
- Type.create_type('long_double_Float64', None, 'LDBL_MANT_DIG',
- complex_name='complex_long_double_Float64',
- condition='defined HUGE_VAL_F64', order=(6, 7),
- internal=True)
- Type.create_type('long_double_Float64x', None, 'FLT64X_MANT_DIG',
- complex_name='complex_long_double_Float64x',
- condition='defined HUGE_VAL_F64X', order=(7, 7),
- internal=True)
- @staticmethod
- def can_combine_types(types):
- """Return a C preprocessor conditional for whether the given list of
- types can be used together as type-generic macro arguments."""
- have_long_double = False
- have_float128 = False
- for t in types:
- t = t.real_floating_type()
- if t.name == 'long double':
- have_long_double = True
- if t.name == '_Float128' or t.name == '_Float64x':
- have_float128 = True
- if have_long_double and have_float128:
- # If ibm128 format is in use for long double, both
- # _Float64x and _Float128 are binary128 and the types
- # cannot be combined.
- return '(LDBL_MANT_DIG != 106)'
- return '1'
- @staticmethod
- def combine_types(types):
- """Return the result of combining a set of types."""
- have_complex = False
- combined = None
- for t in types:
- if t.complex:
- have_complex = True
- t = t.real_floating_type()
- if combined is None:
- combined = t
- else:
- order = (max(combined.order[0], t.order[0]),
- max(combined.order[1], t.order[1]))
- combined = Type.real_types_order[order]
- return combined.complex_type if have_complex else combined
- def list_product_initial(initial, lists):
- """Return a list of lists, with an initial sequence from the first
- argument (a list of lists) followed by each sequence of one
- element from each successive element of the second argument."""
- if not lists:
- return initial
- return list_product_initial([a + [b] for a in initial for b in lists[0]],
- lists[1:])
- def list_product(lists):
- """Return a list of lists, with each sequence of one element from each
- successive element of the argument."""
- return list_product_initial([[]], lists)
- try:
- trans_id = str.maketrans(' *', '_p')
- except AttributeError:
- trans_id = string.maketrans(' *', '_p')
- def var_for_type(name):
- """Return the name of a variable with a given type (name)."""
- return 'var_%s' % name.translate(trans_id)
- def vol_var_for_type(name):
- """Return the name of a variable with a given volatile type (name)."""
- return 'vol_var_%s' % name.translate(trans_id)
- def define_vars_for_type(name):
- """Return the definitions of variables with a given type (name)."""
- if name == 'bit_field':
- struct_vars = define_vars_for_type('struct s');
- return '%s#define %s %s.bf\n' % (struct_vars,
- vol_var_for_type(name),
- vol_var_for_type('struct s'))
- return ('%s %s __attribute__ ((unused));\n'
- '%s volatile %s __attribute__ ((unused));\n'
- % (name, var_for_type(name), name, vol_var_for_type(name)))
- def if_cond_text(conds, text):
- """Return the result of making some text conditional under #if. The
- text ends with a newline, as does the return value if not empty."""
- if '0' in conds:
- return ''
- conds = [c for c in conds if c != '1']
- conds = sorted(set(conds))
- if not conds:
- return text
- return '#if %s\n%s#endif\n' % (' && '.join(conds), text)
- class Tests(object):
- """The state associated with testcase generation."""
- def __init__(self):
- """Initialize a Tests object."""
- self.header_list = ['#define __STDC_WANT_IEC_60559_TYPES_EXT__\n'
- '#include <float.h>\n'
- '#include <stdbool.h>\n'
- '#include <stdint.h>\n'
- '#include <stdio.h>\n'
- '#include <string.h>\n'
- '#include <tgmath.h>\n'
- '\n'
- 'struct test\n'
- ' {\n'
- ' void (*func) (void);\n'
- ' const char *func_name;\n'
- ' const char *test_name;\n'
- ' int mant_dig;\n'
- ' };\n'
- 'int num_pass, num_fail;\n'
- 'volatile int called_mant_dig;\n'
- 'const char *volatile called_func_name;\n'
- 'enum e { E, F };\n'
- 'struct s\n'
- ' {\n'
- ' int bf:2;\n'
- ' };\n']
- float64_text = ('# if LDBL_MANT_DIG == DBL_MANT_DIG\n'
- 'typedef _Float64 long_double_Float64;\n'
- 'typedef __CFLOAT64 complex_long_double_Float64;\n'
- '# else\n'
- 'typedef long double long_double_Float64;\n'
- 'typedef _Complex long double '
- 'complex_long_double_Float64;\n'
- '# endif\n')
- float64_text = if_cond_text([Type.float64_type.condition],
- float64_text)
- float64x_text = ('# if LDBL_MANT_DIG == DBL_MANT_DIG\n'
- 'typedef _Float64x long_double_Float64x;\n'
- 'typedef __CFLOAT64X complex_long_double_Float64x;\n'
- '# else\n'
- 'typedef long double long_double_Float64x;\n'
- 'typedef _Complex long double '
- 'complex_long_double_Float64x;\n'
- '# endif\n')
- float64x_text = if_cond_text([Type.float64x_type.condition],
- float64x_text)
- self.header_list.append(float64_text)
- self.header_list.append(float64x_text)
- self.types_seen = set()
- for t in Type.all_types_list:
- self.add_type_var(t.name, t.condition)
- self.test_text_list = []
- self.test_array_list = []
- self.macros_seen = set()
- def add_type_var(self, name, cond):
- """Add declarations of variables for a type."""
- if name in self.types_seen:
- return
- t_vars = define_vars_for_type(name)
- self.header_list.append(if_cond_text([cond], t_vars))
- self.types_seen.add(name)
- def add_tests(self, macro, ret, args, complex_func=None):
- """Add tests for a given tgmath.h macro, if that is the macro for
- which tests are to be generated; otherwise just add it to the
- list of macros for which test generation is supported."""
- # 'c' means the function argument or return type is
- # type-generic and complex only (a complex function argument
- # may still have a real macro argument). 'g' means it is
- # type-generic and may be real or complex; 'r' means it is
- # type-generic and may only be real; 's' means the same as
- # 'r', but restricted to float, double and long double.
- self.macros_seen.add(macro)
- if macro != self.macro:
- return
- have_complex = False
- func = macro
- if ret == 'c' or 'c' in args:
- # Complex-only.
- have_complex = True
- complex_func = func
- func = None
- elif ret == 'g' or 'g' in args:
- # Real and complex.
- have_complex = True
- if complex_func == None:
- complex_func = 'c%s' % func
- types = [ret] + args
- for t in types:
- if t != 'c' and t != 'g' and t != 'r' and t != 's':
- self.add_type_var(t, '1')
- for t in Type.argument_types_list:
- if t.integer:
- continue
- if t.complex and not have_complex:
- continue
- if func == None and not t.complex:
- continue
- if ret == 's' and t.name.startswith('_Float'):
- continue
- if ret == 'c':
- ret_name = t.complex_type.name
- elif ret == 'g':
- ret_name = t.name
- elif ret == 'r' or ret == 's':
- ret_name = t.real_type.name
- else:
- ret_name = ret
- dummy_func_name = complex_func if t.complex else func
- arg_list = []
- arg_num = 0
- for a in args:
- if a == 'c':
- arg_name = t.complex_type.name
- elif a == 'g':
- arg_name = t.name
- elif a == 'r' or a == 's':
- arg_name = t.real_type.name
- else:
- arg_name = a
- arg_list.append('%s arg%d __attribute__ ((unused))'
- % (arg_name, arg_num))
- arg_num += 1
- dummy_func = ('%s\n'
- '(%s%s) (%s)\n'
- '{\n'
- ' called_mant_dig = %s;\n'
- ' called_func_name = "%s";\n'
- ' return 0;\n'
- '}\n' % (ret_name, dummy_func_name,
- t.real_type.suffix, ', '.join(arg_list),
- t.real_type.mant_dig, dummy_func_name))
- dummy_func = if_cond_text([t.condition], dummy_func)
- self.test_text_list.append(dummy_func)
- arg_types = []
- for t in args:
- if t == 'g' or t == 'c':
- arg_types.append(Type.argument_types_list)
- elif t == 'r':
- arg_types.append(Type.real_argument_types_list)
- elif t == 's':
- arg_types.append(Type.standard_real_argument_types_list)
- arg_types_product = list_product(arg_types)
- test_num = 0
- for this_args in arg_types_product:
- comb_type = Type.combine_types(this_args)
- can_comb = Type.can_combine_types(this_args)
- all_conds = [t.condition for t in this_args]
- all_conds.append(can_comb)
- any_complex = func == None
- for t in this_args:
- if t.complex:
- any_complex = True
- func_name = complex_func if any_complex else func
- test_name = '%s (%s)' % (macro,
- ', '.join([t.name for t in this_args]))
- test_func_name = 'test_%s_%d' % (macro, test_num)
- test_num += 1
- mant_dig = comb_type.real_type.mant_dig
- test_text = '%s, "%s", "%s", %s' % (test_func_name, func_name,
- test_name, mant_dig)
- test_text = ' { %s },\n' % test_text
- test_text = if_cond_text(all_conds, test_text)
- self.test_array_list.append(test_text)
- call_args = []
- call_arg_pos = 0
- for t in args:
- if t == 'g' or t == 'c' or t == 'r' or t == 's':
- type = this_args[call_arg_pos].name
- call_arg_pos += 1
- else:
- type = t
- call_args.append(vol_var_for_type(type))
- call_args_text = ', '.join(call_args)
- if ret == 'g':
- ret_type = comb_type.name
- elif ret == 'r' or ret == 's':
- ret_type = comb_type.real_type.name
- elif ret == 'c':
- ret_type = comb_type.complex_type.name
- else:
- ret_type = ret
- call_text = '%s (%s)' % (macro, call_args_text)
- test_func_text = ('static void\n'
- '%s (void)\n'
- '{\n'
- ' extern typeof (%s) %s '
- '__attribute__ ((unused));\n'
- ' %s = %s;\n'
- '}\n' % (test_func_name, call_text,
- var_for_type(ret_type),
- vol_var_for_type(ret_type), call_text))
- test_func_text = if_cond_text(all_conds, test_func_text)
- self.test_text_list.append(test_func_text)
- def add_all_tests(self, macro):
- """Add tests for the given tgmath.h macro, if any, and generate the
- list of all supported macros."""
- self.macro = macro
- # C99/C11 real-only functions.
- self.add_tests('atan2', 'r', ['r', 'r'])
- self.add_tests('cbrt', 'r', ['r'])
- self.add_tests('ceil', 'r', ['r'])
- self.add_tests('copysign', 'r', ['r', 'r'])
- self.add_tests('erf', 'r', ['r'])
- self.add_tests('erfc', 'r', ['r'])
- self.add_tests('exp2', 'r', ['r'])
- self.add_tests('expm1', 'r', ['r'])
- self.add_tests('fdim', 'r', ['r', 'r'])
- self.add_tests('floor', 'r', ['r'])
- self.add_tests('fma', 'r', ['r', 'r', 'r'])
- self.add_tests('fmax', 'r', ['r', 'r'])
- self.add_tests('fmin', 'r', ['r', 'r'])
- self.add_tests('fmod', 'r', ['r', 'r'])
- self.add_tests('frexp', 'r', ['r', 'int *'])
- self.add_tests('hypot', 'r', ['r', 'r'])
- self.add_tests('ilogb', 'int', ['r'])
- self.add_tests('ldexp', 'r', ['r', 'int'])
- self.add_tests('lgamma', 'r', ['r'])
- self.add_tests('llrint', 'long long int', ['r'])
- self.add_tests('llround', 'long long int', ['r'])
- # log10 is real-only in ISO C, but supports complex arguments
- # as a GNU extension.
- self.add_tests('log10', 'g', ['g'])
- self.add_tests('log1p', 'r', ['r'])
- self.add_tests('log2', 'r', ['r'])
- self.add_tests('logb', 'r', ['r'])
- self.add_tests('lrint', 'long int', ['r'])
- self.add_tests('lround', 'long int', ['r'])
- self.add_tests('nearbyint', 'r', ['r'])
- self.add_tests('nextafter', 'r', ['r', 'r'])
- self.add_tests('nexttoward', 's', ['s', 'long double'])
- self.add_tests('remainder', 'r', ['r', 'r'])
- self.add_tests('remquo', 'r', ['r', 'r', 'int *'])
- self.add_tests('rint', 'r', ['r'])
- self.add_tests('round', 'r', ['r'])
- self.add_tests('scalbn', 'r', ['r', 'int'])
- self.add_tests('scalbln', 'r', ['r', 'long int'])
- self.add_tests('tgamma', 'r', ['r'])
- self.add_tests('trunc', 'r', ['r'])
- # C99/C11 real-and-complex functions.
- self.add_tests('acos', 'g', ['g'])
- self.add_tests('asin', 'g', ['g'])
- self.add_tests('atan', 'g', ['g'])
- self.add_tests('acosh', 'g', ['g'])
- self.add_tests('asinh', 'g', ['g'])
- self.add_tests('atanh', 'g', ['g'])
- self.add_tests('cos', 'g', ['g'])
- self.add_tests('sin', 'g', ['g'])
- self.add_tests('tan', 'g', ['g'])
- self.add_tests('cosh', 'g', ['g'])
- self.add_tests('sinh', 'g', ['g'])
- self.add_tests('tanh', 'g', ['g'])
- self.add_tests('exp', 'g', ['g'])
- self.add_tests('log', 'g', ['g'])
- self.add_tests('pow', 'g', ['g', 'g'])
- self.add_tests('sqrt', 'g', ['g'])
- self.add_tests('fabs', 'r', ['g'], 'cabs')
- # C99/C11 complex-only functions.
- self.add_tests('carg', 'r', ['c'])
- self.add_tests('cimag', 'r', ['c'])
- self.add_tests('conj', 'c', ['c'])
- self.add_tests('cproj', 'c', ['c'])
- self.add_tests('creal', 'r', ['c'])
- # TS 18661-1 functions.
- self.add_tests('roundeven', 'r', ['r'])
- self.add_tests('nextup', 'r', ['r'])
- self.add_tests('nextdown', 'r', ['r'])
- self.add_tests('fminmag', 'r', ['r', 'r'])
- self.add_tests('fmaxmag', 'r', ['r', 'r'])
- self.add_tests('llogb', 'long int', ['r'])
- self.add_tests('fromfp', 'intmax_t', ['r', 'int', 'unsigned int'])
- self.add_tests('fromfpx', 'intmax_t', ['r', 'int', 'unsigned int'])
- self.add_tests('ufromfp', 'uintmax_t', ['r', 'int', 'unsigned int'])
- self.add_tests('ufromfpx', 'uintmax_t', ['r', 'int', 'unsigned int'])
- self.add_tests('totalorder', 'int', ['r', 'r'])
- self.add_tests('totalordermag', 'int', ['r', 'r'])
- # The functions that round their result to a narrower type,
- # and the associated type-generic macros, are not yet
- # supported by this script or by glibc.
- # Miscellaneous functions.
- self.add_tests('scalb', 's', ['s', 's'])
- def tests_text(self):
- """Return the text of the generated testcase."""
- test_list = [''.join(self.test_text_list),
- 'static const struct test tests[] =\n'
- ' {\n',
- ''.join(self.test_array_list),
- ' };\n']
- footer_list = ['static int\n'
- 'do_test (void)\n'
- '{\n'
- ' for (size_t i = 0;\n'
- ' i < sizeof (tests) / sizeof (tests[0]);\n'
- ' i++)\n'
- ' {\n'
- ' called_mant_dig = 0;\n'
- ' called_func_name = "";\n'
- ' tests[i].func ();\n'
- ' if (called_mant_dig == tests[i].mant_dig\n'
- ' && strcmp (called_func_name,\n'
- ' tests[i].func_name) == 0)\n'
- ' num_pass++;\n'
- ' else\n'
- ' {\n'
- ' num_fail++;\n'
- ' printf ("Test %zu (%s):\\n"\n'
- ' " Expected: %s precision %d\\n"\n'
- ' " Actual: %s precision %d\\n\\n",\n'
- ' i, tests[i].test_name,\n'
- ' tests[i].func_name,\n'
- ' tests[i].mant_dig,\n'
- ' called_func_name, called_mant_dig);\n'
- ' }\n'
- ' }\n'
- ' printf ("%d pass, %d fail\\n", num_pass, num_fail);\n'
- ' return num_fail != 0;\n'
- '}\n'
- '\n'
- '#include <support/test-driver.c>']
- return ''.join(self.header_list + test_list + footer_list)
- def check_macro_list(self, macro_list):
- """Check the list of macros that can be tested."""
- if self.macros_seen != set(macro_list):
- print('error: macro list mismatch')
- sys.exit(1)
- def main():
- """The main entry point."""
- Type.init_types()
- t = Tests()
- if sys.argv[1] == 'check-list':
- macro = None
- macro_list = sys.argv[2:]
- else:
- macro = sys.argv[1]
- macro_list = []
- t.add_all_tests(macro)
- if macro:
- print(t.tests_text())
- else:
- t.check_macro_list(macro_list)
- if __name__ == '__main__':
- main()
|