summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2019-02-01 04:34:37 +0100
committerBruno Haible <bruno@clisp.org>2019-02-02 02:03:02 +0100
commitb39cc72608e7ae56e959e2f12f7c8b355e63a35a (patch)
treeaed76819cdea1a2424963b0a9d251053d0983583
parent97e23d40a659c85048b59852e1871823f727aeb2 (diff)
downloadgnulib-b39cc72608e7ae56e959e2f12f7c8b355e63a35a.tar.gz
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.
-rw-r--r--ChangeLog21
-rw-r--r--lib/c-strtod.c39
-rw-r--r--lib/stdlib.in.h2
-rw-r--r--m4/c-strtod.m433
-rw-r--r--modules/c-strtod2
-rw-r--r--modules/c-strtold2
6 files changed, 63 insertions, 36 deletions
diff --git a/ChangeLog b/ChangeLog
index 3dbab7af44..963dedd664 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,26 @@
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.
* lib/strtod.c: Include <locale.h>, <stdio.h>, <langinfo.h>.
(decimal_point_char): New function, copied from lib/vasnprintf.c.
diff --git a/lib/c-strtod.c b/lib/c-strtod.c
index b5f88bc007..53ae189d28 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/lib/stdlib.in.h b/lib/stdlib.in.h
index b70444d083..f829525c10 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/m4/c-strtod.m4 b/m4/c-strtod.m4
index 1694a2396c..1d4b7f860c 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 7999d45ee4..71b292ee7f 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 72ff21dd18..c7f31dba11 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