changeset 40166:cdb3438ceb13

strtold: New module. * lib/stdlib.in.h (strtold): New declaration. * lib/strtold.c: New file. * lib/strtod.c: Consider USE_LONG_DOUBLE. (STRTOD, LDEXP, HAVE_UNDERLYING_STRTOD, DOUBLE, MIN, MAX, L_, USE_LDEXP): New macros. (LDEXP, scale_radix_exp, parse_number, STRTOD): Adapt for USE_LONG_DOUBLE. (underlying_strtod): Remove function. Replace with some macros. Re-add the code for a missing underlying function that was removed on 2013-02-19. * m4/strtold.m4: New file. * m4/stdlib_h.m4 (gl_STDLIB_H): Test whether strtold is declared. (gl_STDLIB_H_DEFAULTS): Initialize GNULIB_STRTOLD, HAVE_STRTOLD, REPLACE_STRTOLD. * modules/stdlib (Makefile.am): Substitute GNULIB_STRTOLD, HAVE_STRTOLD, REPLACE_STRTOLD. * modules/strtold: New file. * doc/posix-functions/strtold.texi: Document the new module.
author Bruno Haible <bruno@clisp.org>
date Wed, 30 Jan 2019 03:52:31 +0100
parents 959d7cd4aec1
children c1aa6d1185ea
files ChangeLog doc/posix-functions/strtold.texi lib/stdlib.in.h lib/strtod.c lib/strtold.c m4/stdlib_h.m4 m4/strtold.m4 modules/stdlib modules/strtold
diffstat 9 files changed, 371 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Tue Jan 29 22:09:58 2019 +0100
+++ b/ChangeLog	Wed Jan 30 03:52:31 2019 +0100
@@ -1,3 +1,25 @@
+2019-01-29  Bruno Haible  <bruno@clisp.org>
+
+	strtold: New module.
+	* lib/stdlib.in.h (strtold): New declaration.
+	* lib/strtold.c: New file.
+	* lib/strtod.c: Consider USE_LONG_DOUBLE.
+	(STRTOD, LDEXP, HAVE_UNDERLYING_STRTOD, DOUBLE, MIN, MAX, L_,
+	USE_LDEXP): New macros.
+	(LDEXP, scale_radix_exp, parse_number, STRTOD): Adapt for
+	USE_LONG_DOUBLE.
+	(underlying_strtod): Remove function. Replace with some macros.
+	Re-add the code for a missing underlying function that was removed on
+	2013-02-19.
+	* m4/strtold.m4: New file.
+	* m4/stdlib_h.m4 (gl_STDLIB_H): Test whether strtold is declared.
+	(gl_STDLIB_H_DEFAULTS): Initialize GNULIB_STRTOLD, HAVE_STRTOLD,
+	REPLACE_STRTOLD.
+	* modules/stdlib (Makefile.am): Substitute GNULIB_STRTOLD, HAVE_STRTOLD,
+	REPLACE_STRTOLD.
+	* modules/strtold: New file.
+	* doc/posix-functions/strtold.texi: Document the new module.
+
 2019-01-29  Bruno Haible  <bruno@clisp.org>
 
 	strtod: Fix compilation error on IRIX 6.5.
--- a/doc/posix-functions/strtold.texi	Tue Jan 29 22:09:58 2019 +0100
+++ b/doc/posix-functions/strtold.texi	Wed Jan 30 03:52:31 2019 +0100
@@ -4,15 +4,63 @@
 
 POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/strtold.html}
 
-Gnulib module: ---
+Gnulib module: strtold
 
 Portability problems fixed by Gnulib:
 @itemize
