• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (C) 2002-2004, 2006-2018 Free Software Foundation, Inc.
2# This file is free software; the Free Software Foundation
3# gives unlimited permission to copy and/or distribute it,
4# with or without modifications, as long as this notice is preserved.
5
6# Test whether the *printf family of functions supports infinite and NaN
7# 'long double' arguments in the %f, %e, %g directives. (ISO C99, POSIX:2001)
8# Result is gl_cv_func_printf_infinite_long_double.
9
10# The user can set or unset the variable gl_printf_safe to indicate
11# that he wishes a safe handling of non-IEEE-754 'long double' values.
12check_print_safe = ''
13if get_variable ('gl_printf_safe', false)
14  check_print_safe = '''
15#if ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_)) && !HAVE_SAME_LONG_DOUBLE_AS_DOUBLE
16/* Representation of an 80-bit 'long double' as an initializer for a sequence
17   of 'unsigned int' words.  */
18# ifdef WORDS_BIGENDIAN
19#  define LDBL80_WORDS(exponent,manthi,mantlo) \
20     { ((unsigned int) (exponent) << 16) | ((unsigned int) (manthi) >> 16), \
21       ((unsigned int) (manthi) << 16) | ((unsigned int) (mantlo) >> 16),   \
22       (unsigned int) (mantlo) << 16                                        \
23     }
24# else
25#  define LDBL80_WORDS(exponent,manthi,mantlo) \
26     { mantlo, manthi, exponent }
27# endif
28  { /* Quiet NaN.  */
29    static union { unsigned int word[4]; long double value; } x =
30      { LDBL80_WORDS (0xFFFF, 0xC3333333, 0x00000000) };
31    if (sprintf (buf, "%Lf", x.value) < 0
32        || !strisnan (buf, 0, strlen (buf)))
33      result |= 2;
34    if (sprintf (buf, "%Le", x.value) < 0
35        || !strisnan (buf, 0, strlen (buf)))
36      result |= 2;
37    if (sprintf (buf, "%Lg", x.value) < 0
38        || !strisnan (buf, 0, strlen (buf)))
39      result |= 2;
40  }
41  {
42    /* Signalling NaN.  */
43    static union { unsigned int word[4]; long double value; } x =
44      { LDBL80_WORDS (0xFFFF, 0x83333333, 0x00000000) };
45    if (sprintf (buf, "%Lf", x.value) < 0
46        || !strisnan (buf, 0, strlen (buf)))
47      result |= 2;
48    if (sprintf (buf, "%Le", x.value) < 0
49        || !strisnan (buf, 0, strlen (buf)))
50      result |= 2;
51    if (sprintf (buf, "%Lg", x.value) < 0
52        || !strisnan (buf, 0, strlen (buf)))
53      result |= 2;
54  }
55  { /* Pseudo-NaN.  */
56    static union { unsigned int word[4]; long double value; } x =
57      { LDBL80_WORDS (0xFFFF, 0x40000001, 0x00000000) };
58    if (sprintf (buf, "%Lf", x.value) <= 0)
59      result |= 4;
60    if (sprintf (buf, "%Le", x.value) <= 0)
61      result |= 4;
62    if (sprintf (buf, "%Lg", x.value) <= 0)
63      result |= 4;
64  }
65  { /* Pseudo-Infinity.  */
66    static union { unsigned int word[4]; long double value; } x =
67      { LDBL80_WORDS (0xFFFF, 0x00000000, 0x00000000) };
68    if (sprintf (buf, "%Lf", x.value) <= 0)
69      result |= 8;
70    if (sprintf (buf, "%Le", x.value) <= 0)
71      result |= 8;
72    if (sprintf (buf, "%Lg", x.value) <= 0)
73      result |= 8;
74  }
75  { /* Pseudo-Zero.  */
76    static union { unsigned int word[4]; long double value; } x =
77      { LDBL80_WORDS (0x4004, 0x00000000, 0x00000000) };
78    if (sprintf (buf, "%Lf", x.value) <= 0)
79      result |= 16;
80    if (sprintf (buf, "%Le", x.value) <= 0)
81      result |= 16;
82    if (sprintf (buf, "%Lg", x.value) <= 0)
83      result |= 16;
84  }
85  { /* Unnormalized number.  */
86    static union { unsigned int word[4]; long double value; } x =
87      { LDBL80_WORDS (0x4000, 0x63333333, 0x00000000) };
88    if (sprintf (buf, "%Lf", x.value) <= 0)
89      result |= 32;
90    if (sprintf (buf, "%Le", x.value) <= 0)
91      result |= 32;
92    if (sprintf (buf, "%Lg", x.value) <= 0)
93      result |= 32;
94  }
95  { /* Pseudo-Denormal.  */
96    static union { unsigned int word[4]; long double value; } x =
97      { LDBL80_WORDS (0x0000, 0x83333333, 0x00000000) };
98    if (sprintf (buf, "%Lf", x.value) <= 0)
99      result |= 64;
100    if (sprintf (buf, "%Le", x.value) <= 0)
101      result |= 64;
102    if (sprintf (buf, "%Lg", x.value) <= 0)
103      result |= 64;
104  }
105#endif
106  '''
107endif
108
109printf_infinite_long_double_test = '''
110#include <float.h>
111#include <stdio.h>
112#include <string.h>
113static int
114strisnan (const char *string, size_t start_index, size_t end_index)
115{
116  if (start_index < end_index)
117    {
118      if (string[start_index] == '-')
119        start_index++;
120      if (start_index + 3 <= end_index
121          && memcmp (string + start_index, "nan", 3) == 0)
122        {
123          start_index += 3;
124          if (start_index == end_index
125              || (string[start_index] == '(' && string[end_index - 1] == ')'))
126            return 1;
127        }
128    }
129  return 0;
130}
131static char buf[10000];
132static long double zeroL = 0.0L;
133int main ()
134{
135  int result = 0;
136  nocrash_init();
137  if (sprintf (buf, "%Lf", 1.0L / zeroL) < 0
138      || (strcmp (buf, "inf") != 0 && strcmp (buf, "infinity") != 0))
139    result |= 1;
140  if (sprintf (buf, "%Lf", -1.0L / zeroL) < 0
141      || (strcmp (buf, "-inf") != 0 && strcmp (buf, "-infinity") != 0))
142    result |= 1;
143  if (sprintf (buf, "%Lf", zeroL / zeroL) < 0
144      || !strisnan (buf, 0, strlen (buf)))
145    result |= 1;
146  if (sprintf (buf, "%Le", 1.0L / zeroL) < 0
147      || (strcmp (buf, "inf") != 0 && strcmp (buf, "infinity") != 0))
148    result |= 1;
149  if (sprintf (buf, "%Le", -1.0L / zeroL) < 0
150      || (strcmp (buf, "-inf") != 0 && strcmp (buf, "-infinity") != 0))
151    result |= 1;
152  if (sprintf (buf, "%Le", zeroL / zeroL) < 0
153      || !strisnan (buf, 0, strlen (buf)))
154    result |= 1;
155  if (sprintf (buf, "%Lg", 1.0L / zeroL) < 0
156      || (strcmp (buf, "inf") != 0 && strcmp (buf, "infinity") != 0))
157    result |= 1;
158  if (sprintf (buf, "%Lg", -1.0L / zeroL) < 0
159      || (strcmp (buf, "-inf") != 0 && strcmp (buf, "-infinity") != 0))
160    result |= 1;
161  if (sprintf (buf, "%Lg", zeroL / zeroL) < 0
162      || !strisnan (buf, 0, strlen (buf)))
163    result |= 1;
164''' + check_print_safe + '''
165  return result;
166}
167'''
168
169if gl_cv_func_printf_long_double
170  if not meson.is_cross_build() or meson.has_exe_wrapper()
171    run_result = cc.run(printf_infinite_long_double_test,
172        name : 'printf supports infinite \'long double\' arguments')
173    gl_cv_func_printf_infinite_long_double = (run_result.compiled() and run_result.returncode() == 0)
174  else
175    if host_machine.cpu_family() == 'x86_64'
176      gl_cv_func_printf_infinite_long_double = false
177    else
178      if host_system in ['linux', 'android']
179        gl_cv_func_printf_infinite_long_double = true
180      elif (host_system.startswith ('freebsd1') or
181            host_system.startswith ('freebsd2') or
182            host_system.startswith ('freebsd3') or
183            host_system.startswith ('freebsd4') or
184            host_system.startswith ('freebsd5'))
185        gl_cv_func_printf_infinite_long_double = false
186      elif (host_system.startswith ('freebsd') or
187            host_system.startswith ('kfreebsd'))
188        gl_cv_func_printf_infinite_long_double = true
189      elif (host_system.startswith ('hpux7') or
190            host_system.startswith ('hpux8') or
191            host_system.startswith ('hpux9') or
192            host_system.startswith ('hpux10'))
193        gl_cv_func_printf_infinite = false
194      elif host_system.startswith ('hpux')
195        gl_cv_func_printf_infinite_long_double = true
196      elif host_system == 'windows'
197        # Guess yes on MSVC, no on mingw.
198        if cc.get_id() == 'msvc' or cc.get_id() == 'clang-cl'
199          gl_cv_func_printf_infinite_long_double = true
200        else
201          gl_cv_func_printf_infinite_long_double = false
202        endif
203      else
204        gl_cv_func_printf_infinite_long_double = false
205      endif
206    endif
207  endif
208endif
209