1*54496Sbostic /*- 2*54496Sbostic * Copyright (c) 1992 The Regents of the University of California. 3*54496Sbostic * All rights reserved. 4*54496Sbostic * 5*54496Sbostic * %sccs.include.redist.c% 6*54496Sbostic */ 7*54496Sbostic 8*54496Sbostic #if defined(LIBC_SCCS) && !defined(lint) 9*54496Sbostic static char sccsid[] = "@(#)strtouq.c 5.1 (Berkeley) 06/26/92"; 10*54496Sbostic #endif /* LIBC_SCCS and not lint */ 11*54496Sbostic 12*54496Sbostic #include <sys/types.h> 13*54496Sbostic 14*54496Sbostic #include <limits.h> 15*54496Sbostic #include <errno.h> 16*54496Sbostic #include <ctype.h> 17*54496Sbostic #include <stdlib.h> 18*54496Sbostic 19*54496Sbostic /* 20*54496Sbostic * Convert a string to an unsigned quad integer. 21*54496Sbostic * 22*54496Sbostic * Ignores `locale' stuff. Assumes that the upper and lower case 23*54496Sbostic * alphabets and digits are each contiguous. 24*54496Sbostic */ 25*54496Sbostic u_quad_t 26*54496Sbostic strtouq(nptr, endptr, base) 27*54496Sbostic const char *nptr; 28*54496Sbostic char **endptr; 29*54496Sbostic register int base; 30*54496Sbostic { 31*54496Sbostic register const char *s = nptr; 32*54496Sbostic register u_quad_t acc; 33*54496Sbostic register int c; 34*54496Sbostic register u_quad_t qbase, cutoff; 35*54496Sbostic register int neg, any, cutlim; 36*54496Sbostic 37*54496Sbostic /* 38*54496Sbostic * See strtoq for comments as to the logic used. 39*54496Sbostic */ 40*54496Sbostic s = nptr; 41*54496Sbostic do { 42*54496Sbostic c = *s++; 43*54496Sbostic } while (isspace(c)); 44*54496Sbostic if (c == '-') { 45*54496Sbostic neg = 1; 46*54496Sbostic c = *s++; 47*54496Sbostic } else { 48*54496Sbostic neg = 0; 49*54496Sbostic if (c == '+') 50*54496Sbostic c = *s++; 51*54496Sbostic } 52*54496Sbostic if ((base == 0 || base == 16) && 53*54496Sbostic c == '0' && (*s == 'x' || *s == 'X')) { 54*54496Sbostic c = s[1]; 55*54496Sbostic s += 2; 56*54496Sbostic base = 16; 57*54496Sbostic } 58*54496Sbostic if (base == 0) 59*54496Sbostic base = c == '0' ? 8 : 10; 60*54496Sbostic qbase = (unsigned)base; 61*54496Sbostic cutoff = (u_quad_t)UQUAD_MAX / qbase; 62*54496Sbostic cutlim = (u_quad_t)UQUAD_MAX % qbase; 63*54496Sbostic for (acc = 0, any = 0;; c = *s++) { 64*54496Sbostic if (isdigit(c)) 65*54496Sbostic c -= '0'; 66*54496Sbostic else if (isalpha(c)) 67*54496Sbostic c -= isupper(c) ? 'A' - 10 : 'a' - 10; 68*54496Sbostic else 69*54496Sbostic break; 70*54496Sbostic if (c >= base) 71*54496Sbostic break; 72*54496Sbostic if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) 73*54496Sbostic any = -1; 74*54496Sbostic else { 75*54496Sbostic any = 1; 76*54496Sbostic acc *= qbase; 77*54496Sbostic acc += c; 78*54496Sbostic } 79*54496Sbostic } 80*54496Sbostic if (any < 0) { 81*54496Sbostic acc = UQUAD_MAX; 82*54496Sbostic errno = ERANGE; 83*54496Sbostic } else if (neg) 84*54496Sbostic acc = -acc; 85*54496Sbostic if (endptr != 0) 86*54496Sbostic *endptr = any ? s - 1 : (char *)nptr; 87*54496Sbostic return (acc); 88*54496Sbostic } 89