strtol
Chris Torek
chris at mimsy.UUCP
Tue Jun 20 21:50:16 AEST 1989
In article <13949 at dartvax.Dartmouth.EDU> pete at eleazar.dartmouth.edu
(Peter Robert Schmitt) writes:
>I am looking for any info on the function strtol(). I can't seem to
>find it in the man pages on my BSD4.3. Any help appreciated.
You will find neither information nor source---4BSD does (or rather,
`did') not have strtol(), nor strtoul().
Here they are. These have been tested, although I cannot recall
how strenuously. (As you can see by the copyright date, I wrote them
last year. Why Copyright Regents of UC, rather than UM? Their
license agreement already exists.)
You will have to replace the `#include <limits.h>' line, e.g., with
#define LONG_MIN (-2147483647L - 1)
/* cannot use `-2147483648' as the type of the result is unsigned */
#define LONG_MAX 2147483647L
#define ULONG_MAX ((unsigned long)4294967295)
/* old BSD compiler does not have UL suffix */
although I am no longer sure as to whether the types here are correct
(I seem to recall something about `removing suffixes from limits.h
definitions'). In any case, strto*.c below do not depend on the types
in limits.h, just the values.
: Run this shell script with "sh" not "csh"
PATH=/bin:/usr/bin:/usr/ucb:/etc:$PATH
export PATH
all=false
if [ x$1 = x-a ]; then
all=true
fi
echo Extracting strtol.c
sed 's/^X//' <<'//go.sysin dd *' >strtol.c
X/*
X * Copyright (c) 1988 Regents of the University of California.
X * All rights reserved. The Berkeley software License Agreement
X * specifies the terms and conditions for redistribution.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "%W% (Berkeley) %G%";
X#endif /* LIBC_SCCS and not lint */
X
X#include <limits.h>
X#include <ctype.h>
X#include <errno.h>
X
Xint errno;
X
X/*
X * Convert a string to a long integer.
X *
X * Ignores `locale' stuff. Assumes that the upper and lower case
X * alphabets and digits are each contiguous.
X */
Xlong
Xstrtol(nptr, endptr, base)
X char *nptr, **endptr;
X register int base;
X{
X register char *s = nptr;
X register unsigned long acc;
X register int c;
X register unsigned long cutoff;
X register int neg = 0, any, cutlim;
X
X /*
X * Skip white space and pick up leading +/- sign if any.
X * If base is 0, allow 0x for hex and 0 for octal, else
X * assume decimal; if base is already 16, allow 0x.
X */
X do {
X c = *s++;
X } while (isspace(c));
X if (c == '-') {
X neg = 1;
X c = *s++;
X } else if (c == '+')
X c = *s++;
X if ((base == 0 || base == 16) &&
X c == '0' && (*s == 'x' || *s == 'X')) {
X c = s[1];
X s += 2;
X base = 16;
X }
X if (base == 0)
X base = c == '0' ? 8 : 10;
X
X /*
X * Compute the cutoff value between legal numbers and illegal
X * numbers. That is the largest legal value, divided by the
X * base. An input number that is greater than this value, if
X * followed by a legal input character, is too big. One that
X * is equal to this value may be valid or not; the limit
X * between valid and invalid numbers is then based on the last
X * digit. For instance, if the range for longs is
X * [-2147483648..2147483647] and the input base is 10,
X * cutoff will be set to 214748364 and cutlim to either
X * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
X * a value > 214748364, or equal but the next digit is > 7 (or 8),
X * the number is too big, and we will return a range error.
X *
X * Set any if any `digits' consumed; make it negative to indicate
X * overflow.
X */
X cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
X cutlim = cutoff % (unsigned long)base;
X cutoff /= (unsigned long)base;
X for (acc = 0, any = 0;; c = *s++) {
X if (isdigit(c))
X c -= '0';
X else if (isalpha(c))
X c -= isupper(c) ? 'A' - 10 : 'a' - 10;
X else
X break;
X if (c >= base)
X break;
X if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
X any = -1;
X else {
X any = 1;
X acc *= base;
X acc += c;
X }
X }
X if (any < 0) {
X acc = neg ? LONG_MIN : LONG_MAX;
X errno = ERANGE;
X } else if (neg)
X acc = -acc;
X if (endptr != 0)
X *endptr = any ? s - 1 : nptr;
X return (acc);
X}
//go.sysin dd *
if [ `wc -c < strtol.c` != 2648 ]; then
made=false
echo error transmitting strtol.c --
echo length should be 2648, not `wc -c < strtol.c`
else
made=true
fi
if $made; then
chmod 644 strtol.c
echo -n ' '; ls -ld strtol.c
fi
echo Extracting strtoul.c
sed 's/^X//' <<'//go.sysin dd *' >strtoul.c
X/*
X * Copyright (c) 1988 Regents of the University of California.
X * All rights reserved. The Berkeley software License Agreement
X * specifies the terms and conditions for redistribution.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "%W% (Berkeley) %G%";
X#endif /* LIBC_SCCS and not lint */
X
X#include <limits.h>
X#include <ctype.h>
X#include <errno.h>
X
Xint errno;
X
X/*
X * Convert a string to an unsigned long integer.
X *
X * Ignores `locale' stuff. Assumes that the upper and lower case
X * alphabets and digits are each contiguous.
X */
Xunsigned long
Xstrtoul(nptr, endptr, base)
X char *nptr, **endptr;
X register int base;
X{
X register char *s = nptr;
X register unsigned long acc;
X register int c;
X register unsigned long cutoff;
X register int neg = 0, any, cutlim;
X
X /*
X * See strtol for comments as to the logic used.
X */
X do {
X c = *s++;
X } while (isspace(c));
X if (c == '-') {
X neg = 1;
X c = *s++;
X } else if (c == '+')
X c = *s++;
X if ((base == 0 || base == 16) &&
X c == '0' && (*s == 'x' || *s == 'X')) {
X c = s[1];
X s += 2;
X base = 16;
X }
X if (base == 0)
X base = c == '0' ? 8 : 10;
X cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
X cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
X for (acc = 0, any = 0;; c = *s++) {
X if (isdigit(c))
X c -= '0';
X else if (isalpha(c))
X c -= isupper(c) ? 'A' - 10 : 'a' - 10;
X else
X break;
X if (c >= base)
X break;
X if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
X any = -1;
X else {
X any = 1;
X acc *= base;
X acc += c;
X }
X }
X if (any < 0) {
X acc = ULONG_MAX;
X errno = ERANGE;
X } else if (neg)
X acc = -acc;
X if (endptr != 0)
X *endptr = any ? s - 1 : nptr;
X return (acc);
X}
//go.sysin dd *
if [ `wc -c < strtoul.c` != 1697 ]; then
made=false
echo error transmitting strtoul.c --
echo length should be 1697, not `wc -c < strtoul.c`
else
made=true
fi
if $made; then
chmod 644 strtoul.c
echo -n ' '; ls -ld strtoul.c
fi
--
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain: chris at mimsy.umd.edu Path: uunet!mimsy!chris
More information about the Comp.unix.questions
mailing list