From: Eric Blake Date: Fri, 30 Jul 2010 22:01:41 +0000 (-0600) Subject: strtod: next round of AIX fixes X-Git-Tag: v0.1~3980 X-Git-Url: http://erislabs.net/gitweb/?p=gnulib.git;a=commitdiff_plain;h=e95ae6d7e8f2627cf450649daf30071f1971f404 strtod: next round of AIX fixes * lib/strtod.c (strtod): Work around AIX bug of parsing p with no exponent. * tests/test-strtod.c (main): Enhance tests. * doc/posix-functions/strtod.texi (strtod): Document next bug. Reported by Rainer Tammer. Signed-off-by: Eric Blake --- diff --git a/ChangeLog b/ChangeLog index f43c55ca6..9b86422b0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2010-07-30 Eric Blake + strtod: next round of AIX fixes + * lib/strtod.c (strtod): Work around AIX bug of parsing p with no + exponent. + * tests/test-strtod.c (main): Enhance tests. + * doc/posix-functions/strtod.texi (strtod): Document next bug. + Reported by Rainer Tammer. + futimens: fix configure check * m4/futimens.m4 (gl_FUNC_FUTIMENS): Use correct logic. Reported by Bruno Haible. diff --git a/doc/posix-functions/strtod.texi b/doc/posix-functions/strtod.texi index 767496749..38d68751d 100644 --- a/doc/posix-functions/strtod.texi +++ b/doc/posix-functions/strtod.texi @@ -58,7 +58,13 @@ glibc-2.4, AIX 7.1. @item This function fails to parse C99 hexadecimal floating point on some platforms: -NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw. +NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, +Solaris 10, mingw. + +@item +This function returns the wrong end pointer for @samp{0x1p} on some +platforms: +AIX 7.1. @end itemize Portability problems not fixed by Gnulib: diff --git a/lib/strtod.c b/lib/strtod.c index bd0ff43e7..94eb8175e 100644 --- a/lib/strtod.c +++ b/lib/strtod.c @@ -216,13 +216,23 @@ strtod (const char *nptr, char **endptr) if (c_isdigit (s[*s == '.'])) { /* If a hex float was converted incorrectly, do it ourselves. - If the string starts with "0x", consume the "0" ourselves. */ - if (*s == '0' && c_tolower (s[1]) == 'x' && end <= s + 2) + If the string starts with "0x" but does not contain digits, + consume the "0" ourselves. If a hex float is followed by a + 'p' but no exponent, then adjust the end pointer. */ + if (*s == '0' && c_tolower (s[1]) == 'x') { - if (c_isxdigit (s[2 + (s[2] == '.')])) + if (! c_isxdigit (s[2 + (s[2] == '.')])) + end = s + 1; + else if (end <= s + 2) num = parse_number (s + 2, 16, 2, 4, 'p', &end); else - end = s + 1; + { + const char *p = s + 2; + while (p < end && c_tolower (*p) != 'p') + p++; + if (p < end && ! c_isdigit (p[1 + (p[1] == '-' || p[1] == '+')])) + end = p; + } } s = end; diff --git a/tests/test-strtod.c b/tests/test-strtod.c index 03ec5023a..694e15d96 100644 --- a/tests/test-strtod.c +++ b/tests/test-strtod.c @@ -434,6 +434,17 @@ main (void) ASSERT (errno == 0); } { + const char input[] = "0XP"; + char *ptr; + double result; + errno = 0; + result = strtod (input, &ptr); + ASSERT (result == 0.0); + ASSERT (!signbit (result)); + ASSERT (ptr == input + 1); /* glibc-2.3.6, MacOS X 10.3, FreeBSD 6.2, AIX 7.1 */ + ASSERT (errno == 0); + } + { const char input[] = "0x."; char *ptr; double result; @@ -487,6 +498,16 @@ main (void) ASSERT (ptr == input + 1); ASSERT (errno == 0); } + { + const char input[] = "1P+1"; + char *ptr; + double result; + errno = 0; + result = strtod (input, &ptr); + ASSERT (result == 1.0); + ASSERT (ptr == input + 1); + ASSERT (errno == 0); + } /* Overflow/underflow. */ { @@ -771,6 +792,16 @@ main (void) ASSERT (errno == 0); } { + const char input[] = "0x1P+"; + char *ptr; + double result; + errno = 0; + result = strtod (input, &ptr); + ASSERT (result == 1.0); /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */ + ASSERT (ptr == input + 3); /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */ + ASSERT (errno == 0); + } + { const char input[] = "0x1p+1"; char *ptr; double result; @@ -781,6 +812,16 @@ main (void) ASSERT (errno == 0); } { + const char input[] = "0X1P+1"; + char *ptr; + double result; + errno = 0; + result = strtod (input, &ptr); + ASSERT (result == 2.0); /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */ + ASSERT (ptr == input + 6); /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */ + ASSERT (errno == 0); + } + { const char input[] = "0x1p+1a"; char *ptr; double result;