Blame math/gen-tgmath-tests.py

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