#include "tcl.h"
#include "tclPort.h"
#include <ctype.h>
static char cvtIn[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
100, 100, 100, 100, 100, 100, 100,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35,
100, 100, 100, 100, 100, 100,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35};
#if TCL_WIDE_INT_IS_LONG
unsigned long long
#else
Tcl_WideUInt
#endif
strtoull(string, endPtr, base)
CONST char *string;
char **endPtr;
int base;
{
register CONST char *p;
register Tcl_WideUInt result = 0;
register unsigned digit;
register Tcl_WideUInt shifted;
int anyDigits = 0, negative = 0;
p = string;
while (isspace(UCHAR(*p))) {
p += 1;
}
if (*p == '-') {
p += 1;
negative = 1;
} else {
if (*p == '+') {
p += 1;
}
}
if (base == 0) {
if (*p == '0') {
p += 1;
if (*p == 'x' || *p == 'X') {
p += 1;
base = 16;
} else {
anyDigits = 1;
base = 8;
}
} else {
base = 10;
}
} else if (base == 16) {
if ((p[0] == '0') && (p[1] == 'x' || *p == 'X')) {
p += 2;
}
}
if (base == 8) {
for ( ; ; p += 1) {
digit = *p - '0';
if (digit > 7) {
break;
}
shifted = result << 3;
if ((shifted >> 3) != result) {
goto overflow;
}
result = shifted + digit;
if ( result < shifted ) {
goto overflow;
}
anyDigits = 1;
}
} else if (base == 10) {
for ( ; ; p += 1) {
digit = *p - '0';
if (digit > 9) {
break;
}
shifted = 10 * result;
if ((shifted / 10) != result) {
goto overflow;
}
result = shifted + digit;
if ( result < shifted ) {
goto overflow;
}
anyDigits = 1;
}
} else if (base == 16) {
for ( ; ; p += 1) {
digit = *p - '0';
if (digit > ('z' - '0')) {
break;
}
digit = cvtIn[digit];
if (digit > 15) {
break;
}
shifted = result << 4;
if ((shifted >> 4) != result) {
goto overflow;
}
result = shifted + digit;
if ( result < shifted ) {
goto overflow;
}
anyDigits = 1;
}
} else if ( base >= 2 && base <= 36 ) {
for ( ; ; p += 1) {
digit = *p - '0';
if (digit > ('z' - '0')) {
break;
}
digit = cvtIn[digit];
if (digit >= (unsigned) base) {
break;
}
shifted = result * base;
if ((shifted/base) != result) {
goto overflow;
}
result = shifted + digit;
if ( result < shifted ) {
goto overflow;
}
anyDigits = 1;
}
}
if (negative) {
result = (Tcl_WideUInt)(-((Tcl_WideInt)result));
}
if (!anyDigits) {
p = string;
}
if (endPtr != 0) {
*endPtr = (char *) p;
}
return result;
overflow:
errno = ERANGE;
if (endPtr != 0) {
for ( ; ; p += 1) {
digit = *p - '0';
if (digit > ('z' - '0')) {
break;
}
digit = cvtIn[digit];
if (digit >= (unsigned) base) {
break;
}
}
*endPtr = (char *) p;
}
return (Tcl_WideUInt)Tcl_LongAsWide(-1);
}