changeset 40173:b716418da8b9

c-strtod, c-strtold: Use the bug fixes for strtod, strtold. * lib/stdlib.in.h (GNULIB_defined_strtod_function, GNULIB_defined_strtold_function): New macros. * lib/c-strtod.c (HAVE_GOOD_STRTOD_L): New macro. (STRTOD): Ignore HAVE_C99_STRTOLD. (c_locale): Don't define it on platforms where strtod_l/strtold_l is deemed buggy. But do use it on platforms where uselocale exists and is usable. (C_STRTOD): Don't use STRTOD_L on platforms where strtod_l/strtold_l is deemed buggy. On platforms where uselocale exists and is usable, use uselocale and strtod/strtold. * m4/c-strtod.m4 (gl_C99_STRTOLD): Remove macro. (gl_C_STRTOD): Require gt_FUNC_USELOCALE. (gl_C_STRTOLD): Likewise. Define HAVE_C99_STRTOLD unconditionally. * modules/c-strtod (Files): Add m4/intl-thread-locale.m4. (Depends-on): Add strtod. * modules/c-strtold (Files): Add m4/intl-thread-locale.m4. (Depends-on): Add strtold.
author Bruno Haible <bruno@clisp.org>
date Fri, 01 Feb 2019 04:34:37 +0100
parents 31ab89a208b9
children b76c7bdde2bf
files ChangeLog lib/c-strtod.c lib/stdlib.in.h m4/c-strtod.m4 modules/c-strtod modules/c-strtold
diffstat 6 files changed, 63 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Fri Feb 01 03:12:28 2019 +0100
+++ b/ChangeLog	Fri Feb 01 04:34:37 2019 +0100
@@ -1,3 +1,24 @@
+2019-01-31  Bruno Haible  <bruno@clisp.org>
+
+	c-strtod, c-strtold: Use the bug fixes for strtod, strtold.
+	* lib/stdlib.in.h (GNULIB_defined_strtod_function,
+	GNULIB_defined_strtold_function): New macros.
+	* lib/c-strtod.c (HAVE_GOOD_STRTOD_L): New macro.
+	(STRTOD): Ignore HAVE_C99_STRTOLD.
+	(c_locale): Don't define it on platforms where strtod_l/strtold_l is
+	deemed buggy. But do use it on platforms where uselocale exists and is
+	usable.
+	(C_STRTOD): Don't use STRTOD_L on platforms where strtod_l/strtold_l is
+	deemed buggy. On platforms where uselocale exists and is usable, use
+	uselocale and strtod/strtold.
+	* m4/c-strtod.m4 (gl_C99_STRTOLD): Remove macro.
+	(gl_C_STRTOD): Require gt_FUNC_USELOCALE.
+	(gl_C_STRTOLD): Likewise. Define HAVE_C99_STRTOLD unconditionally.
+	* modules/c-strtod (Files): Add m4/intl-thread-locale.m4.
+	(Depends-on): Add strtod.
+	* modules/c-strtold (Files): Add m4/intl-thread-locale.m4.
+	(Depends-on): Add strtold.
+
 2019-01-31  Bruno Haible  <bruno@clisp.org>
 
 	strtod, strtold: Use the locale's decimal point.
--- a/lib/c-strtod.c	Fri Feb 01 03:12:28 2019 +0100
+++ b/lib/c-strtod.c	Fri Feb 01 04:34:37 2019 +0100
@@ -30,20 +30,19 @@
 # define C_STRTOD c_strtold
 # define DOUBLE long double
 # define STRTOD_L strtold_l
+# define HAVE_GOOD_STRTOD_L (HAVE_STRTOLD_L && !GNULIB_defined_strtold_function)
+# define STRTOD strtold
 #else
 # define C_STRTOD c_strtod
 # define DOUBLE double
 # define STRTOD_L strtod_l
-#endif
-
-/* c_strtold falls back on strtod if strtold doesn't conform to C99.  */
-#if LONG && HAVE_C99_STRTOLD
-# define STRTOD strtold
-#else
+# define HAVE_GOOD_STRTOD_L (HAVE_STRTOD_L && !GNULIB_defined_strtod_function)
 # define STRTOD strtod
 #endif
 
-#if defined LC_ALL_MASK && (LONG ? HAVE_STRTOLD_L : HAVE_STRTOD_L)
+#if defined LC_ALL_MASK \
+    && ((LONG ? HAVE_GOOD_STRTOLD_L : HAVE_GOOD_STRTOD_L) \
+        || HAVE_WORKING_USELOCALE)
 
 /* Cache for the C locale object.
    Marked volatile so that different threads see the same value
@@ -67,7 +66,9 @@
 {
   DOUBLE r;
 
-#if defined LC_ALL_MASK && (LONG ? HAVE_STRTOLD_L : HAVE_STRTOD_L)
+#if defined LC_ALL_MASK \
+    && ((LONG ? HAVE_GOOD_STRTOLD_L : HAVE_GOOD_STRTOD_L) \
+        || HAVE_WORKING_USELOCALE)
 
   locale_t locale = c_locale ();
   if (!locale)
@@ -77,8 +78,30 @@
       return 0; /* errno is set here */
     }
 
