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
next prev parent 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).