/*
* Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1992
* The Regents of the University of California. All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
/*
** SM_STRTOLL -- Convert a string to a (signed) long long integer.
**
** Ignores `locale' stuff. Assumes that the upper and lower case
** alphabets and digits are each contiguous.
**
** Parameters:
** nptr -- string containing number
** endptr -- location of first invalid character
** base -- numeric base that 'nptr' number is based in
**
** Returns:
** Failure: on underflow LLONG_MIN is returned; on overflow
** LLONG_MAX is returned and errno is set.
** When 'endptr' == '\0' then the entire string 'nptr'
** was valid.
** Success: returns the converted number
*/
const char *nptr;
char **endptr;
register int base;
{
register bool neg;
register const char *s;
register int c;
/*
** Skip white space and pick up leading +/- sign if any.
** If base is 0, allow 0x for hex and 0 for octal, else
** assume decimal; if base is already 16, allow 0x.
*/
s = nptr;
do
{
c = (unsigned char) *s++;
if (c == '-')
{
neg = true;
c = *s++;
}
else
{
neg = false;
if (c == '+')
c = *s++;
}
c == '0' && (*s == 'x' || *s == 'X'))
{
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
/*
** Compute the cutoff value between legal numbers and illegal
** numbers. That is the largest legal value, divided by the
** base. An input number that is greater than this value, if
** followed by a legal input character, is too big. One that
** is equal to this value may be valid or not; the limit
** between valid and invalid numbers is then based on the last
** digit. For instance, if the range for long-long's is
** [-9223372036854775808..9223372036854775807] and the input base
** is 10, cutoff will be set to 922337203685477580 and cutlim to
** either 7 (!neg) or 8 (neg), meaning that if we have
** accumulated a value > 922337203685477580, or equal but the
** next digit is > 7 (or 8), the number is too big, and we will
** return a range error.
**
** Set any if any `digits' consumed; make it negative to indicate
** overflow.
*/
if (neg)
{
if (cutlim > 0)
{
cutoff += 1;
}
}
{
c -= '0';
else
break;
if (c >= base)
break;
if (any < 0)
continue;
if (neg)
{
{
any = -1;
}
else
{
any = 1;
acc -= c;
}
}
else
{
{
any = -1;
}
else
{
any = 1;
acc += c;
}
}
}
if (endptr != 0)
return acc;
}
/*
** SM_STRTOULL -- Convert a string to an unsigned long long integer.
**
** Ignores `locale' stuff. Assumes that the upper and lower case
** alphabets and digits are each contiguous.
**
** Parameters:
** nptr -- string containing (unsigned) number
** endptr -- location of first invalid character
** base -- numeric base that 'nptr' number is based in
**
** Returns:
** Failure: on overflow ULLONG_MAX is returned and errno is set.
** When 'endptr' == '\0' then the entire string 'nptr'
** was valid.
** Success: returns the converted number
*/
const char *nptr;
char **endptr;
register int base;
{
register const char *s;
register int c;
register bool neg;
/* See sm_strtoll for comments as to the logic used. */
s = nptr;
do
{
c = (unsigned char) *s++;
neg = (c == '-');
if (neg)
{
c = *s++;
}
else
{
if (c == '+')
c = *s++;
}
c == '0' && (*s == 'x' || *s == 'X'))
{
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
{
c -= '0';
else
break;
if (c >= base)
break;
if (any < 0)
continue;
{
any = -1;
acc = ULLONG_MAX;
}
else
{
any = 1;
acc += c;
}
}
if (endptr != 0)
return acc;
}