]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Refactor strtod parsing of NaN payloads.
authorJoseph Myers <joseph@codesourcery.com>
Tue, 24 Nov 2015 22:24:52 +0000 (22:24 +0000)
committerJoseph Myers <joseph@codesourcery.com>
Tue, 24 Nov 2015 22:24:52 +0000 (22:24 +0000)
The nan* functions handle their string argument by constructing a
NAN(...) string on the stack as a VLA and passing it to strtod
functions.

This approach has problems discussed in bug 16961 and bug 16962: the
stack usage is unbounded, and it gives incorrect results in certain
cases where the argument is not a valid n-char-sequence.

The natural fix for both issues is to refactor the NaN payload parsing
out of strtod into a separate function that the nan* functions can
call directly, so that no temporary string needs constructing on the
stack at all.  This patch does that refactoring in preparation for
fixing those bugs (but without actually using the new functions from
nan* - which will also require exporting them from libc at version
GLIBC_PRIVATE).  This patch is not intended to change any user-visible
behavior, so no tests are added (fixes for the above bugs will of
course add tests for them).

This patch builds on my recent fixes for strtol and strtod issues in
Turkish locales.  Given those fixes, the parsing of NaN payloads is
locale-independent; thus, the new functions do not need to take a
locale_t argument.

Tested for x86_64, x86, mips64 and powerpc.

* stdlib/strtod_nan.c: New file.
* stdlib/strtod_nan_double.h: Likewise.
* stdlib/strtod_nan_float.h: Likewise.
* stdlib/strtod_nan_main.c: Likewise.
* stdlib/strtod_nan_narrow.h: Likewise.
* stdlib/strtod_nan_wide.h: Likewise.
* stdlib/strtof_nan.c: Likewise.
* stdlib/strtold_nan.c: Likewise.
* sysdeps/ieee754/ldbl-128/strtod_nan_ldouble.h: Likewise.
* sysdeps/ieee754/ldbl-128ibm/strtod_nan_ldouble.h: Likewise.
* sysdeps/ieee754/ldbl-96/strtod_nan_ldouble.h: Likewise.
* wcsmbs/wcstod_nan.c: Likewise.
* wcsmbs/wcstof_nan.c: Likewise.
* wcsmbs/wcstold_nan.c: Likewise.
* stdlib/Makefile (routines): Add strtof_nan, strtod_nan and
strtold_nan.
* wcsmbs/Makefile (routines): Add wcstod_nan, wcstold_nan and
wcstof_nan.
* include/stdlib.h (__strtof_nan): Declare and use
libc_hidden_proto.
(__strtod_nan): Likewise.
(__strtold_nan): Likewise.
(__wcstof_nan): Likewise.
(__wcstod_nan): Likewise.
(__wcstold_nan): Likewise.
* include/wchar.h (____wcstoull_l_internal): Declare.
* stdlib/strtod_l.c: Do not include <ieee754.h>.
(____strtoull_l_internal): Remove declaration.
(STRTOF_NAN): Define macro.
(SET_MANTISSA): Remove macro.
(STRTOULL): Likewise.
(____STRTOF_INTERNAL): Use STRTOF_NAN to parse NaN payload.
* stdlib/strtof_l.c (____strtoull_l_internal): Remove declaration.
(STRTOF_NAN): Define macro.
(SET_MANTISSA): Remove macro.
* sysdeps/ieee754/ldbl-128/strtold_l.c (STRTOF_NAN): Define macro.
(SET_MANTISSA): Remove macro.
* sysdeps/ieee754/ldbl-128ibm/strtold_l.c (STRTOF_NAN): Define
macro.
(SET_MANTISSA): Remove macro.
* sysdeps/ieee754/ldbl-64-128/strtold_l.c (STRTOF_NAN): Define
macro.
(SET_MANTISSA): Remove macro.
* sysdeps/ieee754/ldbl-96/strtold_l.c (STRTOF_NAN): Define macro.
(SET_MANTISSA): Remove macro.
* wcsmbs/wcstod_l.c (____wcstoull_l_internal): Remove declaration.
* wcsmbs/wcstof_l.c (____wcstoull_l_internal): Likewise.
* wcsmbs/wcstold_l.c (____wcstoull_l_internal): Likewise.

