+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.
# 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
{
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)
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);
# 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));
# 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));
-# 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
# 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
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])
])
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
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