+# if (LONG ? HAVE_GOOD_STRTOLD_L : HAVE_GOOD_STRTOD_L)
+
   r = STRTOD_L (nptr, endptr, locale);
 
+# else /* HAVE_WORKING_USELOCALE */
+
+  locale_t old_locale = uselocale (locale);
+  if (old_locale == (locale_t)0)
+    {
+      if (endptr)
+        *endptr = (char *) nptr;
+      return 0; /* errno is set here */
+    }
+
+  r = STRTOD (nptr, endptr);
+
+  int saved_errno = errno;
+  if (uselocale (old_locale) == (locale_t)0)
+    /* We can't switch back to the old locale.  The thread is hosed.  */
+    abort ();
+  errno = saved_errno;
+
+# endif
+
 #else
 
   char *saved_locale = setlocale (LC_NUMERIC, NULL);
--- a/lib/stdlib.in.h	Fri Feb 01 03:12:28 2019 +0100
+++ b/lib/stdlib.in.h	Fri Feb 01 04:34:37 2019 +0100
@@ -929,6 +929,7 @@
 #  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
 #   define strtod rpl_strtod
 #  endif
+#  define GNULIB_defined_strtod_function 1
 _GL_FUNCDECL_RPL (strtod, double, (const char *str, char **endp)
                                   _GL_ARG_NONNULL ((1)));
 _GL_CXXALIAS_RPL (strtod, double, (const char *str, char **endp));
@@ -954,6 +955,7 @@
 #  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
 #   define strtold rpl_strtold
 #  endif
+#  define GNULIB_defined_strtold_function 1
 _GL_FUNCDECL_RPL (strtold, long double, (const char *str, char **endp)
                                         _GL_ARG_NONNULL ((1)));
 _GL_CXXALIAS_RPL (strtold, long double, (const char *str, char **endp));
--- a/m4/c-strtod.m4	Fri Feb 01 03:12:28 2019 +0100
+++ b/m4/c-strtod.m4	Fri Feb 01 04:34:37 2019 +0100
@@ -1,4 +1,4 @@
-# c-strtod.m4 serial 16
+# c-strtod.m4 serial 17
 
 # Copyright (C) 2004-2006, 2009-2019 Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
@@ -7,36 +7,11 @@
 
 # Written by Paul Eggert.
 
-AC_DEFUN([gl_C99_STRTOLD],
-[
-  AC_CACHE_CHECK([whether strtold conforms to C99],
-    [gl_cv_func_c99_strtold],
-    [AC_LINK_IFELSE(
-       [AC_LANG_PROGRAM(
-          [[/* On HP-UX before 11.23, strtold returns a struct instead of
-                long double.  Reject implementations like that, by requiring
-                compatibility with the C99 prototype.  */
-             #include <stdlib.h>
-             static long double (*p) (char const *, char **) = strtold;
-             static long double
-             test (char const *nptr, char **endptr)
-             {
-               long double r;
-               r = strtold (nptr, endptr);
-               return r;
-             }]],
-           [[return test ("1.0", NULL) != 1 || p ("1.0", NULL) != 1;]])],
-       [gl_cv_func_c99_strtold=yes],
-       [gl_cv_func_c99_strtold=no])])
-  if test $gl_cv_func_c99_strtold = yes; then
-    AC_DEFINE([HAVE_C99_STRTOLD], [1], [Define to 1 if strtold conforms to C99.])
-  fi
-])
-
 dnl Prerequisites of lib/c-strtod.c.
 AC_DEFUN([gl_C_STRTOD],
 [
   AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+  AC_REQUIRE([gt_FUNC_USELOCALE])
 
   AC_CHECK_HEADERS_ONCE([xlocale.h])
   dnl We can't use AC_CHECK_FUNC here, because strtod_l() is defined as a
@@ -71,6 +46,8 @@
 AC_DEFUN([gl_C_STRTOLD],
 [
   AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
-  AC_REQUIRE([gl_C99_STRTOLD])
+  AC_REQUIRE([gt_FUNC_USELOCALE])
+  AC_DEFINE([HAVE_C99_STRTOLD], [1],
+    [Define to 1 because the gnulib 'strtold' module provides a C99-conforming strtold function.])
   AC_CHECK_FUNCS([strtold_l])
 ])
--- a/modules/c-strtod	Fri Feb 01 03:12:28 2019 +0100
+++ b/modules/c-strtod	Fri Feb 01 04:34:37 2019 +0100
@@ -5,11 +5,13 @@
 lib/c-strtod.c
 lib/c-strtod.h
 m4/c-strtod.m4
+m4/intl-thread-locale.m4
 
 Depends-on:
 extensions
 locale
 strdup-posix
+strtod
 
 configure.ac:
 gl_C_STRTOD
--- a/modules/c-strtold	Fri Feb 01 03:12:28 2019 +0100
+++ b/modules/c-strtold	Fri Feb 01 04:34:37 2019 +0100
@@ -6,11 +6,13 @@
 lib/c-strtod.c
 lib/c-strtold.c
 m4/c-strtod.m4
+m4/intl-thread-locale.m4
 
 Depends-on:
 extensions
 locale
 strdup-posix
+strtold
 
 configure.ac:
 gl_C_STRTOLD