+@item
+This function is missing on some platforms:
+NetBSD 3.0, OpenBSD 3.8, Minix 3.1.8, older IRIX 6.5, OSF/1 4.0, Solaris 9, older Cygwin, MSVC 9, Interix 3.5, BeOS, Android 4.4.
+
+@item
+This function returns a struct, not a @code{long double}, on some platforms:
+HP-UX 11.31/hppa.
+
+@item
+This function consumes whitespace even when there is nothing that should
+be parsed on some platforms:
+IRIX 6.5.
+
+@item
+This function allows whitespace between @samp{e} and the exponent on
+some platforms:
+HP-UX 11.31/ia64, IRIX 6.5.
+
+@item
+This function returns the wrong end pointer for @samp{-0x} on some
+platforms:
+glibc-2.3.2, Mac OS X 10.5, Haiku.
+
+@item
+This function returns +0.0 (not @minus{}0.0) for @samp{-0} on some platforms:
+IRIX 6.5.
+
+@item
+This function fails to parse Infinities and plain NaNs on some platforms:
+HP-UX 11.31/ia64, IRIX 6.5.
+
+@item
+This function fails to parse @samp{NaN()} on some platforms:
+glibc-2.3.2, IRIX 6.5, mingw, Haiku.
+
+@item
+This function fails to parse @samp{NaN(@var{n-char-sequence})} on some
+platforms:
+IRIX 6.5.
+
+@item
+This function parses @samp{NaN(@var{n-char-sequence})}, but returns
+the wrong end pointer on some platforms:
+glibc-2.3.2, mingw, Haiku.
+
+@item
+This function fails to parse C99 hexadecimal floating point on some
+platforms:
+IRIX 6.5, mingw.
 @end itemize
 
 Portability problems not fixed by Gnulib:
 @itemize
 @item
-This function is missing on some platforms:
-NetBSD 3.0, OpenBSD 3.8, Minix 3.1.8, IRIX 6.5, OSF/1 4.0, Solaris 9, Cygwin, MSVC 9, Interix 3.5, BeOS, Android 4.4.
+The replacement function does not always return correctly rounded results.
 @end itemize
--- a/lib/stdlib.in.h	Tue Jan 29 22:09:58 2019 +0100
+++ b/lib/stdlib.in.h	Wed Jan 30 03:52:31 2019 +0100
@@ -948,6 +948,31 @@
 # endif
 #endif
 
+#if @GNULIB_STRTOLD@
+ /* Parse a 'long double' from STRING, updating ENDP if appropriate.  */
+# if @REPLACE_STRTOLD@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   define strtold rpl_strtold
+#  endif
+_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));
+# else
+#  if !@HAVE_STRTOLD@
+_GL_FUNCDECL_SYS (strtold, long double, (const char *str, char **endp)
+                                        _GL_ARG_NONNULL ((1)));
+#  endif
+_GL_CXXALIAS_SYS (strtold, long double, (const char *str, char **endp));
+# endif
+_GL_CXXALIASWARN (strtold);
+#elif defined GNULIB_POSIXCHECK
+# undef strtold
+# if HAVE_RAW_DECL_STRTOLD
+_GL_WARN_ON_USE (strtold, "strtold is unportable - "
+                 "use gnulib module strtold for portability");
+# endif
+#endif
+
 #if @GNULIB_STRTOLL@
 /* Parse a signed integer whose textual representation starts at STRING.
    The integer is expected to be in base BASE (2 <= BASE <= 36); if BASE == 0,
--- a/lib/strtod.c	Tue Jan 29 22:09:58 2019 +0100
+++ b/lib/strtod.c	Wed Jan 30 03:52:31 2019 +0100
@@ -14,8 +14,11 @@
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
 
-#include <config.h>
+#if ! defined USE_LONG_DOUBLE
+# include <config.h>
+#endif
 
+/* Specification.  */
 #include <stdlib.h>
 
 #include <ctype.h>
@@ -28,8 +31,36 @@
 
 #include "c-ctype.h"
 
