/* original from norbert schelenkar's stdio */ /* eff hacks ++jrb */ /* conversion to ansi spec -- mj */ /* * Base can be anything between 2 and 36 or 0. * If not NULL then resulting *endptr points to the first * non-accepted character. */ #include #include #include #include #include /* macro to avoid most frequent long muls on a lowly 68k */ #define _BASEMUL(B, SH, X) \ ((0 != SH) ? \ ((10 == (B)) ? ((((X) << (SH)) + (X)) << 1) : ((X) << (SH))) : \ ((X) * (B))) unsigned long int strtoul(nptr, endptr, base) register const char *nptr; char **endptr; int base; { register short c; unsigned long result = 0L; unsigned long limit; short negative = 0; short overflow = -2; /* if this stays negative then no conversion was performed */ short digit; int shift; if (endptr != NULL) *endptr = (char *)nptr; while ((c = *nptr) && isspace(c)) /* skip leading white space */ nptr++; if ((c = *nptr) == '+' || c == '-') { /* handle signs */ negative = (c == '-'); nptr++; } if (base == 0) { /* determine base if unknown */ if (*nptr == '0') { base = 8; nptr++; if ((c = *nptr) == 'x' || c == 'X') { base += base; nptr++; } } else base = 10; } else if (base == 16 && *nptr == '0') { /* discard 0x/0X prefix if hex */ nptr++; if ((c = *nptr == 'x') || c == 'X') nptr++; } if (base < 2 || base > 36) return result; limit = ULONG_MAX/(unsigned long)base; /* ensure no overflow */ shift = 0; switch (base) { case 32: shift++; case 16: shift++; case 8: shift++; case 4: case 10: shift++; case 2: shift++; default:; } nptr--; /* convert the number */ while (c = *++nptr) { if (isdigit(c)) digit = c - '0'; else digit = c - (isupper(c) ? 'A' : 'a') + 10; if (digit < 0 || digit >= base) break; overflow &= 1; /* valid digit - some conversion performed */ if (0 == (overflow &= 1)) { /* valid digit - some conversion performed */ if ((result > limit) || (digit > (ULONG_MAX - (result = _BASEMUL(base, shift, result))))) { result = ULONG_MAX; errno = ERANGE; overflow = 1; negative = 0; } else result += digit; } } if (negative) /* ANSI says we should do this! */ result = 0L - result; if ((endptr != NULL) && (overflow >= 0)) /* move *endptr if some */ *endptr = (char *) nptr; /* digits were accepted */ return result; }