/*
 * strtol()
 * Stolen from the Linux C Library
 */
#include <ctype.h>

#define UNSIGNED  1

#define ULONG_MAX 0xffffffffUL
#define NULL 0L
#define LONG_MIN  0x80000000L
#define LONG_MAX  0x7fffffffL

unsigned strtol(const char *nptr, char **endptr, int base)
{
    int negative;
    unsigned long int cutoff;
    unsigned int cutlim;
    unsigned long int i;
    const char *s;
    unsigned char c;
    const char *save;
    int overflow;

    if (base < 0 || base == 1 || base > 36)
	base = 10;

    s = nptr;

    /*
     * Skip white space.
     */
    while (isspace(*s))
	++s;
    if (*s == '\0')
	goto noconv;

    /* 
     * Check for a sign.
     */
    if (*s == '-')
    {
	negative = 1;
	++s;
    }
    else if (*s == '+')
    {
	negative = 0;
	++s;
    }
    else
	negative = 0;

    if (base == 16 && s[0] == '0' && toupper(s[1]) == 'X')
	s += 2;

    /* 
     * If BASE is zero, figure it out ourselves.
     */
    if (base == 0)
	if (*s == '0')
	{
	    if (toupper(s[1]) == 'X')
	    {
		s += 2;
		base = 16;
	    }
	    else
		base = 8;
	}
	else
	    base = 10;

    /*
     * Save the pointer so we can check later if anything happened.
     */
    save = s;

    cutoff = ULONG_MAX / (unsigned long int) base;
    cutlim = ULONG_MAX % (unsigned long int) base;

    overflow = 0;
    i = 0;
    for (c = *s; c != '\0'; c = *++s)
    {
	if (isdigit(c))
	    c -= '0';
	else if (isalpha(c))
	    c = toupper(c) - 'A' + 10;
	else
	    break;
	if (c >= base)
	    break;
	/*
	 * Check for overflow.
	 */
	if (i > cutoff || (i == cutoff && c > cutlim))
	    overflow = 1;
	else
        {
	    i *= (unsigned long int) base;
	    i += c;
        }
    }

    /*
     * Check if anything actually happened.
     */
    if (s == save)
	goto noconv;

    /* Store in ENDPTR the address of one character
     * past the last character we converted.
     */
    if (endptr != NULL)
	*endptr = (char *) s;

#if     !UNSIGNED
    /* Check for a value that is within the range of
     * `unsigned long int', but outside the range of `long int'.
     */
    if (i > (negative ?
	     - (unsigned long int) LONG_MIN : (unsigned long int) LONG_MAX))
	overflow = 1;
#endif

    if (overflow)
    {
	/*      errno = ERANGE; */
#if     UNSIGNED
	return ULONG_MAX;
#else
	return negative ? LONG_MIN : LONG_MAX;
#endif
    }

    /*
     * Return the result of the appropriate sign.
     */
    return (negative ? - i : i);

noconv:
    /*
     * There was no number to convert.
     */
    if (endptr != NULL)
	*endptr = (char *) nptr;
    return 0L;
}