-#ifndef HAVE_LDEXP_IN_LIBC
-#define HAVE_LDEXP_IN_LIBC 0
+#undef MIN
+#undef MAX
+#ifdef USE_LONG_DOUBLE
+# define STRTOD strtold
+# define LDEXP ldexpl
+# if defined __hpux && defined __hppa
+   /* We cannot call strtold on HP-UX/hppa, because its return type is a struct,
+      not a 'long double'.  */
+#  define HAVE_UNDERLYING_STRTOD 0
+# else
+#  define HAVE_UNDERLYING_STRTOD HAVE_STRTOLD
+# endif
+# define DOUBLE long double
+# define MIN LDBL_MIN
+# define MAX LDBL_MAX
+# define L_(literal) literal##L
+#else
+# define STRTOD strtod
+# define LDEXP ldexp
+# define HAVE_UNDERLYING_STRTOD 1
+# define DOUBLE double
+# define MIN DBL_MIN
+# define MAX DBL_MAX
+# define L_(literal) literal
+#endif
+
+#if (defined USE_LONG_DOUBLE ? HAVE_LDEXPM_IN_LIBC : HAVE_LDEXP_IN_LIBC)
+# define USE_LDEXP 1
+#else
+# define USE_LDEXP 0
 #endif
 
 /* Return true if C is a space in the current locale, avoiding
@@ -41,20 +72,21 @@
   return isspace (uc) != 0;
 }
 
-#if !HAVE_LDEXP_IN_LIBC
- #define ldexp dummy_ldexp
+#if !USE_LDEXP
+ #undef LDEXP
+ #define LDEXP dummy_ldexp
  /* A dummy definition that will never be invoked.  */
- static double ldexp (double x _GL_UNUSED, int exponent _GL_UNUSED)
+ static DOUBLE LDEXP (DOUBLE x _GL_UNUSED, int exponent _GL_UNUSED)
  {
    abort ();
-   return 0.0;
+   return L_(0.0);
  }
 #endif
 
 /* Return X * BASE**EXPONENT.  Return an extreme value and set errno
    to ERANGE if underflow or overflow occurs.  */
