142116Sbostic /* 242116Sbostic * Copyright (c) 1990 Regents of the University of California. 342116Sbostic * All rights reserved. 442116Sbostic * 542116Sbostic * %sccs.include.redist.c% 642116Sbostic */ 742116Sbostic 842116Sbostic #if defined(LIBC_SCCS) && !defined(lint) 9*42179Sbostic static char sccsid[] = "@(#)strtoul.c 5.2 (Berkeley) 05/17/90"; 1042116Sbostic #endif /* LIBC_SCCS and not lint */ 1142116Sbostic 1242116Sbostic #include <limits.h> 1342116Sbostic #include <ctype.h> 1442116Sbostic #include <errno.h> 15*42179Sbostic #include <stdlib.h> 1642116Sbostic 1742116Sbostic /* 1842116Sbostic * Convert a string to an unsigned long integer. 1942116Sbostic * 2042116Sbostic * Ignores `locale' stuff. Assumes that the upper and lower case 2142116Sbostic * alphabets and digits are each contiguous. 2242116Sbostic */ 2342116Sbostic unsigned long 2442116Sbostic strtoul(nptr, endptr, base) 2542116Sbostic char *nptr, **endptr; 2642116Sbostic register int base; 2742116Sbostic { 2842116Sbostic register char *s = nptr; 2942116Sbostic register unsigned long acc; 3042116Sbostic register int c; 3142116Sbostic register unsigned long cutoff; 3242116Sbostic register int neg = 0, any, cutlim; 3342116Sbostic 3442116Sbostic /* 3542116Sbostic * See strtol for comments as to the logic used. 3642116Sbostic */ 3742116Sbostic do { 3842116Sbostic c = *s++; 3942116Sbostic } while (isspace(c)); 4042116Sbostic if (c == '-') { 4142116Sbostic neg = 1; 4242116Sbostic c = *s++; 4342116Sbostic } else if (c == '+') 4442116Sbostic c = *s++; 4542116Sbostic if ((base == 0 || base == 16) && 4642116Sbostic c == '0' && (*s == 'x' || *s == 'X')) { 4742116Sbostic c = s[1]; 4842116Sbostic s += 2; 4942116Sbostic base = 16; 5042116Sbostic } 5142116Sbostic if (base == 0) 5242116Sbostic base = c == '0' ? 8 : 10; 5342116Sbostic cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; 5442116Sbostic cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; 5542116Sbostic for (acc = 0, any = 0;; c = *s++) { 5642116Sbostic if (isdigit(c)) 5742116Sbostic c -= '0'; 5842116Sbostic else if (isalpha(c)) 5942116Sbostic c -= isupper(c) ? 'A' - 10 : 'a' - 10; 6042116Sbostic else 6142116Sbostic break; 6242116Sbostic if (c >= base) 6342116Sbostic break; 6442116Sbostic if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) 6542116Sbostic any = -1; 6642116Sbostic else { 6742116Sbostic any = 1; 6842116Sbostic acc *= base; 6942116Sbostic acc += c; 7042116Sbostic } 7142116Sbostic } 7242116Sbostic if (any < 0) { 7342116Sbostic acc = ULONG_MAX; 7442116Sbostic errno = ERANGE; 7542116Sbostic } else if (neg) 7642116Sbostic acc = -acc; 7742116Sbostic if (endptr != 0) 7842116Sbostic *endptr = any ? s - 1 : nptr; 7942116Sbostic return (acc); 8042116Sbostic } 81