28 files changed:
ChangeLog
include/stdlib.h
include/wchar.h
stdlib/Makefile
stdlib/strtod_l.c
stdlib/strtod_nan.c [new file with mode: 0644]
stdlib/strtod_nan_double.h [new file with mode: 0644]
stdlib/strtod_nan_float.h [new file with mode: 0644]
stdlib/strtod_nan_main.c [new file with mode: 0644]
stdlib/strtod_nan_narrow.h [new file with mode: 0644]
stdlib/strtod_nan_wide.h [new file with mode: 0644]
stdlib/strtof_l.c
stdlib/strtof_nan.c [new file with mode: 0644]
stdlib/strtold_nan.c [new file with mode: 0644]
sysdeps/ieee754/ldbl-128/strtod_nan_ldouble.h [new file with mode: 0644]
sysdeps/ieee754/ldbl-128/strtold_l.c
sysdeps/ieee754/ldbl-128ibm/strtod_nan_ldouble.h [new file with mode: 0644]
sysdeps/ieee754/ldbl-128ibm/strtold_l.c
sysdeps/ieee754/ldbl-64-128/strtold_l.c
sysdeps/ieee754/ldbl-96/strtod_nan_ldouble.h [new file with mode: 0644]
sysdeps/ieee754/ldbl-96/strtold_l.c
wcsmbs/Makefile
wcsmbs/wcstod_l.c
wcsmbs/wcstod_nan.c [new file with mode: 0644]
wcsmbs/wcstof_l.c
wcsmbs/wcstof_nan.c [new file with mode: 0644]
wcsmbs/wcstold_l.c
wcsmbs/wcstold_nan.c [new file with mode: 0644]

index 78ba1f9c191a77c18e6b9223c6aacb39f24c2eb7..343a936105002b13458ba654016a890c4d69d0c0 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,54 @@
 2015-11-24  Joseph Myers  <joseph@codesourcery.com>
 
