Impliment the ISO-C99 strto[u]ll()
and rewrite strto[u]q() in terms of it.
This commit is contained in:
parent
1b0dabf0c0
commit
4c0440cb86
@ -104,8 +104,12 @@ void *realloc __P((void *, size_t));
|
||||
void srand __P((unsigned));
|
||||
double strtod __P((const char *, char **));
|
||||
long strtol __P((const char *, char **, int));
|
||||
long long
|
||||
strtoll __P((const char *, char **, int));
|
||||
unsigned long
|
||||
strtoul __P((const char *, char **, int));
|
||||
unsigned long long
|
||||
strtoull __P((const char *, char **, int));
|
||||
int system __P((const char *));
|
||||
|
||||
int mblen __P((const char *, size_t));
|
||||
|
@ -7,8 +7,9 @@
|
||||
MISRCS+=abort.c abs.c atexit.c atof.c atoi.c atol.c bsearch.c calloc.c div.c \
|
||||
exit.c getenv.c getopt.c getsubopt.c heapsort.c labs.c ldiv.c \
|
||||
malloc.c merge.c putenv.c qsort.c radixsort.c rand.c random.c \
|
||||
reallocf.c realpath.c setenv.c strhash.c strtol.c strtoq.c strtoul.c \
|
||||
strtouq.c system.c tdelete.c tfind.c tsearch.c twalk.c
|
||||
reallocf.c realpath.c setenv.c strhash.c strtol.c strtoll.c strtoq.c \
|
||||
strtoul.c strtoull.c strtouq.c system.c tdelete.c tfind.c tsearch.c \
|
||||
twalk.c
|
||||
|
||||
.if ${MACHINE_ARCH} == "alpha"
|
||||
# XXX Temporary until the assumption that a long is 32-bits is resolved
|
||||
@ -33,7 +34,7 @@ MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3
|
||||
MLINKS+=rand.3 rand_r.3 rand.3 srand.3
|
||||
MLINKS+=random.3 initstate.3 random.3 setstate.3 random.3 srandom.3 \
|
||||
random.3 srandomdev.3
|
||||
MLINKS+=strtol.3 strtoq.3
|
||||
MLINKS+=strtoul.3 strtouq.3
|
||||
MLINKS+=strtol.3 strtoll.3 strtol.3 strtoq.3
|
||||
MLINKS+=strtoul.3 strtoull.3 strtoul.3 strtouq.3
|
||||
MLINKS+=malloc.3 calloc.3 malloc.3 free.3 malloc.3 realloc.3 malloc.3 reallocf.3
|
||||
.endif
|
||||
|
@ -40,8 +40,8 @@
|
||||
.Dt STRTOL 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm strtol , strtoq
|
||||
.Nd convert string value to a long or quad_t integer
|
||||
.Nm strtol , strtoll , strtoq
|
||||
.Nd convert string value to a long , long long , or quad_t integer
|
||||
.Sh LIBRARY
|
||||
.Lb libc
|
||||
.Sh SYNOPSIS
|
||||
@ -49,6 +49,8 @@
|
||||
.Fd #include <limits.h>
|
||||
.Ft long
|
||||
.Fn strtol "const char *nptr" "char **endptr" "int base"
|
||||
.Ft long long
|
||||
.Fn strtoll "const char *nptr" "char **endptr" "int base"
|
||||
.Fd #include <sys/types.h>
|
||||
.Fd #include <stdlib.h>
|
||||
.Fd #include <limits.h>
|
||||
@ -64,6 +66,14 @@ to a
|
||||
.Em long
|
||||
value.
|
||||
The
|
||||
.Fn strtoll
|
||||
function
|
||||
converts the string in
|
||||
.Fa nptr
|
||||
to a
|
||||
.Em long long
|
||||
value.
|
||||
The
|
||||
.Fn strtoq
|
||||
function
|
||||
converts the string in
|
||||
@ -145,7 +155,20 @@ If an overflow occurs,
|
||||
.Fn strtol
|
||||
returns
|
||||
.Dv LONG_MAX .
|
||||
In both cases,
|
||||
The
|
||||
.Fn strtoll
|
||||
function
|
||||
returns the result of the conversion,
|
||||
unless the value would underflow or overflow.
|
||||
If an underflow occurs,
|
||||
.Fn strtoll
|
||||
returns
|
||||
.Dv LLONG_MIN .
|
||||
If an overflow occurs,
|
||||
.Fn strtoll
|
||||
returns
|
||||
.Dv LLONG_MAX .
|
||||
In all cases,
|
||||
.Va errno
|
||||
is set to
|
||||
.Er ERANGE .
|
||||
@ -166,5 +189,13 @@ The
|
||||
function
|
||||
conforms to
|
||||
.St -isoC .
|
||||
The
|
||||
.Fn strtoll
|
||||
function
|
||||
conforms to
|
||||
.St -isoC-99 .
|
||||
The BSD
|
||||
.Fn strtoq
|
||||
function is deprecated.
|
||||
.Sh BUGS
|
||||
Ignores the current locale.
|
||||
|
@ -35,6 +35,11 @@
|
||||
static char sccsid[] = "@(#)strtoq.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#ifndef lint
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <limits.h>
|
||||
@ -43,21 +48,21 @@ static char sccsid[] = "@(#)strtoq.c 8.1 (Berkeley) 6/4/93";
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
* Convert a string to a quad integer.
|
||||
* Convert a string to a long long integer.
|
||||
*
|
||||
* Ignores `locale' stuff. Assumes that the upper and lower case
|
||||
* alphabets and digits are each contiguous.
|
||||
*/
|
||||
quad_t
|
||||
strtoq(nptr, endptr, base)
|
||||
long long
|
||||
strtoll(nptr, endptr, base)
|
||||
const char *nptr;
|
||||
char **endptr;
|
||||
register int base;
|
||||
{
|
||||
register const char *s;
|
||||
register u_quad_t acc;
|
||||
register unsigned long long acc;
|
||||
register unsigned char c;
|
||||
register u_quad_t qbase, cutoff;
|
||||
register unsigned long long qbase, cutoff;
|
||||
register int neg, any, cutlim;
|
||||
|
||||
/*
|
||||
@ -105,7 +110,8 @@ strtoq(nptr, endptr, base)
|
||||
* overflow.
|
||||
*/
|
||||
qbase = (unsigned)base;
|
||||
cutoff = neg ? (u_quad_t)-(QUAD_MIN + QUAD_MAX) + QUAD_MAX : QUAD_MAX;
|
||||
cutoff = neg ? (unsigned long long)-(LLONG_MIN + LLONG_MAX) + LLONG_MAX
|
||||
: LLONG_MAX;
|
||||
cutlim = cutoff % qbase;
|
||||
cutoff /= qbase;
|
||||
for (acc = 0, any = 0;; c = *s++) {
|
||||
@ -128,7 +134,7 @@ strtoq(nptr, endptr, base)
|
||||
}
|
||||
}
|
||||
if (any < 0) {
|
||||
acc = neg ? QUAD_MIN : QUAD_MAX;
|
||||
acc = neg ? LLONG_MIN : LLONG_MAX;
|
||||
errno = ERANGE;
|
||||
} else if (neg)
|
||||
acc = -acc;
|
||||
|
@ -35,11 +35,11 @@
|
||||
static char sccsid[] = "@(#)strtoq.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifndef lint
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
@ -52,87 +52,8 @@ quad_t
|
||||
strtoq(nptr, endptr, base)
|
||||
const char *nptr;
|
||||
char **endptr;
|
||||
register int base;
|
||||
int base;
|
||||
{
|
||||
register const char *s;
|
||||
register u_quad_t acc;
|
||||
register unsigned char c;
|
||||
register u_quad_t qbase, cutoff;
|
||||
register int neg, any, cutlim;
|
||||
|
||||
/*
|
||||
* Skip white space and pick up leading +/- sign if any.
|
||||
* If base is 0, allow 0x for hex and 0 for octal, else
|
||||
* assume decimal; if base is already 16, allow 0x.
|
||||
*/
|
||||
s = nptr;
|
||||
do {
|
||||
c = *s++;
|
||||
} while (isspace(c));
|
||||
if (c == '-') {
|
||||
neg = 1;
|
||||
c = *s++;
|
||||
} else {
|
||||
neg = 0;
|
||||
if (c == '+')
|
||||
c = *s++;
|
||||
}
|
||||
if ((base == 0 || base == 16) &&
|
||||
c == '0' && (*s == 'x' || *s == 'X')) {
|
||||
c = s[1];
|
||||
s += 2;
|
||||
base = 16;
|
||||
}
|
||||
if (base == 0)
|
||||
base = c == '0' ? 8 : 10;
|
||||
|
||||
/*
|
||||
* Compute the cutoff value between legal numbers and illegal
|
||||
* numbers. That is the largest legal value, divided by the
|
||||
* base. An input number that is greater than this value, if
|
||||
* followed by a legal input character, is too big. One that
|
||||
* is equal to this value may be valid or not; the limit
|
||||
* between valid and invalid numbers is then based on the last
|
||||
* digit. For instance, if the range for quads is
|
||||
* [-9223372036854775808..9223372036854775807] and the input base
|
||||
* is 10, cutoff will be set to 922337203685477580 and cutlim to
|
||||
* either 7 (neg==0) or 8 (neg==1), meaning that if we have
|
||||
* accumulated a value > 922337203685477580, or equal but the
|
||||
* next digit is > 7 (or 8), the number is too big, and we will
|
||||
* return a range error.
|
||||
*
|
||||
* Set any if any `digits' consumed; make it negative to indicate
|
||||
* overflow.
|
||||
*/
|
||||
qbase = (unsigned)base;
|
||||
cutoff = neg ? (u_quad_t)-(QUAD_MIN + QUAD_MAX) + QUAD_MAX : QUAD_MAX;
|
||||
cutlim = cutoff % qbase;
|
||||
cutoff /= qbase;
|
||||
for (acc = 0, any = 0;; c = *s++) {
|
||||
if (!isascii(c))
|
||||
break;
|
||||
if (isdigit(c))
|
||||
c -= '0';
|
||||
else if (isalpha(c))
|
||||
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
|
||||
else
|
||||
break;
|
||||
if (c >= base)
|
||||
break;
|
||||
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
|
||||
any = -1;
|
||||
else {
|
||||
any = 1;
|
||||
acc *= qbase;
|
||||
acc += c;
|
||||
}
|
||||
}
|
||||
if (any < 0) {
|
||||
acc = neg ? QUAD_MIN : QUAD_MAX;
|
||||
errno = ERANGE;
|
||||
} else if (neg)
|
||||
acc = -acc;
|
||||
if (endptr != 0)
|
||||
*endptr = (char *)(any ? s - 1 : nptr);
|
||||
return (acc);
|
||||
return strtoll(nptr, endptr, base);
|
||||
}
|
||||
|
@ -40,8 +40,8 @@
|
||||
.Dt STRTOUL 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm strtoul , strtouq
|
||||
.Nd "convert a string to an unsigned long or uquad_t integer"
|
||||
.Nm strtoul , strtoull , strtouq
|
||||
.Nd "convert a string to an unsigned long , unsigned long long , or uquad_t integer"
|
||||
.Sh LIBRARY
|
||||
.Lb libc
|
||||
.Sh SYNOPSIS
|
||||
@ -49,6 +49,8 @@
|
||||
.Fd #include <limits.h>
|
||||
.Ft unsigned long
|
||||
.Fn strtoul "const char *nptr" "char **endptr" "int base"
|
||||
.Ft unsigned long long
|
||||
.Fn strtoull "const char *nptr" "char **endptr" "int base"
|
||||
.Fd #include <sys/types.h>
|
||||
.Fd #include <stdlib.h>
|
||||
.Fd #include <limits.h>
|
||||
@ -64,6 +66,14 @@ to an
|
||||
.Em unsigned long
|
||||
value.
|
||||
The
|
||||
.Fn strtoull
|
||||
function
|
||||
converts the string in
|
||||
.Fa nptr
|
||||
to an
|
||||
.Em unsigned long long
|
||||
value.
|
||||
The
|
||||
.Fn strtouq
|
||||
function
|
||||
converts the string in
|
||||
@ -143,10 +153,21 @@ unless the original (non-negated) value would overflow;
|
||||
in the latter case,
|
||||
.Fn strtoul
|
||||
returns
|
||||
.Dv ULONG_MAX
|
||||
and sets the global variable
|
||||
.Dv ULONG_MAX .
|
||||
The
|
||||
.Fn strtoull
|
||||
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,
|
||||
.Fn strtoull
|
||||
returns
|
||||
.Dv ULLONG_MAX .
|
||||
In all cases,
|
||||
.Va errno
|
||||
to
|
||||
is set to
|
||||
.Er ERANGE .
|
||||
.Sh ERRORS
|
||||
.Bl -tag -width Er
|
||||
@ -161,5 +182,13 @@ The
|
||||
function
|
||||
conforms to
|
||||
.St -isoC .
|
||||
The
|
||||
.Fn strtoull
|
||||
function
|
||||
conforms to
|
||||
.St -isoC-99 .
|
||||
The BSD
|
||||
.Fn strtoq
|
||||
function is deprecated.
|
||||
.Sh BUGS
|
||||
Ignores the current locale.
|
||||
|
@ -35,6 +35,11 @@
|
||||
static char sccsid[] = "@(#)strtouq.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#ifndef lint
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <limits.h>
|
||||
@ -43,21 +48,21 @@ static char sccsid[] = "@(#)strtouq.c 8.1 (Berkeley) 6/4/93";
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
* Convert a string to an unsigned quad integer.
|
||||
* Convert a string to an unsigned long long integer.
|
||||
*
|
||||
* Ignores `locale' stuff. Assumes that the upper and lower case
|
||||
* alphabets and digits are each contiguous.
|
||||
*/
|
||||
u_quad_t
|
||||
strtouq(nptr, endptr, base)
|
||||
unsigned long long
|
||||
strtoull(nptr, endptr, base)
|
||||
const char *nptr;
|
||||
char **endptr;
|
||||
register int base;
|
||||
{
|
||||
register const char *s = nptr;
|
||||
register u_quad_t acc;
|
||||
register unsigned long long acc;
|
||||
register unsigned char c;
|
||||
register u_quad_t qbase, cutoff;
|
||||
register unsigned long long qbase, cutoff;
|
||||
register int neg, any, cutlim;
|
||||
|
||||
/*
|
||||
@ -84,8 +89,8 @@ strtouq(nptr, endptr, base)
|
||||
if (base == 0)
|
||||
base = c == '0' ? 8 : 10;
|
||||
qbase = (unsigned)base;
|
||||
cutoff = (u_quad_t)UQUAD_MAX / qbase;
|
||||
cutlim = (u_quad_t)UQUAD_MAX % qbase;
|
||||
cutoff = (unsigned long long)ULLONG_MAX / qbase;
|
||||
cutlim = (unsigned long long)ULLONG_MAX % qbase;
|
||||
for (acc = 0, any = 0;; c = *s++) {
|
||||
if (!isascii(c))
|
||||
break;
|
||||
@ -106,7 +111,7 @@ strtouq(nptr, endptr, base)
|
||||
}
|
||||
}
|
||||
if (any < 0) {
|
||||
acc = UQUAD_MAX;
|
||||
acc = ULLONG_MAX;
|
||||
errno = ERANGE;
|
||||
} else if (neg)
|
||||
acc = -acc;
|
||||
|
@ -35,11 +35,11 @@
|
||||
static char sccsid[] = "@(#)strtouq.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifndef lint
|
||||
static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
@ -52,65 +52,8 @@ u_quad_t
|
||||
strtouq(nptr, endptr, base)
|
||||
const char *nptr;
|
||||
char **endptr;
|
||||
register int base;
|
||||
int base;
|
||||
{
|
||||
register const char *s = nptr;
|
||||
register u_quad_t acc;
|
||||
register unsigned char c;
|
||||
register u_quad_t qbase, cutoff;
|
||||
register int neg, any, cutlim;
|
||||
|
||||
/*
|
||||
* See strtoq for comments as to the logic used.
|
||||
*/
|
||||
s = nptr;
|
||||
do {
|
||||
c = *s++;
|
||||
} while (isspace(c));
|
||||
if (c == '-') {
|
||||
neg = 1;
|
||||
c = *s++;
|
||||
} else {
|
||||
neg = 0;
|
||||
if (c == '+')
|
||||
c = *s++;
|
||||
}
|
||||
if ((base == 0 || base == 16) &&
|
||||
c == '0' && (*s == 'x' || *s == 'X')) {
|
||||
c = s[1];
|
||||
s += 2;
|
||||
base = 16;
|
||||
}
|
||||
if (base == 0)
|
||||
base = c == '0' ? 8 : 10;
|
||||
qbase = (unsigned)base;
|
||||
cutoff = (u_quad_t)UQUAD_MAX / qbase;
|
||||
cutlim = (u_quad_t)UQUAD_MAX % qbase;
|
||||
for (acc = 0, any = 0;; c = *s++) {
|
||||
if (!isascii(c))
|
||||
break;
|
||||
if (isdigit(c))
|
||||
c -= '0';
|
||||
else if (isalpha(c))
|
||||
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
|
||||
else
|
||||
break;
|
||||
if (c >= base)
|
||||
break;
|
||||
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
|
||||
any = -1;
|
||||
else {
|
||||
any = 1;
|
||||
acc *= qbase;
|
||||
acc += c;
|
||||
}
|
||||
}
|
||||
if (any < 0) {
|
||||
acc = UQUAD_MAX;
|
||||
errno = ERANGE;
|
||||
} else if (neg)
|
||||
acc = -acc;
|
||||
if (endptr != 0)
|
||||
*endptr = (char *)(any ? s - 1 : nptr);
|
||||
return (acc);
|
||||
return strtoull(nptr, endptr, base);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user