bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: new module 'strtold'


From: Bruno Haible
Subject: Re: new module 'strtold'
Date: Fri, 01 Feb 2019 04:34:31 +0100
User-agent: KMail/5.1.3 (Linux/4.4.0-141-generic; KDE/5.18.0; x86_64; ; )

Pádraig Brady wrote:
> 
>   #if HAVE_C99_STRTOLD /* provided by c-strtold module.  */
>   # define STRTOD strtold
>   #else
>   # define STRTOD strtod
>   #endif
>   long double a = STRTOD (sa, &ea);

But wait, the 'c-strtod' and 'c-strtold' modules are not up-to-date.
When strtod() or strtold() have bugs, you can assume that strtod_l()
and strtold_l() have the same bugs. In this case, it is better to
use the gnulib override of strtod() or strtold(), through 'uselocale'.
This affects at some versions of glibc and some versions of Mac OS X.
Here is a proposed patch.


2019-01-31  Bruno Haible  <address@hidden>

        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.

diff --git a/lib/stdlib.in.h b/lib/stdlib.in.h
index b70444d..f829525 100644
--- a/lib/stdlib.in.h
+++ b/lib/stdlib.in.h
@@ -929,6 +929,7 @@ _GL_WARN_ON_USE (setenv, "setenv is unportable - "
 #  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 @@ _GL_WARN_ON_USE (strtod, "strtod is unportable - "
 #  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));
diff --git a/lib/c-strtod.c b/lib/c-strtod.c
index b5f88bc..53ae189 100644
--- a/lib/c-strtod.c
+++ b/lib/c-strtod.c
@@ -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 @@ C_STRTOD (char const *nptr, char **endptr)
 {
   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 @@ C_STRTOD (char const *nptr, char **endptr)
       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);
diff --git a/m4/c-strtod.m4 b/m4/c-strtod.m4
index 1694a23..1d4b7f8 100644
--- a/m4/c-strtod.m4
+++ b/m4/c-strtod.m4
@@ -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 @@ dnl Prerequisites of lib/c-strtold.c.
 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])
 ])
diff --git a/modules/c-strtod b/modules/c-strtod
index 7999d45..71b292e 100644
--- a/modules/c-strtod
+++ b/modules/c-strtod
@@ -5,11 +5,13 @@ Files:
 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
diff --git a/modules/c-strtold b/modules/c-strtold
index 72ff21d..c7f31db 100644
--- a/modules/c-strtold
+++ b/modules/c-strtold
@@ -6,11 +6,13 @@ lib/c-strtod.h
 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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]