-static double
-scale_radix_exp (double x, int radix, long int exponent)
+static DOUBLE
+scale_radix_exp (DOUBLE x, int radix, long int exponent)
 {
   /* If RADIX == 10, this code is neither precise nor fast; it is
      merely a straightforward and relatively portable approximation.
@@ -63,11 +95,11 @@
 
   long int e = exponent;
 
-  if (HAVE_LDEXP_IN_LIBC && radix == 2)
-    return ldexp (x, e < INT_MIN ? INT_MIN : INT_MAX < e ? INT_MAX : e);
+  if (USE_LDEXP && radix == 2)
+    return LDEXP (x, e < INT_MIN ? INT_MIN : INT_MAX < e ? INT_MAX : e);
   else
     {
-      double r = x;
+      DOUBLE r = x;
 
       if (r != 0)
         {
@@ -87,12 +119,12 @@
             {
               while (e-- != 0)
                 {
-                  if (r < -DBL_MAX / radix)
+                  if (r < -MAX / radix)
                     {
                       errno = ERANGE;
                       return -HUGE_VAL;
                     }
-                  else if (DBL_MAX / radix < r)
+                  else if (MAX / radix < r)
                     {
                       errno = ERANGE;
                       return HUGE_VAL;
@@ -113,7 +145,7 @@
    radix RADIX (either 10 or 2) exponent, and exponent character
    EXPCHAR.  To convert from a number of digits to a radix exponent,
    multiply by RADIX_MULTIPLIER (either 1 or 4).  */
-static double
+static DOUBLE
 parse_number (const char *nptr,
               int base, int radix, int radix_multiplier, char expchar,
               char **endptr)
@@ -121,7 +153,7 @@
   const char *s = nptr;
   bool got_dot = false;
   long int exponent = 0;
-  double num = 0;
+  DOUBLE num = 0;
 
   for (;; ++s)
     {
@@ -141,12 +173,12 @@
         break;
 
       /* Make sure that multiplication by base will not overflow.  */
-      if (num <= DBL_MAX / base)
+      if (num <= MAX / base)
         num = num * base + digit;
       else
         {
           /* The value of the digit doesn't matter, since we have already
-             gotten as many digits as can be represented in a 'double'.
+             gotten as many digits as can be represented in a 'DOUBLE'.
              This doesn't necessarily mean the result will overflow.
              The exponent may reduce it to within range.
 
@@ -185,32 +217,42 @@
   return scale_radix_exp (num, radix, exponent);
 }
 
-static double underlying_strtod (const char *, char **);
-
 /* HP cc on HP-UX 10.20 has a bug with the constant expression -0.0.
    ICC 10.0 has a bug when optimizing the expression -zero.
-   The expression -DBL_MIN * DBL_MIN does not work when cross-compiling
+   The expression -MIN * MIN does not work when cross-compiling
    to PowerPC on Mac OS X 10.5.  */
 #if defined __hpux || defined __sgi || defined __ICC
-static double
+static DOUBLE
 compute_minus_zero (void)
 {
-  return -DBL_MIN * DBL_MIN;
+  return -MIN * MIN;
 }
 # define minus_zero compute_minus_zero ()
 #else
-double minus_zero = -0.0;
+DOUBLE minus_zero = -0.0;
 #endif
 
-/* Convert NPTR to a double.  If ENDPTR is not NULL, a pointer to the
+/* Convert NPTR to a DOUBLE.  If ENDPTR is not NULL, a pointer to the
    character after the last one used in the number is put in *ENDPTR.  */
-double
-strtod (const char *nptr, char **endptr)
+DOUBLE
+STRTOD (const char *nptr, char **endptr)
+#if HAVE_UNDERLYING_STRTOD
+# ifdef USE_LONG_DOUBLE
+#  undef strtold
+# else
+#  undef strtod
+# endif
+#else
+# undef STRTOD
+# define STRTOD(NPTR,ENDPTR) parse_number (NPTR, 10, 10, 1, 'e', ENDPTR)
+#endif
+/* From here on, STRTOD refers to the underlying implementation.  It needs
+   to handle only finite unsigned decimal numbers with non-null ENDPTR.  */
 {
   bool negative = false;
 
   /* The number so far.  */
-  double num;
+  DOUBLE num;
 
   const char *s = nptr;
   const char *end;
@@ -226,7 +268,7 @@
   if (*s == '-' || *s == '+')
     ++s;
 
-  num = underlying_strtod (s, &endbuf);
+  num = STRTOD (s, &endbuf);
   end = endbuf;
 
   if (c_isdigit (s[*s == '.']))
@@ -261,7 +303,7 @@
       else
         {
           /* If "1e 1" was misparsed as 10.0 instead of 1.0, re-do the
-             underlying strtod on a copy of the original string
+             underlying STRTOD on a copy of the original string
              truncated to avoid the bug.  */
           const char *e = s + 1;
           while (e < end && c_tolower (*e) != 'e')
@@ -279,7 +321,7 @@
               else
                 {
                   dup[e - s] = '\0';
-                  num = underlying_strtod (dup, &endbuf);
+                  num = STRTOD (dup, &endbuf);
                   saved_errno = errno;
                   free (dup);
                   errno = saved_errno;
@@ -344,12 +386,3 @@
     return minus_zero;
   return negative ? -num : num;
 }
-
-/* The underlying strtod implementation.  This must be defined
-   after strtod because it #undefs strtod.  */
-static double
-underlying_strtod (const char *nptr, char **endptr)
-{
-#undef strtod
-  return strtod (nptr, endptr);
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/strtold.c	Wed Jan 30 03:52:31 2019 +0100
@@ -0,0 +1,37 @@
+/* Convert string to 'long double'.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2019.  */
+
+#include <config.h>
+
+#if HAVE_SAME_LONG_DOUBLE_AS_DOUBLE
+
+/* Specification.  */
+# include <stdlib.h>
+
+long double
+strtold (const char *str, char **endp)
+{
+  return strtod (str, endp);
+}
+
+#else
+
+# define USE_LONG_DOUBLE
+# include "strtod.c"
+
+#endif
--- a/m4/stdlib_h.m4	Tue Jan 29 22:09:58 2019 +0100
+++ b/m4/stdlib_h.m4	Wed Jan 30 03:52:31 2019 +0100
@@ -1,4 +1,4 @@
-# stdlib_h.m4 serial 47
+# stdlib_h.m4 serial 48
 dnl Copyright (C) 2007-2019 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -26,7 +26,7 @@
     initstate initstate_r mbtowc mkdtemp mkostemp mkostemps mkstemp mkstemps
     posix_openpt ptsname ptsname_r qsort_r random random_r reallocarray
     realpath rpmatch secure_getenv setenv setstate setstate_r srandom
-    srandom_r strtod strtoll strtoull unlockpt unsetenv])
+    srandom_r strtod strtold strtoll strtoull unlockpt unsetenv])
 ])
 
 AC_DEFUN([gl_STDLIB_MODULE_INDICATOR],
@@ -68,6 +68,7 @@
   GNULIB_SECURE_GETENV=0; AC_SUBST([GNULIB_SECURE_GETENV])
   GNULIB_SETENV=0;        AC_SUBST([GNULIB_SETENV])
   GNULIB_STRTOD=0;        AC_SUBST([GNULIB_STRTOD])
+  GNULIB_STRTOLD=0;       AC_SUBST([GNULIB_STRTOLD])
   GNULIB_STRTOLL=0;       AC_SUBST([GNULIB_STRTOLL])
   GNULIB_STRTOULL=0;      AC_SUBST([GNULIB_STRTOULL])
   GNULIB_SYSTEM_POSIX=0;  AC_SUBST([GNULIB_SYSTEM_POSIX])
@@ -105,6 +106,7 @@
   HAVE_SETSTATE=1;           AC_SUBST([HAVE_SETSTATE])
   HAVE_DECL_SETSTATE=1;      AC_SUBST([HAVE_DECL_SETSTATE])
   HAVE_STRTOD=1;             AC_SUBST([HAVE_STRTOD])
+  HAVE_STRTOLD=1;            AC_SUBST([HAVE_STRTOLD])
   HAVE_STRTOLL=1;            AC_SUBST([HAVE_STRTOLL])
   HAVE_STRTOULL=1;           AC_SUBST([HAVE_STRTOULL])
   HAVE_STRUCT_RANDOM_DATA=1; AC_SUBST([HAVE_STRUCT_RANDOM_DATA])
@@ -128,6 +130,7 @@
   REPLACE_SETENV=0;          AC_SUBST([REPLACE_SETENV])
   REPLACE_SETSTATE=0;        AC_SUBST([REPLACE_SETSTATE])
   REPLACE_STRTOD=0;          AC_SUBST([REPLACE_STRTOD])
+  REPLACE_STRTOLD=0;         AC_SUBST([REPLACE_STRTOLD])
   REPLACE_UNSETENV=0;        AC_SUBST([REPLACE_UNSETENV])
   REPLACE_WCTOMB=0;          AC_SUBST([REPLACE_WCTOMB])
 ])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/m4/strtold.m4	Wed Jan 30 03:52:31 2019 +0100
