From 563abe819af1f885ec595f63e6761cc150dfcf0b Mon Sep 17 00:00:00 2001 From: pjanzen <> Date: Tue, 14 Sep 1999 03:59:55 +0000 Subject: [PATCH] Supply examples and discuss limitations. --- src/lib/libc/stdlib/strtol.3 | 65 ++++++++++++++++++++++++++++++++++- src/lib/libc/stdlib/strtoul.3 | 62 +++++++++++++++++++++++++++++---- 2 files changed, 120 insertions(+), 7 deletions(-) diff --git a/src/lib/libc/stdlib/strtol.3 b/src/lib/libc/stdlib/strtol.3 index e7435cf8..3e0d5e67 100644 --- a/src/lib/libc/stdlib/strtol.3 +++ b/src/lib/libc/stdlib/strtol.3 @@ -33,7 +33,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $OpenBSD: strtol.3,v 1.5 1999/07/20 10:18:22 aaron Exp $ +.\" $OpenBSD: strtol.3,v 1.6 1999/09/14 03:59:55 pjanzen Exp $ .\" .Dd June 25, 1992 .Dt STRTOL 3 @@ -147,6 +147,68 @@ In both cases, .Va errno is set to .Er ERANGE . +.Sh EXAMPLES +Ensuring that a string is a valid number (i.e., in range and containing no +trailing characters) requires clearing +.Va errno +beforehand explicitly since +.Va errno +is not changed on a successful call to +.Fn strtol , +and the return value of +.Fn strtol +cannot be used unambiguously to signal an error: +.Bd -literal -offset indent +char *ep; +long lval; + +\&... + +errno = 0; +lval = strtol(buf, &ep, 10); +if (buf[0] == '\e0' || *ep != '\e0') + goto not_a_number; +if (errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN)) + goto out_of_range; +.Ed +.Pp +This example will accept +.Dq 12 +but not +.Dq 12foo +or +.Dq 12\en . +If trailing whitespace is acceptable, further checks must be done on +.Va *ep ; +alternately, use +.Xr sscanf 3 . +.Pp +If +.Fn strtol +is being used instead of +.Xr atoi 3 , +error checking is further complicated because the desired return value is an +.Li int +rather than a +.Li long ; +however, on some architectures integers and long integers are the same +size. Thus the following is necessary: +.Bd -literal -offset indent +char *ep; +int ival; +long lval; + +\&... + +errno = 0; +lval = strtol(buf, &ep, 10); +if (buf[0] == '\e0' || *ep != '\e0') + goto not_a_number; +if ((errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN)) || + (lval > INT_MAX || lval < INT_MIN)) + goto out_of_range; +ival = lval; +.Ed .Sh ERRORS .Bl -tag -width Er .It Bq Er ERANGE @@ -156,6 +218,7 @@ The given string was out of range; the value converted has been clamped. .Xr atof 3 , .Xr atoi 3 , .Xr atol 3 , +.Xr sscanf 3 , .Xr strtod 3 , .Xr strtoul 3 .Sh STANDARDS diff --git a/src/lib/libc/stdlib/strtoul.3 b/src/lib/libc/stdlib/strtoul.3 index 570e3a9e..80eb0378 100644 --- a/src/lib/libc/stdlib/strtoul.3 +++ b/src/lib/libc/stdlib/strtoul.3 @@ -33,7 +33,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $OpenBSD: strtoul.3,v 1.4 1999/07/20 10:18:21 aaron Exp $ +.\" $OpenBSD: strtoul.3,v 1.5 1999/09/14 03:59:55 pjanzen Exp $ .\" .Dd June 25, 1992 .Dt STRTOUL 3 @@ -134,11 +134,18 @@ on return, the entire string was valid.) The .Fn strtoul function -returns either the result of the conversion -or, if there was a leading minus sign, -the negation of the result of the conversion, -unless the original (non-negated) value would overflow; -in the latter case, +returns the result of the conversion, +unless the value would overflow, in which case +.Dv ULONG_MAX +is returned and +.Va errno +is set to +.Er ERANGE . +If there was a leading minus sign, +.Fn strtoul +returns the (unsigned) negation of the absolute value of the number, unless +the absolute value would overflow. +In this case, .Fn strtoul returns .Dv ULONG_MAX @@ -146,12 +153,55 @@ and sets the global variable .Va errno to .Er ERANGE . +.Pp +There is no way to determine if +.Fn strtoul +has processed a negative number (and returned an unsigned value) short of +examining the string in +.Fa nptr +directly. +.Sh EXAMPLES +Ensuring that a string is a valid number (i.e., in range and containing no +trailing characters) requires clearing +.Va errno +beforehand explicitly since +.Va errno +is not changed on a successful call to +.Fn strtoul , +and the return value of +.Fn strtoul +cannot be used unambiguously to signal an error: +.Bd -literal -offset indent +char *ep; +unsigned long ulval; + +\&... + +errno = 0; +ulval = strtoul(buf, &ep, 10); +if (buf[0] == '\e0' || *ep != '\e0') + goto not_a_number; +if (errno == ERANGE && ulval == ULONG_MAX) + goto out_of_range; +.Ed +.Pp +This example will accept +.Dq 12 +but not +.Dq 12foo +or +.Dq 12\en . +If trailing whitespace is acceptable, further checks must be done on +.Va *ep ; +alternately, use +.Xr sscanf 3 . .Sh ERRORS .Bl -tag -width Er .It Bq Er ERANGE The given string was out of range; the value converted has been clamped. .El .Sh SEE ALSO +.Xr sscanf 3 , .Xr strtol 3 .Sh STANDARDS The