xref: /csrg-svn/lib/libc/stdlib/strtouq.c (revision 61180)
154496Sbostic /*-
2*61180Sbostic  * Copyright (c) 1992, 1993
3*61180Sbostic  *	The Regents of the University of California.  All rights reserved.
454496Sbostic  *
554496Sbostic  * %sccs.include.redist.c%
654496Sbostic  */
754496Sbostic 
854496Sbostic #if defined(LIBC_SCCS) && !defined(lint)
9*61180Sbostic static char sccsid[] = "@(#)strtouq.c	8.1 (Berkeley) 06/04/93";
1054496Sbostic #endif /* LIBC_SCCS and not lint */
1154496Sbostic 
1254496Sbostic #include <sys/types.h>
1354496Sbostic 
1454496Sbostic #include <limits.h>
1554496Sbostic #include <errno.h>
1654496Sbostic #include <ctype.h>
1754496Sbostic #include <stdlib.h>
1854496Sbostic 
1954496Sbostic /*
2054496Sbostic  * Convert a string to an unsigned quad integer.
2154496Sbostic  *
2254496Sbostic  * Ignores `locale' stuff.  Assumes that the upper and lower case
2354496Sbostic  * alphabets and digits are each contiguous.
2454496Sbostic  */
2554496Sbostic u_quad_t
strtouq(nptr,endptr,base)2654496Sbostic strtouq(nptr, endptr, base)
2754496Sbostic 	const char *nptr;
2854496Sbostic 	char **endptr;
2954496Sbostic 	register int base;
3054496Sbostic {
3154496Sbostic 	register const char *s = nptr;
3254496Sbostic 	register u_quad_t acc;
3354496Sbostic 	register int c;
3454496Sbostic 	register u_quad_t qbase, cutoff;
3554496Sbostic 	register int neg, any, cutlim;
3654496Sbostic 
3754496Sbostic 	/*
3854496Sbostic 	 * See strtoq for comments as to the logic used.
3954496Sbostic 	 */
4054496Sbostic 	s = nptr;
4154496Sbostic 	do {
4254496Sbostic 		c = *s++;
4354496Sbostic 	} while (isspace(c));
4454496Sbostic 	if (c == '-') {
4554496Sbostic 		neg = 1;
4654496Sbostic 		c = *s++;
4754496Sbostic 	} else {
4854496Sbostic 		neg = 0;
4954496Sbostic 		if (c == '+')
5054496Sbostic 			c = *s++;
5154496Sbostic 	}
5254496Sbostic 	if ((base == 0 || base == 16) &&
5354496Sbostic 	    c == '0' && (*s == 'x' || *s == 'X')) {
5454496Sbostic 		c = s[1];
5554496Sbostic 		s += 2;
5654496Sbostic 		base = 16;
5754496Sbostic 	}
5854496Sbostic 	if (base == 0)
5954496Sbostic 		base = c == '0' ? 8 : 10;
6054496Sbostic 	qbase = (unsigned)base;
6154496Sbostic 	cutoff = (u_quad_t)UQUAD_MAX / qbase;
6254496Sbostic 	cutlim = (u_quad_t)UQUAD_MAX % qbase;
6354496Sbostic 	for (acc = 0, any = 0;; c = *s++) {
6454496Sbostic 		if (isdigit(c))
6554496Sbostic 			c -= '0';
6654496Sbostic 		else if (isalpha(c))
6754496Sbostic 			c -= isupper(c) ? 'A' - 10 : 'a' - 10;
6854496Sbostic 		else
6954496Sbostic 			break;
7054496Sbostic 		if (c >= base)
7154496Sbostic 			break;
7254496Sbostic 		if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
7354496Sbostic 			any = -1;
7454496Sbostic 		else {
7554496Sbostic 			any = 1;
7654496Sbostic 			acc *= qbase;
7754496Sbostic 			acc += c;
7854496Sbostic 		}
7954496Sbostic 	}
8054496Sbostic 	if (any < 0) {
8154496Sbostic 		acc = UQUAD_MAX;
8254496Sbostic 		errno = ERANGE;
8354496Sbostic 	} else if (neg)
8454496Sbostic 		acc = -acc;
8554496Sbostic 	if (endptr != 0)
8658777Storek 		*endptr = (char *)(any ? s - 1 : nptr);
8754496Sbostic 	return (acc);
8854496Sbostic }
89