@@ -0,0 +1,120 @@
+# strtold.m4 serial 1
+dnl Copyright (C) 2002-2003, 2006-2019 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_STRTOLD],
+[
+  AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
+  AC_REQUIRE([gl_LONG_DOUBLE_VS_DOUBLE])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CHECK_FUNCS_ONCE([strtold])
+  if test $ac_cv_func_strtold != yes; then
+    HAVE_STRTOLD=0
+  else
+    AC_CACHE_CHECK([whether strtold obeys C99], [gl_cv_func_strtold_works],
+      [AC_RUN_IFELSE([AC_LANG_PROGRAM([[
+#include <stdlib.h>
+#include <math.h>
+#include <errno.h>
+/* Compare two numbers with ==.
+   This is a separate function because IRIX 6.5 "cc -O" miscompiles an
+   'x == x' test.  */
+static int
+numeric_equal (long double x, long double y)
+{
+  return x == y;
+}
+]], [[
+  int result = 0;
+  {
+    /* Under Solaris 2.4, strtod returns the wrong value for the
+       terminating character under some conditions.  */
+    const char *string = "NaN";
+    char *term;
+    strtod (string, &term);
+    if (term != string && *(term - 1) == 0)
+      result |= 2;
+  }
+  {
+    /* Older glibc and Cygwin mis-parse "-0x".  */
+    const char *string = "-0x";
+    char *term;
+    long double value = strtold (string, &term);
+    long double zero = 0.0L;
+    if (1.0L / value != -1.0L / zero || term != (string + 2))
+      result |= 4;
+  }
+  {
+    /* IRIX 6.5, mingw do not parse hex floats.  */
+    const char *string = "0XaP+1";
+    char *term;
+    long double value = strtold (string, &term);
+    if (value != 20.0L || term != (string + 6))
+      result |= 8;
+  }
+  {
+    /* IRIX 6.5 does not parse infinities.  HP-UX 11.31/ia64 parses inf,
+       but mistakenly sets errno.  */
+    const char *string = "inf";
+    char *term;
+    long double value;
+    errno = 0;
+    value = strtod (string, &term);
+    if (value != HUGE_VAL || term != (string + 3) || errno)
+      result |= 16;
+  }
+  {
+    /* glibc-2.3.2, IRIX 6.5, mingw, Haiku misparse "nan()".  */
+    const char *string = "nan()";
+    char *term;
+    long double value = strtold (string, &term);
+    if (numeric_equal (value, value) || term != (string + 5))
+      result |= 32;
+  }
+  {
+    /* Mac OS X 10.5, IRIX 6.5 misparse "nan(".  */
+    const char *string = "nan(";
+    char *term;
+    long double value = strtold (string, &term);
+    if (numeric_equal (value, value) || term != (string + 3))
+      result |= 64;
+  }
+  return result;
+]])],
+        [gl_cv_func_strtold_works=yes],
+        [gl_cv_func_strtold_works=no],
+        [dnl The last known bugs in glibc strtold(), as of this writing,
+         dnl were fixed in version 2.8
+         AC_EGREP_CPP([Lucky user],
+           [
+#include <features.h>
+#ifdef __GNU_LIBRARY__
+ #if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8) || (__GLIBC__ > 2)) \
+     && !defined __UCLIBC__
+  Lucky user
+ #endif
+#endif
+           ],
+           [gl_cv_func_strtold_works="guessing yes"],
+           [gl_cv_func_strtod_works="guessing no"])
+        ])
+      ])
+    case "$gl_cv_func_strtold_works" in
+      *yes) ;;
+      *)
+        REPLACE_STRTOLD=1
+        ;;
+    esac
+  fi
+])
+
+# Prerequisites of lib/strtold.c.
+AC_DEFUN([gl_PREREQ_STRTOLD], [
+  AC_REQUIRE([gl_CHECK_LDEXPL_NO_LIBM])
+  if test $gl_cv_func_ldexpl_no_libm = yes; then
+    AC_DEFINE([HAVE_LDEXPL_IN_LIBC], [1],
+      [Define if the ldexpl function is available in libc.])
+  fi
+])
--- a/modules/stdlib	Tue Jan 29 22:09:58 2019 +0100
+++ b/modules/stdlib	Wed Jan 30 03:52:31 2019 +0100
@@ -59,6 +59,7 @@
 	      -e 's/@''GNULIB_SECURE_GETENV''@/$(GNULIB_SECURE_GETENV)/g' \
 	      -e 's/@''GNULIB_SETENV''@/$(GNULIB_SETENV)/g' \
 	      -e 's/@''GNULIB_STRTOD''@/$(GNULIB_STRTOD)/g' \
