#include <sm/gen.h>
SM_IDSTR(id, "@(#)$Id: strto.c,v 1.18 2001/12/30 04:59:37 gshapiro Exp $")
#include <sys/param.h>
#include <sys/types.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <sm/limits.h>
#include <sm/conf.h>
#include <sm/string.h>
LONGLONG_T
sm_strtoll(nptr, endptr, base)
const char *nptr;
char **endptr;
register int base;
{
register bool neg;
register const char *s;
register LONGLONG_T acc, cutoff;
register int c;
register int any, cutlim;
s = nptr;
do
{
c = (unsigned char) *s++;
} while (isascii(c) && isspace(c));
if (c == '-')
{
neg = true;
c = *s++;
}
else
{
neg = false;
if (c == '+')
c = *s++;
}
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X'))
{
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = c == '0' ? 8 : 10;
cutoff = neg ? LLONG_MIN : LLONG_MAX;
cutlim = cutoff % base;
cutoff /= base;
if (neg)
{
if (cutlim > 0)
{
cutlim -= base;
cutoff += 1;
}
cutlim = -cutlim;
}
for (acc = 0, any = 0;; c = (unsigned char) *s++)
{
if (isascii(c) && isdigit(c))
c -= '0';
else if (isascii(c) && isalpha(c))
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
else
break;
if (c >= base)
break;
if (any < 0)
continue;
if (neg)
{
if (acc < cutoff || (acc == cutoff && c > cutlim))
{
any = -1;
acc = LLONG_MIN;
errno = ERANGE;
}
else
{
any = 1;
acc *= base;
acc -= c;
}
}
else
{
if (acc > cutoff || (acc == cutoff && c > cutlim))
{
any = -1;
acc = LLONG_MAX;
errno = ERANGE;
}
else
{
any = 1;
acc *= base;
acc += c;
}
}
}
if (endptr != 0)
*endptr = (char *) (any ? s - 1 : nptr);
return acc;
}
ULONGLONG_T
sm_strtoull(nptr, endptr, base)
const char *nptr;
char **endptr;
register int base;
{
register const char *s;
register ULONGLONG_T acc, cutoff;
register int c;
register bool neg;
register int any, cutlim;
s = nptr;
do
{
c = (unsigned char) *s++;
} while (isascii(c) && isspace(c));
neg = (c == '-');
if (neg)
{
c = *s++;
}
else
{
if (c == '+')
c = *s++;
}
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X'))
{
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = c == '0' ? 8 : 10;
cutoff = ULLONG_MAX / (ULONGLONG_T)base;
cutlim = ULLONG_MAX % (ULONGLONG_T)base;
for (acc = 0, any = 0;; c = (unsigned char) *s++)
{
if (isascii(c) && isdigit(c))
c -= '0';
else if (isascii(c) && isalpha(c))
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
else
break;
if (c >= base)
break;
if (any < 0)
continue;
if (acc > cutoff || (acc == cutoff && c > cutlim))
{
any = -1;
acc = ULLONG_MAX;
errno = ERANGE;
}
else
{
any = 1;
acc *= (ULONGLONG_T)base;
acc += c;
}
}
if (neg && any > 0)
acc = -((LONGLONG_T) acc);
if (endptr != 0)
*endptr = (char *) (any ? s - 1 : nptr);
return acc;
}