15e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann/*-
25e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann * Copyright (c) 1992, 1993
35e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann *	The Regents of the University of California.  All rights reserved.
45e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann *
55e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann * Redistribution and use in source and binary forms, with or without
65e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann * modification, are permitted provided that the following conditions
75e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann * are met:
85e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann * 1. Redistributions of source code must retain the above copyright
95e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann *    notice, this list of conditions and the following disclaimer.
105e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann * 2. Redistributions in binary form must reproduce the above copyright
115e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann *    notice, this list of conditions and the following disclaimer in the
125e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann *    documentation and/or other materials provided with the distribution.
135e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann * 4. Neither the name of the University nor the names of its contributors
145e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann *    may be used to endorse or promote products derived from this software
155e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann *    without specific prior written permission.
165e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann *
175e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
185e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
195e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
205e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
215e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
225e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
235e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
245e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
255e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
265e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
275e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann * SUCH DAMAGE.
285e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann */
295e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann
305e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann
315e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann#include <limits.h>
325e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann#ifdef HAVE_ERRNO_H
335e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann#include <errno.h>
345e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann#endif
355e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann#include <stdlib.h>
365e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann#ifdef DBUS_WINCE
375e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann#include <windows.h>
385e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann#endif
395e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann
405e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann#ifndef isspace
415e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann#define isspace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n')
425e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann#endif
435e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann
445e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann/* Minimum and maximum values a `signed long long int' can hold.  */
455e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann#ifndef LLONG_MAX
465e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann#   define LLONG_MAX	9223372036854775807LL
475e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann#endif
485e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann
495e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann#ifndef LLONG_MIN
505e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann#   define LLONG_MIN	(-LLONG_MAX - 1LL)
515e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann#endif
525e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann/* Maximum value an `unsigned long long int' can hold.  (Minimum is 0.)  */
535e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann#ifndef ULLONG_MAX
545e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann#   define ULLONG_MAX	18446744073709551615ULL
555e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann#endif
565e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann
575e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann/*
585e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann * Convert a string to an unsigned long long integer.
595e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann *
605e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann * Assumes that the upper and lower case
615e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann * alphabets and digits are each contiguous.
625e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann */
635e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmannunsigned long long strtoull (const char *, char **, int);
645e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann
655e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmannunsigned long long
665e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmannstrtoull(const char * nptr, char ** endptr, int base)
675e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann{
685e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	const char *s;
695e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	unsigned long long acc;
705e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	char c;
715e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	unsigned long long cutoff;
725e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	int neg, any, cutlim;
735e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann
745e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	/*
755e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	 * See strtoq for comments as to the logic used.
765e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	 */
775e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	s = nptr;
785e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	do {
795e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann		c = *s++;
805e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	} while (isspace((unsigned char)c));
815e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	if (c == '-') {
825e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann		neg = 1;
835e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann		c = *s++;
845e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	} else {
855e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann		neg = 0;
865e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann		if (c == '+')
875e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann			c = *s++;
885e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	}
895e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	if ((base == 0 || base == 16) &&
905e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	    c == '0' && (*s == 'x' || *s == 'X') &&
915e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	    ((s[1] >= '0' && s[1] <= '9') ||
925e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	    (s[1] >= 'A' && s[1] <= 'F') ||
935e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	    (s[1] >= 'a' && s[1] <= 'f'))) {
945e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann		c = s[1];
955e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann		s += 2;
965e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann		base = 16;
975e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	}
985e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	if (base == 0)
995e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann		base = c == '0' ? 8 : 10;
1005e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	acc = any = 0;
1015e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	if (base < 2 || base > 36)
1025e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann		goto noconv;
1035e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann
1045e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	cutoff = ULLONG_MAX / base;
1055e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	cutlim = ULLONG_MAX % base;
1065e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	for ( ; ; c = *s++) {
1075e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann		if (c >= '0' && c <= '9')
1085e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann			c -= '0';
1095e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann		else if (c >= 'A' && c <= 'Z')
1105e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann			c -= 'A' - 10;
1115e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann		else if (c >= 'a' && c <= 'z')
1125e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann			c -= 'a' - 10;
1135e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann		else
1145e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann			break;
1155e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann		if (c >= base)
1165e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann			break;
1175e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
1185e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann			any = -1;
1195e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann		else {
1205e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann			any = 1;
1215e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann			acc *= base;
1225e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann			acc += c;
1235e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann		}
1245e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	}
1255e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	if (any < 0) {
1265e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann		acc = ULLONG_MAX;
1275e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann#ifdef DBUS_WINCE
1285e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann		SetLastError (ERROR_ARITHMETIC_OVERFLOW);
1295e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann#else
1305e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann		errno = ERANGE;
1315e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann#endif
1325e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	} else if (!any) {
1335e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmannnoconv:
1345e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann#ifdef DBUS_WINCE
1355e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann		SetLastError (ERROR_INVALID_PARAMETER);
1365e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann#else
1375e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann		errno = EINVAL;
1385e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann#endif
1395e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	} else if (neg)
1405e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann		acc = -acc;
1415e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	if (endptr != NULL)
1425e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann		*endptr = (char *)(any ? s - 1 : nptr);
1435e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann	return (acc);
1445e4ef80e098c950fa394092060eb311babbe7035Marcus Brinkmann}
145