+	      -e 's/@''GNULIB_STRTOLD''@/$(GNULIB_STRTOLD)/g' \
 	      -e 's/@''GNULIB_STRTOLL''@/$(GNULIB_STRTOLL)/g' \
 	      -e 's/@''GNULIB_STRTOULL''@/$(GNULIB_STRTOULL)/g' \
 	      -e 's/@''GNULIB_SYSTEM_POSIX''@/$(GNULIB_SYSTEM_POSIX)/g' \
@@ -95,6 +96,7 @@
 	      -e 's|@''HAVE_SETSTATE''@|$(HAVE_SETSTATE)|g' \
 	      -e 's|@''HAVE_DECL_SETSTATE''@|$(HAVE_DECL_SETSTATE)|g' \
 	      -e 's|@''HAVE_STRTOD''@|$(HAVE_STRTOD)|g' \
+	      -e 's|@''HAVE_STRTOLD''@|$(HAVE_STRTOLD)|g' \
 	      -e 's|@''HAVE_STRTOLL''@|$(HAVE_STRTOLL)|g' \
 	      -e 's|@''HAVE_STRTOULL''@|$(HAVE_STRTOULL)|g' \
 	      -e 's|@''HAVE_STRUCT_RANDOM_DATA''@|$(HAVE_STRUCT_RANDOM_DATA)|g' \
