142116Sbostic /* 2*61180Sbostic * Copyright (c) 1990, 1993 3*61180Sbostic * The Regents of the University of California. All rights reserved. 442116Sbostic * 542116Sbostic * %sccs.include.redist.c% 642116Sbostic */ 742116Sbostic 842116Sbostic #if defined(LIBC_SCCS) && !defined(lint) 9*61180Sbostic static char sccsid[] = "@(#)strtoul.c 8.1 (Berkeley) 06/04/93"; 1042116Sbostic #endif /* LIBC_SCCS and not lint */ 1142116Sbostic 1242116Sbostic #include <limits.h> 1342116Sbostic #include <ctype.h> 1442116Sbostic #include <errno.h> 1542179Sbostic #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 strtoul(nptr,endptr,base)2442116Sbosticstrtoul(nptr, endptr, base) 2546599Sdonn const char *nptr; 2646599Sdonn char **endptr; 2742116Sbostic register int base; 2842116Sbostic { 2946599Sdonn register const char *s = nptr; 3042116Sbostic register unsigned long acc; 3142116Sbostic register int c; 3242116Sbostic register unsigned long cutoff; 3342116Sbostic register int neg = 0, any, cutlim; 3442116Sbostic 3542116Sbostic /* 3642116Sbostic * See strtol for comments as to the logic used. 3742116Sbostic */ 3842116Sbostic do { 3942116Sbostic c = *s++; 4042116Sbostic } while (isspace(c)); 4142116Sbostic if (c == '-') { 4242116Sbostic neg = 1; 4342116Sbostic c = *s++; 4442116Sbostic } else if (c == '+') 4542116Sbostic c = *s++; 4642116Sbostic if ((base == 0 || base == 16) && 4742116Sbostic c == '0' && (*s == 'x' || *s == 'X')) { 4842116Sbostic c = s[1]; 4942116Sbostic s += 2; 5042116Sbostic base = 16; 5142116Sbostic } 5242116Sbostic if (base == 0) 5342116Sbostic base = c == '0' ? 8 : 10; 5442116Sbostic cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; 5542116Sbostic cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; 5642116Sbostic for (acc = 0, any = 0;; c = *s++) { 5742116Sbostic if (isdigit(c)) 5842116Sbostic c -= '0'; 5942116Sbostic else if (isalpha(c)) 6042116Sbostic c -= isupper(c) ? 'A' - 10 : 'a' - 10; 6142116Sbostic else 6242116Sbostic break; 6342116Sbostic if (c >= base) 6442116Sbostic break; 6542116Sbostic if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) 6642116Sbostic any = -1; 6742116Sbostic else { 6842116Sbostic any = 1; 6942116Sbostic acc *= base; 7042116Sbostic acc += c; 7142116Sbostic } 7242116Sbostic } 7342116Sbostic if (any < 0) { 7442116Sbostic acc = ULONG_MAX; 7542116Sbostic errno = ERANGE; 7642116Sbostic } else if (neg) 7742116Sbostic acc = -acc; 7842116Sbostic if (endptr != 0) 7958777Storek *endptr = (char *)(any ? s - 1 : nptr); 8042116Sbostic return (acc); 8142116Sbostic } 82