xref: /csrg-svn/lib/libc/stdlib/strtouq.c (revision 54496)
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