|
Packit |
67cb25 |
/* Copyright (C) 1991, 1992, 1994 Free Software Foundation, Inc.
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
This file is part of the GNU C Library.
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
The GNU C Library is free software; you can redistribute it and/or
|
|
Packit |
67cb25 |
modify it under the terms of the GNU Library General Public License as
|
|
Packit |
67cb25 |
published by the Free Software Foundation; either version 3 of the
|
|
Packit |
67cb25 |
License, or (at your option) any later version.
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
The GNU C Library is distributed in the hope that it will be useful,
|
|
Packit |
67cb25 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
67cb25 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
67cb25 |
Library General Public License for more details.
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
You should have received a copy of the GNU Library General Public
|
|
Packit |
67cb25 |
License along with the GNU C Library; see the file COPYING.LIB. If
|
|
Packit |
67cb25 |
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
|
Packit |
67cb25 |
Cambridge, MA 02110-1301, USA. */
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#include <ctype.h>
|
|
Packit |
67cb25 |
#include <limits.h>
|
|
Packit |
67cb25 |
#include <stddef.h>
|
|
Packit |
67cb25 |
#include <stdlib.h>
|
|
Packit |
67cb25 |
#include <errno.h>
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#ifndef UNSIGNED
|
|
Packit |
67cb25 |
#define UNSIGNED 0
|
|
Packit |
67cb25 |
#endif
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
|
|
Packit |
67cb25 |
If BASE is 0 the base is determined by the presence of a leading
|
|
Packit |
67cb25 |
zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
|
|
Packit |
67cb25 |
If BASE is < 2 or > 36, it is reset to 10.
|
|
Packit |
67cb25 |
If ENDPTR is not NULL, a pointer to the character after the last
|
|
Packit |
67cb25 |
one converted is stored in *ENDPTR. */
|
|
Packit |
67cb25 |
#if UNSIGNED
|
|
Packit |
67cb25 |
unsigned long int
|
|
Packit |
67cb25 |
#define strtol strtoul
|
|
Packit |
67cb25 |
#else
|
|
Packit |
67cb25 |
long int
|
|
Packit |
67cb25 |
#endif
|
|
Packit |
67cb25 |
strtol (nptr, endptr, base)
|
|
Packit |
67cb25 |
const char *nptr;
|
|
Packit |
67cb25 |
char **endptr;
|
|
Packit |
67cb25 |
int base;
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
int negative;
|
|
Packit |
67cb25 |
register unsigned long int cutoff;
|
|
Packit |
67cb25 |
register unsigned int cutlim;
|
|
Packit |
67cb25 |
register unsigned long int i;
|
|
Packit |
67cb25 |
register const char *s;
|
|
Packit |
67cb25 |
register unsigned char c;
|
|
Packit |
67cb25 |
const char *save;
|
|
Packit |
67cb25 |
int overflow;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (base < 0 || base == 1 || base > 36)
|
|
Packit |
67cb25 |
base = 10;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
s = nptr;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Skip white space. */
|
|
Packit |
67cb25 |
while (isspace (*s))
|
|
Packit |
67cb25 |
++s;
|
|
Packit |
67cb25 |
if (*s == '\0')
|
|
Packit |
67cb25 |
goto noconv;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Check for a sign. */
|
|
Packit |
67cb25 |
if (*s == '-')
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
negative = 1;
|
|
Packit |
67cb25 |
++s;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else if (*s == '+')
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
negative = 0;
|
|
Packit |
67cb25 |
++s;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
negative = 0;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (base == 16 && s[0] == '0' && toupper (s[1]) == 'X')
|
|
Packit |
67cb25 |
s += 2;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* If BASE is zero, figure it out ourselves. */
|
|
Packit |
67cb25 |
if (base == 0)
|
|
Packit |
67cb25 |
if (*s == '0')
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
if (toupper (s[1]) == 'X')
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
s += 2;
|
|
Packit |
67cb25 |
base = 16;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
base = 8;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
base = 10;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Save the pointer so we can check later if anything happened. */
|
|
Packit |
67cb25 |
save = s;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
cutoff = ULONG_MAX / (unsigned long int) base;
|
|
Packit |
67cb25 |
cutlim = ULONG_MAX % (unsigned long int) base;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
overflow = 0;
|
|
Packit |
67cb25 |
i = 0;
|
|
Packit |
67cb25 |
for (c = *s; c != '\0'; c = *++s)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
if (isdigit (c))
|
|
Packit |
67cb25 |
c -= '0';
|
|
Packit |
67cb25 |
else if (isalpha (c))
|
|
Packit |
67cb25 |
c = toupper (c) - 'A' + 10;
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
break;
|
|
Packit |
67cb25 |
if (c >= base)
|
|
Packit |
67cb25 |
break;
|
|
Packit |
67cb25 |
/* Check for overflow. */
|
|
Packit |
67cb25 |
if (i > cutoff || (i == cutoff && c > cutlim))
|
|
Packit |
67cb25 |
overflow = 1;
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
i *= (unsigned long int) base;
|
|
Packit |
67cb25 |
i += c;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Check if anything actually happened. */
|
|
Packit |
67cb25 |
if (s == save)
|
|
Packit |
67cb25 |
goto noconv;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Store in ENDPTR the address of one character
|
|
Packit |
67cb25 |
past the last character we converted. */
|
|
Packit |
67cb25 |
if (endptr != NULL)
|
|
Packit |
67cb25 |
*endptr = (char *) s;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#if !UNSIGNED
|
|
Packit |
67cb25 |
/* Check for a value that is within the range of
|
|
Packit |
67cb25 |
`unsigned long int', but outside the range of `long int'. */
|
|
Packit |
67cb25 |
if (i > (negative ?
|
|
Packit |
67cb25 |
-(unsigned long int) LONG_MIN : (unsigned long int) LONG_MAX))
|
|
Packit |
67cb25 |
overflow = 1;
|
|
Packit |
67cb25 |
#endif
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (overflow)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
errno = ERANGE;
|
|
Packit |
67cb25 |
#if UNSIGNED
|
|
Packit |
67cb25 |
return ULONG_MAX;
|
|
Packit |
67cb25 |
#else
|
|
Packit |
67cb25 |
return negative ? LONG_MIN : LONG_MAX;
|
|
Packit |
67cb25 |
#endif
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
/* Return the result of the appropriate sign. */
|
|
Packit |
67cb25 |
return (negative ? -i : i);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
noconv:
|
|
Packit |
67cb25 |
/* There was no number to convert. */
|
|
Packit |
67cb25 |
if (endptr != NULL)
|
|
Packit |
67cb25 |
*endptr = (char *) nptr;
|
|
Packit |
67cb25 |
return 0L;
|
|
Packit |
67cb25 |
}
|