+       * stdlib/strtod_nan.c: New file.
+       * stdlib/strtod_nan_double.h: Likewise.
+       * stdlib/strtod_nan_float.h: Likewise.
+       * stdlib/strtod_nan_main.c: Likewise.
+       * stdlib/strtod_nan_narrow.h: Likewise.
+       * stdlib/strtod_nan_wide.h: Likewise.
+       * stdlib/strtof_nan.c: Likewise.
+       * stdlib/strtold_nan.c: Likewise.
+       * sysdeps/ieee754/ldbl-128/strtod_nan_ldouble.h: Likewise.
+       * sysdeps/ieee754/ldbl-128ibm/strtod_nan_ldouble.h: Likewise.
+       * sysdeps/ieee754/ldbl-96/strtod_nan_ldouble.h: Likewise.
+       * wcsmbs/wcstod_nan.c: Likewise.
+       * wcsmbs/wcstof_nan.c: Likewise.
+       * wcsmbs/wcstold_nan.c: Likewise.
+       * stdlib/Makefile (routines): Add strtof_nan, strtod_nan and
+       strtold_nan.
+       * wcsmbs/Makefile (routines): Add wcstod_nan, wcstold_nan and
+       wcstof_nan.
+       * include/stdlib.h (__strtof_nan): Declare and use
+       libc_hidden_proto.
+       (__strtod_nan): Likewise.
+       (__strtold_nan): Likewise.
+       (__wcstof_nan): Likewise.
+       (__wcstod_nan): Likewise.
+       (__wcstold_nan): Likewise.
+       * include/wchar.h (____wcstoull_l_internal): Declare.
+       * stdlib/strtod_l.c: Do not include <ieee754.h>.
+       (____strtoull_l_internal): Remove declaration.
+       (STRTOF_NAN): Define macro.
+       (SET_MANTISSA): Remove macro.
+       (STRTOULL): Likewise.
+       (____STRTOF_INTERNAL): Use STRTOF_NAN to parse NaN payload.
+       * stdlib/strtof_l.c (____strtoull_l_internal): Remove declaration.
+       (STRTOF_NAN): Define macro.
+       (SET_MANTISSA): Remove macro.
+       * sysdeps/ieee754/ldbl-128/strtold_l.c (STRTOF_NAN): Define macro.
+       (SET_MANTISSA): Remove macro.
+       * sysdeps/ieee754/ldbl-128ibm/strtold_l.c (STRTOF_NAN): Define
+       macro.
+       (SET_MANTISSA): Remove macro.
+       * sysdeps/ieee754/ldbl-64-128/strtold_l.c (STRTOF_NAN): Define
+       macro.
+       (SET_MANTISSA): Remove macro.
+       * sysdeps/ieee754/ldbl-96/strtold_l.c (STRTOF_NAN): Define macro.
+       (SET_MANTISSA): Remove macro.
+       * wcsmbs/wcstod_l.c (____wcstoull_l_internal): Remove declaration.
+       * wcsmbs/wcstof_l.c (____wcstoull_l_internal): Likewise.
+       * wcsmbs/wcstold_l.c (____wcstoull_l_internal): Likewise.
+
        [BZ #19266]
        * stdlib/strtod_l.c (____STRTOF_INTERNAL): Check directly for
        upper case and lower case letters inside NAN(), not using TOLOWER.
index dcb83a502712512982d16f4cceaadf0fe16b4cc7..352339e8595eb8229018cb27f7d2decf63f511c7 100644 (file)
@@ -203,6 +203,24 @@ libc_hidden_proto (strtoll)
 libc_hidden_proto (strtoul)
 libc_hidden_proto (strtoull)
 
+extern float __strtof_nan (const char *, char **, char) internal_function;
+extern double __strtod_nan (const char *, char **, char) internal_function;
+extern long double __strtold_nan (const char *, char **, char)
+     internal_function;
+extern float __wcstof_nan (const wchar_t *, wchar_t **, wchar_t)
+     internal_function;
+extern double __wcstod_nan (const wchar_t *, wchar_t **, wchar_t)
+     internal_function;
+extern long double __wcstold_nan (const wchar_t *, wchar_t **, wchar_t)
+     internal_function;
+
+libc_hidden_proto (__strtof_nan)
+libc_hidden_proto (__strtod_nan)
+libc_hidden_proto (__strtold_nan)
+libc_hidden_proto (__wcstof_nan)
+libc_hidden_proto (__wcstod_nan)
+libc_hidden_proto (__wcstold_nan)
+
 extern char *__ecvt (double __value, int __ndigit, int *__restrict __decpt,
                     int *__restrict __sign);
 extern char *__fcvt (double __value, int __ndigit, int *__restrict __decpt,
index 67d0248f001d57d50d3328b63f3de3ccf1a2047b..0f33d094ed6f4a1cb32b59042096b837a1c31105 100644 (file)
@@ -52,6 +52,9 @@ extern unsigned long long int __wcstoull_internal (const wchar_t *
                                                   __restrict __endptr,
                                                   int __base,
                                                   int __group) __THROW;
+extern unsigned long long int ____wcstoull_l_internal (const wchar_t *,
+                                                      wchar_t **, int, int,
+                                                      __locale_t);
 libc_hidden_proto (__wcstof_internal)
 libc_hidden_proto (__wcstod_internal)
 libc_hidden_proto (__wcstold_internal)
index 10d9406813b669eb64b6e0adb452b25d7eb72d57..d7ae165fc7f34f293efec0c3dcf25a7bd97605a0 100644 (file)
@@ -50,6 +50,7 @@ routines      :=                                                            \
        strtol_l strtoul_l strtoll_l strtoull_l                               \
        strtof strtod strtold                                                 \
        strtof_l strtod_l strtold_l                                           \
+       strtof_nan strtod_nan strtold_nan                                     \
        system canonicalize                                                   \
        a64l l64a                                                             \
        rpmatch strfmon strfmon_l getsubopt xpg_basename fmtmsg               \
index 7307d98b24471e82e945c2c8b43564ccec816a18..21692914fd03e3590b41a37f3dfb03162fc5235d 100644 (file)
@@ -20,8 +20,6 @@
 #include <xlocale.h>
 
 extern double ____strtod_l_internal (const char *, char **, int, __locale_t);
-extern unsigned long long int ____strtoull_l_internal (const char *, char **,
-                                                      int, int, __locale_t);
 
 /* Configuration part.  These macros are defined by `strtold.c',
    `strtof.c', `wcstod.c', `wcstold.c', and `wcstof.c' to produce the
@@ -33,27 +31,20 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **,
 # ifdef USE_WIDE_CHAR
 #  define STRTOF       wcstod_l
 #  define __STRTOF     __wcstod_l
+#  define STRTOF_NAN   __wcstod_nan
 # else
 #  define STRTOF       strtod_l
 #  define __STRTOF     __strtod_l
+#  define STRTOF_NAN   __strtod_nan
 # endif
 # define MPN2FLOAT     __mpn_construct_double
 # define FLOAT_HUGE_VAL        HUGE_VAL
-# define SET_MANTISSA(flt, mant) \
-  do { union ieee754_double u;                                               \
-       u.d = (flt);                                                          \
-       u.ieee_nan.mantissa0 = (mant) >> 32;                                  \
-       u.ieee_nan.mantissa1 = (mant);                                        \
-       if ((u.ieee.mantissa0 | u.ieee.mantissa1) != 0)                       \
-        (flt) = u.d;                                                         \
-  } while (0)
 #endif
 /* End of configuration part.  */
 \f
 #include <ctype.h>
 #include <errno.h>
 #include <float.h>
-#include <ieee754.h>
 #include "../locale/localeinfo.h"
 #include <locale.h>
 #include <math.h>
@@ -105,7 +96,6 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **,
 # define TOLOWER_C(Ch) __towlower_l ((Ch), _nl_C_locobj_ptr)
 # define STRNCASECMP(S1, S2, N) \
   __wcsncasecmp_l ((S1), (S2), (N), _nl_C_locobj_ptr)
-# define STRTOULL(S, E, B) ____wcstoull_l_internal ((S), (E), (B), 0, loc)
 #else
 # define STRING_TYPE char
 # define CHAR_TYPE char
@@ -117,7 +107,6 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **,
 # define TOLOWER_C(Ch) __tolower_l ((Ch), _nl_C_locobj_ptr)
 # define STRNCASECMP(S1, S2, N) \
   __strncasecmp_l ((S1), (S2), (N), _nl_C_locobj_ptr)
-# define STRTOULL(S, E, B) ____strtoull_l_internal ((S), (E), (B), 0, loc)
 #endif
 
 
@@ -649,33 +638,14 @@ ____STRTOF_INTERNAL (const STRING_TYPE *nptr, STRING_TYPE **endptr, int group,
          if (*cp == L_('('))
            {
              const STRING_TYPE *startp = cp;
-             do
-               ++cp;
-             while ((*cp >= L_('0') && *cp <= L_('9'))
-                    || (*cp >= L_('A') && *cp <= L_('Z'))
-                    || (*cp >= L_('a') && *cp <= L_('z'))
-                    || *cp == L_('_'));
-
-             if (*cp != L_(')'))
-               /* The closing brace is missing.  Only match the NAN
-                  part.  */
-               cp = startp;
+             STRING_TYPE *endp;
+             retval = STRTOF_NAN (cp + 1, &endp, L_(')'));
+             if (*endp == L_(')'))
+               /* Consume the closing parenthesis.  */
+               cp = endp + 1;
              else
-               {
-                 /* This is a system-dependent way to specify the
-                    bitmask used for the NaN.  We expect it to be
-                    a number which is put in the mantissa of the
-                    number.  */
-                 STRING_TYPE *endp;
-                 unsigned long long int mant;
-
-                 mant = STRTOULL (startp + 1, &endp, 0);
-                 if (endp == cp)
-                   SET_MANTISSA (retval, mant);
-
-                 /* Consume the closing brace.  */
-                 ++cp;
-               }
+               /* Only match the NAN part.  */
+               cp = startp;
            }
 
          if (endptr != NULL)
diff --git a/stdlib/strtod_nan.c b/stdlib/strtod_nan.c
new file mode 100644 (file)
index 0000000..2a0a89f
--- /dev/null
@@ -0,0 +1,24 @@
+/* Convert string for NaN payload to corresponding NaN.  Narrow
+   strings, double.
+   Copyright (C) 2015 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/>.  */
+
+#include <strtod_nan_narrow.h>
+#include <strtod_nan_double.h>
+
+#define STRTOD_NAN __strtod_nan
+#include <strtod_nan_main.c>
diff --git a/stdlib/strtod_nan_double.h b/stdlib/strtod_nan_double.h
new file mode 100644 (file)
index 0000000..f5bdb03
--- /dev/null
@@ -0,0 +1,30 @@
+/* Convert string for NaN payload to corresponding NaN.  For double.
+   Copyright (C) 1997-2015 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/>.  */
+
+#define FLOAT          double
+#define SET_MANTISSA(flt, mant)                                \
+  do                                                   \
+    {                                                  \
+      union ieee754_double u;                          \
+      u.d = (flt);                                     \
+      u.ieee_nan.mantissa0 = (mant) >> 32;             \
+      u.ieee_nan.mantissa1 = (mant);                   \
+      if ((u.ieee.mantissa0 | u.ieee.mantissa1) != 0)  \
+       (flt) = u.d;                                    \
+    }                                                  \
+  while (0)
diff --git a/stdlib/strtod_nan_float.h b/stdlib/strtod_nan_float.h
new file mode 100644 (file)
index 0000000..4c52de8
--- /dev/null
@@ -0,0 +1,29 @@
+/* Convert string for NaN payload to corresponding NaN.  For float.
+   Copyright (C) 1997-2015 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/>.  */
+
+#define        FLOAT           float
+#define SET_MANTISSA(flt, mant)                        \
+  do                                           \
+    {                                          \
+      union ieee754_float u;                   \
+      u.f = (flt);                             \
+      u.ieee_nan.mantissa = (mant);            \
+      if (u.ieee.mantissa != 0)                        \
+       (flt) = u.f;                            \
+    }                                          \
+  while (0)
diff --git a/stdlib/strtod_nan_main.c b/stdlib/strtod_nan_main.c
new file mode 100644 (file)
index 0000000..bc37a63
--- /dev/null
@@ -0,0 +1,63 @@
+/* Convert string for NaN payload to corresponding NaN.
+   Copyright (C) 1997-2015 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/>.  */
+
+#include <ieee754.h>
+#include <locale.h>
+#include <math.h>
+#include <stdlib.h>
+#include <wchar.h>
+
+
+/* If STR starts with an optional n-char-sequence as defined by ISO C
+   (a sequence of ASCII letters, digits and underscores), followed by
+   ENDC, return a NaN whose payload is set based on STR.  Otherwise,
+   return a default NAN.  If ENDPTR is not NULL, set *ENDPTR to point
+   to the character after the initial n-char-sequence.  */
+
+internal_function
+FLOAT
+STRTOD_NAN (const STRING_TYPE *str, STRING_TYPE **endptr, STRING_TYPE endc)
+{
+  const STRING_TYPE *cp = str;
+
+  while ((*cp >= L_('0') && *cp <= L_('9'))
+        || (*cp >= L_('A') && *cp <= L_('Z'))
+        || (*cp >= L_('a') && *cp <= L_('z'))
+        || *cp == L_('_'))
+    ++cp;
+
+  FLOAT retval = NAN;
+  if (*cp != endc)
+    goto out;
+
+  /* This is a system-dependent way to specify the bitmask used for
+     the NaN.  We expect it to be a number which is put in the
+     mantissa of the number.  */
+  STRING_TYPE *endp;
+  unsigned long long int mant;
+
+  mant = STRTOULL (str, &endp, 0);
+  if (endp == cp)
+    SET_MANTISSA (retval, mant);
+
+ out:
+  if (endptr != NULL)
+    *endptr = (STRING_TYPE *) cp;
+  return retval;
+}
+libc_hidden_def (STRTOD_NAN)
diff --git a/stdlib/strtod_nan_narrow.h b/stdlib/strtod_nan_narrow.h
new file mode 100644 (file)
index 0000000..bd77045
--- /dev/null
@@ -0,0 +1,22 @@
+/* Convert string for NaN payload to corresponding NaN.  Narrow strings.
+   Copyright (C) 1997-2015 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/>.  */
+
+#define STRING_TYPE char
+#define L_(Ch) Ch
+#define STRTOULL(S, E, B) ____strtoull_l_internal ((S), (E), (B), 0,   \
+                                                  _nl_C_locobj_ptr)
diff --git a/stdlib/strtod_nan_wide.h b/stdlib/strtod_nan_wide.h
new file mode 100644 (file)
index 0000000..783fbf4
--- /dev/null
@@ -0,0 +1,22 @@
+/* Convert string for NaN payload to corresponding NaN.  Wide strings.
+   Copyright (C) 1997-2015 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/>.  */
+
+#define STRING_TYPE wchar_t
+#define L_(Ch) L##Ch
+#define STRTOULL(S, E, B) ____wcstoull_l_internal ((S), (E), (B), 0,   \
+                                                  _nl_C_locobj_ptr)
index 2a8646a8f6562824fa310e31cfa5a1a3f0669e6d..491256f3b93b44936d60409ec7cec736f048d598 100644 (file)
 #include <xlocale.h>
 
 extern float ____strtof_l_internal (const char *, char **, int, __locale_t);
-extern unsigned long long int ____strtoull_l_internal (const char *, char **,
-                                                      int, int, __locale_t);
 
 #define        FLOAT           float
 #define        FLT             FLT
 #ifdef USE_WIDE_CHAR
 # define STRTOF                wcstof_l
 # define __STRTOF      __wcstof_l
+# define STRTOF_NAN    __wcstof_nan
 #else
 # define STRTOF                strtof_l
 # define __STRTOF      __strtof_l
+# define STRTOF_NAN    __strtof_nan
 #endif
 #define        MPN2FLOAT       __mpn_construct_float
 #define        FLOAT_HUGE_VAL  HUGE_VALF
-#define SET_MANTISSA(flt, mant) \
-  do { union ieee754_float u;                                                \
-       u.f = (flt);                                                          \
-       u.ieee_nan.mantissa = (mant);                                         \
-       if (u.ieee.mantissa != 0)                                             \
-        (flt) = u.f;                                                         \
-  } while (0)
 
 #include "strtod_l.c"
diff --git a/stdlib/strtof_nan.c b/stdlib/strtof_nan.c
new file mode 100644 (file)
index 0000000..b971310
--- /dev/null
@@ -0,0 +1,24 @@
+/* Convert string for NaN payload to corresponding NaN.  Narrow
+   strings, float.
+   Copyright (C) 2015 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/>.  */
+
+#include <strtod_nan_narrow.h>
+#include <strtod_nan_float.h>
+
+#define STRTOD_NAN __strtof_nan
+#include <strtod_nan_main.c>
diff --git a/stdlib/strtold_nan.c b/stdlib/strtold_nan.c
new file mode 100644 (file)
index 0000000..dd43032
--- /dev/null
@@ -0,0 +1,30 @@
+/* Convert string for NaN payload to corresponding NaN.  Narrow
+   strings, long double.
+   Copyright (C) 2015 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/>.  */
+
+#include <math.h>
+
+/* This function is unused if long double and double have the same
+   representation.  */
+#ifndef __NO_LONG_DOUBLE_MATH
+# include <strtod_nan_narrow.h>
+# include <strtod_nan_ldouble.h>
+
+# define STRTOD_NAN __strtold_nan
+# include <strtod_nan_main.c>
+#endif
diff --git a/sysdeps/ieee754/ldbl-128/strtod_nan_ldouble.h b/sysdeps/ieee754/ldbl-128/strtod_nan_ldouble.h
new file mode 100644 (file)
index 0000000..e0da4e2
--- /dev/null
@@ -0,0 +1,33 @@
+/* Convert string for NaN payload to corresponding NaN.  For ldbl-128.
+   Copyright (C) 1997-2015 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/>.  */
+
+#define FLOAT          long double
+#define SET_MANTISSA(flt, mant)                                \
+  do                                                   \
+    {                                                  \
+      union ieee854_long_double u;                     \
+      u.d = (flt);                                     \
+      u.ieee_nan.mantissa0 = 0;                                \
+      u.ieee_nan.mantissa1 = 0;                                \
+      u.ieee_nan.mantissa2 = (mant) >> 32;             \
+      u.ieee_nan.mantissa3 = (mant);                   \
+      if ((u.ieee.mantissa0 | u.ieee.mantissa1         \
+          | u.ieee.mantissa2 | u.ieee.mantissa3) != 0) \
+       (flt) = u.d;                                    \
+    }                                                  \
+  while (0)
index d1ae57e3042cee0f53175d15f1b6b8c9d59772d8..0b2ed27aa82064b31b7faca26f1d2e03fd793c0d 100644 (file)
 #ifdef USE_WIDE_CHAR
 # define STRTOF                wcstold_l
 # define __STRTOF      __wcstold_l
+# define STRTOF_NAN    __wcstold_nan
 #else
 # define STRTOF                strtold_l
 # define __STRTOF      __strtold_l
+# define STRTOF_NAN    __strtold_nan
 #endif
 #define MPN2FLOAT      __mpn_construct_long_double
 #define FLOAT_HUGE_VAL HUGE_VALL
-#define SET_MANTISSA(flt, mant) \
-  do { union ieee854_long_double u;                                          \
-       u.d = (flt);                                                          \
-       u.ieee_nan.mantissa0 = 0;                                             \
-       u.ieee_nan.mantissa1 = 0;                                             \
-       u.ieee_nan.mantissa2 = (mant) >> 32;                                  \
-       u.ieee_nan.mantissa3 = (mant);                                        \
-       if ((u.ieee.mantissa0 | u.ieee.mantissa1                                      \
-           | u.ieee.mantissa2 | u.ieee.mantissa3) != 0)                      \
-        (flt) = u.d;                                                         \
-  } while (0)
 
 #include <strtod_l.c>
diff --git a/sysdeps/ieee754/ldbl-128ibm/strtod_nan_ldouble.h b/sysdeps/ieee754/ldbl-128ibm/strtod_nan_ldouble.h
new file mode 100644 (file)
index 0000000..876a4bb
--- /dev/null
@@ -0,0 +1,30 @@
+/* Convert string for NaN payload to corresponding NaN.  For ldbl-128ibm.
+   Copyright (C) 1997-2015 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/>.  */
+
+#define FLOAT          long double
+#define SET_MANTISSA(flt, mant)                                        \
+  do                                                           \
+    {                                                          \
+      union ibm_extended_long_double u;                                \
+      u.ld = (flt);                                            \
+      u.d[0].ieee_nan.mantissa0 = (mant) >> 32;                        \
+      u.d[0].ieee_nan.mantissa1 = (mant);                      \
+      if ((u.d[0].ieee.mantissa0 | u.d[0].ieee.mantissa1) != 0)        \
+       (flt) = u.ld;                                           \
+    }                                                          \
+  while (0)
index 3e2f69e3534b24ad7d9532ba673afb372575ea9e..6cd963b2cccfbe5f7c6beb24411e3955978fbd4b 100644 (file)
@@ -30,25 +30,19 @@ extern long double ____new_wcstold_l (const wchar_t *, wchar_t **, __locale_t);
 # define STRTOF                __new_wcstold_l
 # define __STRTOF      ____new_wcstold_l
 # define ____STRTOF_INTERNAL ____wcstold_l_internal
+# define STRTOF_NAN    __wcstold_nan
 #else
 extern long double ____new_strtold_l (const char *, char **, __locale_t);
 # define STRTOF                __new_strtold_l
 # define __STRTOF      ____new_strtold_l
 # define ____STRTOF_INTERNAL ____strtold_l_internal
+# define STRTOF_NAN    __strtold_nan
 #endif
 extern __typeof (__STRTOF) STRTOF;
 libc_hidden_proto (__STRTOF)
 libc_hidden_proto (STRTOF)
 #define MPN2FLOAT      __mpn_construct_long_double
 #define FLOAT_HUGE_VAL HUGE_VALL
-# define SET_MANTISSA(flt, mant) \
-  do { union ibm_extended_long_double u;                                     \
-       u.ld = (flt);                                                         \
-       u.d[0].ieee_nan.mantissa0 = (mant) >> 32;                             \
-       u.d[0].ieee_nan.mantissa1 = (mant);                                   \
-       if ((u.d[0].ieee.mantissa0 | u.d[0].ieee.mantissa1) != 0)             \
-        (flt) = u.ld;                                                        \
-  } while (0)
 
 #include <strtod_l.c>
 
index 3944a4364354f8fd7e4a76d401c5e8aaca2d4524..6cd963b2cccfbe5f7c6beb24411e3955978fbd4b 100644 (file)
@@ -30,28 +30,19 @@ extern long double ____new_wcstold_l (const wchar_t *, wchar_t **, __locale_t);
 # define STRTOF                __new_wcstold_l
 # define __STRTOF      ____new_wcstold_l
 # define ____STRTOF_INTERNAL ____wcstold_l_internal
+# define STRTOF_NAN    __wcstold_nan
 #else
 extern long double ____new_strtold_l (const char *, char **, __locale_t);
 # define STRTOF                __new_strtold_l
 # define __STRTOF      ____new_strtold_l
 # define ____STRTOF_INTERNAL ____strtold_l_internal
+# define STRTOF_NAN    __strtold_nan
 #endif
 extern __typeof (__STRTOF) STRTOF;
 libc_hidden_proto (__STRTOF)
 libc_hidden_proto (STRTOF)
 #define MPN2FLOAT      __mpn_construct_long_double
 #define FLOAT_HUGE_VAL HUGE_VALL
-#define SET_MANTISSA(flt, mant) \
-  do { union ieee854_long_double u;                                          \
-       u.d = (flt);                                                          \
-       u.ieee_nan.mantissa0 = 0;                                             \
-       u.ieee_nan.mantissa1 = 0;                                             \
-       u.ieee_nan.mantissa2 = (mant) >> 32;                                  \
-       u.ieee_nan.mantissa3 = (mant);                                        \
-       if ((u.ieee.mantissa0 | u.ieee.mantissa1                                      \
-           | u.ieee.mantissa2 | u.ieee.mantissa3) != 0)                      \
-        (flt) = u.d;                                                         \
-  } while (0)
 
 #include <strtod_l.c>
 
diff --git a/sysdeps/ieee754/ldbl-96/strtod_nan_ldouble.h b/sysdeps/ieee754/ldbl-96/strtod_nan_ldouble.h
new file mode 100644 (file)
index 0000000..6f03359
--- /dev/null
@@ -0,0 +1,30 @@
+/* Convert string for NaN payload to corresponding NaN.  For ldbl-96.
+   Copyright (C) 1997-2015 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/>.  */
+
+#define FLOAT          long double
+#define SET_MANTISSA(flt, mant)                                \
+  do                                                   \
+    {                                                  \
+      union ieee854_long_double u;                     \
+      u.d = (flt);                                     \
+      u.ieee_nan.mantissa0 = (mant) >> 32;             \
+      u.ieee_nan.mantissa1 = (mant);                   \
+      if ((u.ieee.mantissa0 | u.ieee.mantissa1) != 0)  \
+       (flt) = u.d;                                    \
+    }                                                  \
+  while (0)
index c082e7472eacd9d8179f2f4ddf62e4324126dc18..db92242d5982d43a1feb33ebbafab9fac1e220ac 100644 (file)
 #ifdef USE_WIDE_CHAR
 # define STRTOF                wcstold_l
 # define __STRTOF      __wcstold_l
+# define STRTOF_NAN    __wcstold_nan
 #else
 # define STRTOF                strtold_l
 # define __STRTOF      __strtold_l
+# define STRTOF_NAN    __strtold_nan
 #endif
 #define MPN2FLOAT      __mpn_construct_long_double
 #define FLOAT_HUGE_VAL HUGE_VALL
-#define SET_MANTISSA(flt, mant) \
-  do { union ieee854_long_double u;                                          \
-       u.d = (flt);                                                          \
-       u.ieee_nan.mantissa0 = (mant) >> 32;                                  \
-       u.ieee_nan.mantissa1 = (mant);                                        \
-       if ((u.ieee.mantissa0 | u.ieee.mantissa1) != 0)                       \
-        (flt) = u.d;                                                         \
-  } while (0)
 
 #include <stdlib/strtod_l.c>
index 773cfdb9323991603ed4586893c25f2279b92a42..e5de439fcde31656185e888f3c0893623c6f3f5d 100644 (file)
@@ -33,6 +33,7 @@ routines := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \
            wcstol wcstoul wcstoll wcstoull wcstod wcstold wcstof \
            wcstol_l wcstoul_l wcstoll_l wcstoull_l \
            wcstod_l wcstold_l wcstof_l \
+           wcstod_nan wcstold_nan wcstof_nan \
            wcscoll wcsxfrm \
            wcwidth wcswidth \
            wcscoll_l wcsxfrm_l \
index 9c026d82254478e6469f485933d6a981704d1b00..0fe820c77be95aa3e67e69964a63d86d9523ea3a 100644 (file)
@@ -23,9 +23,6 @@
 
 extern double ____wcstod_l_internal (const wchar_t *, wchar_t **, int,
                                     __locale_t);
-extern unsigned long long int ____wcstoull_l_internal (const wchar_t *,
-                                                      wchar_t **, int, int,
-                                                      __locale_t);
 
 #define        USE_WIDE_CHAR   1
 
diff --git a/wcsmbs/wcstod_nan.c b/wcsmbs/wcstod_nan.c
new file mode 100644 (file)
index 0000000..b3dd6af
--- /dev/null
@@ -0,0 +1,23 @@
+/* Convert string for NaN payload to corresponding NaN.  Wide strings, double.
+   Copyright (C) 2015 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/>.  */
+
+#include "../stdlib/strtod_nan_wide.h"
+#include "../stdlib/strtod_nan_double.h"
+
+#define STRTOD_NAN __wcstod_nan
+#include "../stdlib/strtod_nan_main.c"
index bcf983473803859798d5cc9eb9d744da4824e5b2..392ea49e98d8fd33c18aa5036a8edf37f181156f 100644 (file)
@@ -25,8 +25,5 @@
 
 extern float ____wcstof_l_internal (const wchar_t *, wchar_t **, int,
                                    __locale_t);
-extern unsigned long long int ____wcstoull_l_internal (const wchar_t *,
-                                                      wchar_t **, int, int,
-                                                      __locale_t);
 
 #include <stdlib/strtof_l.c>
diff --git a/wcsmbs/wcstof_nan.c b/wcsmbs/wcstof_nan.c
new file mode 100644 (file)
index 0000000..c5f667a
--- /dev/null
@@ -0,0 +1,23 @@
+/* Convert string for NaN payload to corresponding NaN.  Wide strings, float.
+   Copyright (C) 2015 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/>.  */
+
+#include "../stdlib/strtod_nan_wide.h"
+#include "../stdlib/strtod_nan_float.h"
+
+#define STRTOD_NAN __wcstof_nan
+#include "../stdlib/strtod_nan_main.c"
index 8df93afb5624e17715017f92afcfe2d9e33b3a65..f5d055470c4518db02e939d5cd5eaf5978205651 100644 (file)
@@ -24,8 +24,5 @@
 
 extern long double ____wcstold_l_internal (const wchar_t *, wchar_t **, int,
                                           __locale_t);
-extern unsigned long long int ____wcstoull_l_internal (const wchar_t *,
-                                                      wchar_t **, int, int,
-                                                      __locale_t);
 
 #include <strtold_l.c>
diff --git a/wcsmbs/wcstold_nan.c b/wcsmbs/wcstold_nan.c
new file mode 100644 (file)
index 0000000..ef905d3
--- /dev/null
@@ -0,0 +1,30 @@
+/* Convert string for NaN payload to corresponding NaN.  Wide strings,
+   long double.
+   Copyright (C) 2015 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/>.  */
+
+#include <math.h>
+
+/* This function is unused if long double and double have the same
+   representation.  */
+#ifndef __NO_LONG_DOUBLE_MATH
+# include "../stdlib/strtod_nan_wide.h"
+# include <strtod_nan_ldouble.h>
+
+# define STRTOD_NAN __wcstold_nan
+# include "../stdlib/strtod_nan_main.c"
+#endif