| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 | /* * Copyright (C) 2000 Manuel Novoa III * * Notes: * * The primary objective of this implementation was minimal size. * * Note: Assumes char layout 0-9.*A-Z.*a-z for ordinals values. * * There are a couple of compile-time options below. * *//*****************************************************************************//*                            OPTIONS                                        *//*****************************************************************************//* Set if we want errno set appropriately. *//* NOTE: Implies _STRTO_ENDPTR below */#define _STRTO_ERRNO            0/* Set if we want support for the endptr arg. *//* Implied by _STRTO_ERRNO. */#define _STRTO_ENDPTR           1/*****************************************************************************//* Don't change anything that follows.                                       *//*****************************************************************************/#if _STRTO_ERRNO#undef _STRTO_ENDPTR#define _STRTO_ENDPTR           1#endif/*****************************************************************************//* Are there actually any machines where this might fail? */#if 'A' > 'a'#error ordering assumption violated : 'A' > 'a'#endif#include <stdlib.h>#include <limits.h>#include <ctype.h>#if _STRTO_ERRNO#include <errno.h>#endifunsigned long _strto_l(const char *str, char **endptr, int base, int uflag);#if L_strto_l/* * This is the main work fuction which handles both strtol (uflag = 0) and * strtoul (uflag = 1). */unsigned long _strto_l(const char *str, char **endptr, int base, int uflag){    unsigned long number = 0;    unsigned long cutoff;    char *pos = (char *) str;#if _STRTO_ENDPTR    char *fail_char = (char *) str;#endif    int digit, cutoff_digit;    int negative;    while (isspace(*pos)) {	/* skip leading whitespace */	++pos;    }    /* handle optional sign */    negative = 0;    switch(*pos) {    case '-': negative = 1;	/* fall through to increment pos */    case '+': ++pos;    }    if ((base == 16) && (*pos == '0')) { /* handle option prefix */	++pos;#if _STRTO_ENDPTR	fail_char = pos;#endif	if ((*pos == 'x') || (*pos == 'X')) {	    ++pos;	}    }        if (base == 0) {		/* dynamic base */	base = 10;		/* default is 10 */	if (*pos == '0') {	    ++pos;	    base -= 2;		/* now base is 8 (or 16) */#if _STRTO_ENDPTR	    fail_char = pos;#endif	    if ((*pos == 'x') || (*pos == 'X')) {		base += 8;	/* base is 16 */		++pos;	    }	}    }    if ((base < 2) || (base > 36)) { /* illegal base */	goto DONE;    }    cutoff_digit = ULONG_MAX % base;    cutoff = ULONG_MAX / base;    while (1) {	digit = 40;	if ((*pos >= '0') && (*pos <= '9')) {	    digit = (*pos - '0');	} else if (*pos >= 'a') {	    digit = (*pos - 'a' + 10);	} else if (*pos >= 'A') {	    digit = (*pos - 'A' + 10);	} else break;	if (digit >= base) {	    break;	}	++pos;#if _STRTO_ENDPTR	fail_char = pos;#endif	/* adjust number, with overflow check */	if ((number > cutoff)	    || ((number == cutoff) && (digit > cutoff_digit))) {	    number = ULONG_MAX;	    if (uflag) {		negative = 0; /* since unsigned returns ULONG_MAX */	    }#if _STRTO_ERRNO	    errno = ERANGE;#endif	} else {	    number = number * base + digit;	}    } DONE:#if _STRTO_ENDPTR    if (endptr) {	*endptr = fail_char;    }#endif    if (negative) {	if (!uflag && (number > ((unsigned long)(-(1+LONG_MIN)))+1)) {#if _STRTO_ERRNO	    errno = ERANGE;#endif	    return (unsigned long) LONG_MIN;	}	return (unsigned long)(-((long)number));    } else {	if (!uflag && (number > (unsigned long) LONG_MAX)) {#if _STRTO_ERRNO	    errno = ERANGE;#endif	    return LONG_MAX;	}	return number;    }}#endif#if L_strtoulunsigned long strtoul(const char *str, char **endptr, int base){    return _strto_l(str, endptr, base, 1);}#endif#if L_strtollong strtol(const char *str, char **endptr, int base){    return _strto_l(str, endptr, base, 0);}#endif
 |