@@ -118,6 +120,7 @@
 	      -e 's|@''REPLACE_SETENV''@|$(REPLACE_SETENV)|g' \
 	      -e 's|@''REPLACE_SETSTATE''@|$(REPLACE_SETSTATE)|g' \
 	      -e 's|@''REPLACE_STRTOD''@|$(REPLACE_STRTOD)|g' \
+	      -e 's|@''REPLACE_STRTOLD''@|$(REPLACE_STRTOLD)|g' \
 	      -e 's|@''REPLACE_UNSETENV''@|$(REPLACE_UNSETENV)|g' \
 	      -e 's|@''REPLACE_WCTOMB''@|$(REPLACE_WCTOMB)|g' \
 	      -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/strtold	Wed Jan 30 03:52:31 2019 +0100
@@ -0,0 +1,35 @@
+Description:
+strtold() function: convert string to 'long double'.
+
+Files:
+lib/strtold.c
+lib/strtod.c
+m4/strtold.m4
+m4/math_h.m4
+m4/ldexpl.m4
+
+Depends-on:
+stdlib
+c-ctype         [test $HAVE_STRTOLD = 0 || test $REPLACE_STRTOLD = 1]
+math            [test $HAVE_STRTOLD = 0 || test $REPLACE_STRTOLD = 1]
+stdbool         [test $HAVE_STRTOLD = 0 || test $REPLACE_STRTOLD = 1]
+strtod          [{ test $HAVE_STRTOLD = 0 || test $REPLACE_STRTOLD = 1; } && test $HAVE_SAME_LONG_DOUBLE_AS_DOUBLE = 1]
+
+configure.ac:
+gl_FUNC_STRTOLD
+if test $HAVE_STRTOLD = 0 || test $REPLACE_STRTOLD = 1; then
+  AC_LIBOBJ([strtold])
+  gl_PREREQ_STRTOLD
+fi
+gl_STDLIB_MODULE_INDICATOR([strtold])
+
+Makefile.am:
+
+Include:
+<stdlib.h>
+
+License:
+LGPL
+
+Maintainer:
+all