Module Name: src Committed By: snj Date: Sun Dec 18 06:31:01 UTC 2016
Modified Files: src/lib/libc/stdlib [netbsd-7]: strtod.3 strtol.3 strtoul.3 Log Message: Pull up following revision(s) (requested by riastradh in ticket #1311): lib/libc/stdlib/strtod.3: revisions 1.21-1.29 lib/libc/stdlib/strtol.3: revision 1.36-1.38 lib/libc/stdlib/strtoul.3: revision 1.36 strtod yields ERANGE for below-subnormal magnitudes, not underflow. For a floating-point computation, in the language of IEEE 754, `underflow' means the output was rounded and is too small to be represented *normally*. There are many nonzero floating-point numbers to which the exact output may have been rounded -- namely subnormals. The condition under which strtod returns ERANGE for small magnitudes is when the magnitude of the exact result is so small it is rounded to zero, not even to a subnormal. While here, use parallel language about large magnitudes instead of the (albeit correct) word `overflow', to avoid temptation to treat `underflow' as the opposite notion with zero instead of infinity. -- Bump date for previous. -- Fix description of ERANGE cases again. Do use the technical terms `overflow' and `underflow', because strtod sets ERANGE precisely to indicate either of these two conditions, and they are the right keywords that one might be looking for. Note that strtod may set ERANGE even if it returns noninfinity and nonzero -- specifically, if the result is subnormal. This part was wrong before I `fixed' it and remained wrong after I `fixed' it earlier this year. -- Add example for strtod. This illustrates all the cases you might be interested in and asserts theorems in those cases. -- Fix infinity detection with isinf(d), not d == HUGE_VAL. Negative infinity counts as overflow too. Simplify. -- EXIT_FAILURE police -- Distinguish altogether invalid syntax from trailing garbage. -- Distinguish invalid syntax from trailing garbage cases. Clarify. -- Simplify error condition case. Add assertions to reflect its implications. -- Tidy up the second example too. -- Update strtoul(3) example to reflect clarifications in strtol(3). -- Fix phrasing about `out-of-band' and `sentinel value'. Either an out-of-band channel, or an in-band sentinel value, could indicate an error, but an out-of-band sentinel value is a silly proposition. Noted by uwe@. -- Use the keywords `underflow' and `overflow' in ERANGE summary. To generate a diff of this commit: cvs rdiff -u -r1.20 -r1.20.50.1 src/lib/libc/stdlib/strtod.3 cvs rdiff -u -r1.26.24.2 -r1.26.24.3 src/lib/libc/stdlib/strtol.3 cvs rdiff -u -r1.25.24.2 -r1.25.24.3 src/lib/libc/stdlib/strtoul.3 Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libc/stdlib/strtod.3 diff -u src/lib/libc/stdlib/strtod.3:1.20 src/lib/libc/stdlib/strtod.3:1.20.50.1 --- src/lib/libc/stdlib/strtod.3:1.20 Wed Oct 24 13:42:10 2007 +++ src/lib/libc/stdlib/strtod.3 Sun Dec 18 06:31:01 2016 @@ -1,4 +1,4 @@ -.\" $NetBSD: strtod.3,v 1.20 2007/10/24 13:42:10 reed Exp $ +.\" $NetBSD: strtod.3,v 1.20.50.1 2016/12/18 06:31:01 snj Exp $ .\" .\" Copyright (c) 1990, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -33,7 +33,7 @@ .\" .\" from: @(#)strtod.3 8.1 (Berkeley) 6/4/93 .\" -.Dd March 12, 2006 +.Dd November 4, 2016 .Dt STRTOD 3 .Os .Sh NAME @@ -151,7 +151,9 @@ If no conversion is performed, zero is r is stored in the location referenced by .Fa endptr . .Pp -If the correct value would cause overflow, plus or minus +If the correct value is too large in magnitude to be represented +.Pq Sq overflow , +plus or minus .Dv HUGE_VAL , .Dv HUGE_VALF , or @@ -160,15 +162,58 @@ is returned (according to the return typ .Dv ERANGE is stored in .Va errno . -If the correct value would cause underflow, zero is -returned and +.Pp +If the correct value is too small in magnitude to be represented +normally with full precision +.Pq Sq underflow , +the closest subnormal value, or zero, is returned, and .Dv ERANGE is stored in .Va errno . +.Sh EXAMPLES +Since there is no out-of-band channel or sentinel value to indicate an +error, callers who wish to know whether there was overflow or underflow +must set +.Va errno +to zero before calling +.Fn strtod , +.Fn strtof , +or +.Fn strtold ; +in the case of no underflow or overflow, these functions preserve +.Va errno . +.Pp +To check for syntax errors, callers must +.Em also +check whether +.Fa endptr +was updated to reflect the true end of the string in order to determine +whether the full string was consumed or whether there were additional +erroneous characters in it. +.Bd -literal -offset abcd +char *end; +double d; + +\&... + +errno = 0; +d = strtod(s, &end); +if (end == s) + errx(EXIT_FAILURE, "invalid syntax"); +if (end[0] != '\e0') + errx(EXIT_FAILURE, "trailing garbage"); +if (errno) { + assert(errno == ERANGE); + assert(isinf(d) || d == 0 || + fpclassify(d) == FP_SUBNORMAL); + warnx("%s", isinf(d) ? "overflow" : "underflow"); +} +/* d is the best floating-point approximation to the number in s */ +.Ed .Sh ERRORS .Bl -tag -width Er .It Bq Er ERANGE -Overflow or underflow occurred. +The conversion resulted in floating-point underflow or overflow. .El .Sh SEE ALSO .Xr atof 3 , Index: src/lib/libc/stdlib/strtol.3 diff -u src/lib/libc/stdlib/strtol.3:1.26.24.2 src/lib/libc/stdlib/strtol.3:1.26.24.3 --- src/lib/libc/stdlib/strtol.3:1.26.24.2 Sat May 16 17:58:46 2015 +++ src/lib/libc/stdlib/strtol.3 Sun Dec 18 06:31:01 2016 @@ -1,4 +1,4 @@ -.\" $NetBSD: strtol.3,v 1.26.24.2 2015/05/16 17:58:46 snj Exp $ +.\" $NetBSD: strtol.3,v 1.26.24.3 2016/12/18 06:31:01 snj Exp $ .\" .\" Copyright (c) 1990, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -213,10 +213,15 @@ long lval; errno = 0; lval = strtol(buf, \*[Am]ep, 10); -if (buf[0] == '\e0' || *ep != '\e0') +if (ep == buf) goto not_a_number; -if (errno == ERANGE \*[Am]\*[Am] (lval == LONG_MAX || lval == LONG_MIN)) +if (*ep != '\e0') + goto trailing_garbage; +if (errno) { + assert(errno == ERANGE); + assert(lval == LONG_MAX || lval == LONG_MIN); goto out_of_range; +} .Ed .Pp This example will accept @@ -249,11 +254,15 @@ long lval; errno = 0; lval = strtol(buf, \*[Am]ep, 10); -if (buf[0] == '\e0' || *ep != '\e0') +if (ep == buf) goto not_a_number; -if ((errno == ERANGE \*[Am]\*[Am] (lval == LONG_MAX || lval == LONG_MIN)) || - (lval \*[Gt] INT_MAX || lval \*[Lt] INT_MIN)) +if (*ep != '\e0') + goto trailing_garbage; +if (errno == ERANGE || lval < INT_MIN || INT_MAX < lval) goto out_of_range; +assert(errno == 0); +assert(INT_MIN <= lval); +assert(lval <= INT_MAX); ival = lval; .Ed .Sh ERRORS Index: src/lib/libc/stdlib/strtoul.3 diff -u src/lib/libc/stdlib/strtoul.3:1.25.24.2 src/lib/libc/stdlib/strtoul.3:1.25.24.3 --- src/lib/libc/stdlib/strtoul.3:1.25.24.2 Sat May 16 17:58:47 2015 +++ src/lib/libc/stdlib/strtoul.3 Sun Dec 18 06:31:01 2016 @@ -1,4 +1,4 @@ -.\" $NetBSD: strtoul.3,v 1.25.24.2 2015/05/16 17:58:47 snj Exp $ +.\" $NetBSD: strtoul.3,v 1.25.24.3 2016/12/18 06:31:01 snj Exp $ .\" .\" Copyright (c) 1990, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -215,10 +215,15 @@ unsigned long ulval; errno = 0; ulval = strtoul(buf, \*[Am]ep, 10); -if (buf[0] == '\e0' || *ep != '\e0') +if (ep == buf) goto not_a_number; -if (errno == ERANGE \*[Am]\*[Am] ulval == ULONG_MAX) +if (*ep != '\e0') + goto trailing_garbage; +if (errno) { + assert(errno == ERANGE); + assert(ulval == ULONG_MAX); goto out_of_range; +} .Ed .Pp This example will accept