Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!rutgers!mailrus!csd4.milw.wisc.edu!uxc.cso.uiuc.edu!tank!mimsy!chris From: chris@mimsy.UUCP (Chris Torek) Newsgroups: comp.unix.questions Subject: Re: strtol Message-ID: <18164@mimsy.UUCP> Date: 20 Jun 89 11:50:16 GMT References: <13949@dartvax.Dartmouth.EDU> Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742 Lines: 245 In article <13949@dartvax.Dartmouth.EDU> pete@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 ' 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 X#include X#include 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 X#include X#include 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@mimsy.umd.edu Path: uunet!mimsy!chris