bug-gnulib@gnu.org mirror (unofficial)
 help / color / mirror / Atom feed
From: Bruno Haible <bruno@clisp.org>
To: "Pádraig Brady" <P@draigbrady.com>
Cc: bug-gnulib@gnu.org
Subject: Re: new module 'strtold'
Date: Fri, 01 Feb 2019 04:34:31 +0100	[thread overview]
Message-ID: <103272061.ln51gt88HS@omega> (raw)
In-Reply-To: <76e35280-8cd3-7ecd-b5f0-ee3bf35d7013@draigBrady.com>

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  <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.

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	other threads:[~2019-02-01  3:34 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-01-30  3:05 new module 'strtold' Bruno Haible
2019-01-30  5:42 ` Pádraig Brady
2019-02-01  3:34   ` Bruno Haible [this message]
2019-02-01 22:47     ` Paul Eggert
2019-02-02  1:44       ` Bruno Haible
2019-02-01  2:16 ` strtod, strtold: various fixes Bruno Haible

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://lists.gnu.org/mailman/listinfo/bug-gnulib

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=103272061.ln51gt88HS@omega \
    --to=bruno@clisp.org \
    --cc=P@draigbrady.com \
    --cc=bug-gnulib@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).