From: Bruno Haible Date: Thu, 12 Dec 2019 10:07:49 +0000 (+0100) Subject: strtold: Work around Cygwin bug. X-Git-Tag: v1.0~4519 X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=fac670ce47d49a37df8929110b9adc70a1763643;p=gnulib.git strtold: Work around Cygwin bug. * m4/strtold.m4 (gl_FUNC_STRTOLD): Add test for the underflow problem. If it is present, define STRTOLD_HAS_UNDERFLOW_BUG. * lib/strtod.c (HAVE_UNDERLYING_STRTOD): Set to 0 if STRTOLD_HAS_UNDERFLOW_BUG is defined. * doc/posix-functions/strtold.texi: Mention the Cygwin bug. --- diff --git a/ChangeLog b/ChangeLog index b1c836cbfb..3cd4b9f9c0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2019-12-12 Bruno Haible + + strtold: Work around Cygwin bug. + * m4/strtold.m4 (gl_FUNC_STRTOLD): Add test for the underflow problem. + If it is present, define STRTOLD_HAS_UNDERFLOW_BUG. + * lib/strtod.c (HAVE_UNDERLYING_STRTOD): Set to 0 if + STRTOLD_HAS_UNDERFLOW_BUG is defined. + * doc/posix-functions/strtold.texi: Mention the Cygwin bug. + 2019-12-12 Bruno Haible strtold: Fix autoconf test. diff --git a/doc/posix-functions/strtold.texi b/doc/posix-functions/strtold.texi index d8ed1747fa..f4116c6528 100644 --- a/doc/posix-functions/strtold.texi +++ b/doc/posix-functions/strtold.texi @@ -62,6 +62,11 @@ IRIX 6.5, mingw. In hexadecimal floats, this function allows whitespace between @samp{p} and the exponent on some platforms: HP-UX 11.31/ia64. + +@item +This function fails to set @code{errno} upon underflow on some platforms: +@c https://cygwin.com/ml/cygwin/2019-12/msg00072.html +Cygwin 2.9. @end itemize Portability problems not fixed by Gnulib: diff --git a/lib/strtod.c b/lib/strtod.c index 69b1564e11..30abbae1b9 100644 --- a/lib/strtod.c +++ b/lib/strtod.c @@ -45,6 +45,9 @@ /* We cannot call strtold on HP-UX/hppa, because its return type is a struct, not a 'long double'. */ # define HAVE_UNDERLYING_STRTOD 0 +# elif STRTOLD_HAS_UNDERFLOW_BUG + /* strtold would not set errno=ERANGE upon underflow. */ +# define HAVE_UNDERLYING_STRTOD 0 # else # define HAVE_UNDERLYING_STRTOD HAVE_STRTOLD # endif diff --git a/m4/strtold.m4 b/m4/strtold.m4 index 15fea14814..0c7cc3b55f 100644 --- a/m4/strtold.m4 +++ b/m4/strtold.m4 @@ -1,4 +1,4 @@ -# strtold.m4 serial 6 +# strtold.m4 serial 7 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, @@ -13,7 +13,7 @@ AC_DEFUN([gl_FUNC_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_CACHE_CHECK([whether strtold obeys POSIX], [gl_cv_func_strtold_works], [AC_RUN_IFELSE([AC_LANG_PROGRAM([[ #include #include @@ -35,7 +35,7 @@ numeric_equal (long double x, long double y) char *term; strtold (string, &term); if (term != string && *(term - 1) == 0) - result |= 2; + result |= 1; } { /* Older glibc and Cygwin mis-parse "-0x". */ @@ -44,7 +44,7 @@ numeric_equal (long double x, long double y) long double value = strtold (string, &term); long double zero = 0.0L; if (1.0L / value != -1.0L / zero || term != (string + 2)) - result |= 4; + result |= 2; } { /* IRIX 6.5, mingw do not parse hex floats. */ @@ -52,7 +52,7 @@ numeric_equal (long double x, long double y) char *term; long double value = strtold (string, &term); if (value != 20.0L || term != (string + 6)) - result |= 8; + result |= 4; } { /* IRIX 6.5 does not parse infinities. HP-UX 11.31/ia64 parses inf, @@ -63,7 +63,7 @@ numeric_equal (long double x, long double y) errno = 0; value = strtold (string, &term); if (value != HUGE_VAL || term != (string + 3) || errno) - result |= 16; + result |= 8; } { /* glibc-2.3.2, IRIX 6.5, mingw, Haiku misparse "nan()". */ @@ -71,7 +71,7 @@ numeric_equal (long double x, long double y) char *term; long double value = strtold (string, &term); if (numeric_equal (value, value) || term != (string + 5)) - result |= 32; + result |= 16; } { /* Mac OS X 10.5, IRIX 6.5 misparse "nan(". */ @@ -79,12 +79,27 @@ numeric_equal (long double x, long double y) char *term; long double value = strtold (string, &term); if (numeric_equal (value, value) || term != (string + 3)) + result |= 32; + } + { + /* In Cygwin 2.9, strtold does not set errno upon underflow. */ + const char *string = "1E-100000"; + char *term; + long double value; + errno = 0; + value = strtold (string, &term); + if (term != (string + 9) || (value == 0.0L && errno != ERANGE)) result |= 64; } return result; ]])], [gl_cv_func_strtold_works=yes], - [gl_cv_func_strtold_works=no], + [if expr $? '>=' 64 >/dev/null; then + gl_cv_func_strtold_works="no (underflow problem)" + else + gl_cv_func_strtold_works=no + fi + ], [dnl The last known bugs in glibc strtold(), as of this writing, dnl were fixed in version 2.8 AC_EGREP_CPP([Lucky user], @@ -101,6 +116,8 @@ numeric_equal (long double x, long double y) [case "$host_os" in # Guess yes on musl systems. *-musl*) gl_cv_func_strtold_works="guessing yes" ;; + # Guess 'no (underflow problem)' on Cygwin. + cygwin*) gl_cv_func_strtold_works="guessing no (underflow problem)" ;; *) gl_cv_func_strtold_works="$gl_cross_guess_normal" ;; esac ]) @@ -110,6 +127,12 @@ numeric_equal (long double x, long double y) *yes) ;; *) REPLACE_STRTOLD=1 + case "$gl_cv_func_strtold_works" in + *"no (underflow problem)") + AC_DEFINE([STRTOLD_HAS_UNDERFLOW_BUG], [1], + [Define to 1 if strtold does not set errno upon underflow.]) + ;; + esac ;; esac fi