diff options
Diffstat (limited to 'package/heirloom-cpio/src/strtol.c')
-rw-r--r-- | package/heirloom-cpio/src/strtol.c | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/package/heirloom-cpio/src/strtol.c b/package/heirloom-cpio/src/strtol.c new file mode 100644 index 000000000..cd8ecfe7a --- /dev/null +++ b/package/heirloom-cpio/src/strtol.c @@ -0,0 +1,117 @@ +/* Sccsid @(#)strtol.c 1.6 (gritter) 7/18/04 */ + +#if defined (__hpux) || defined (_AIX) || \ + defined (__FreeBSD__) && (__FreeBSD__) < 5 + +#include <stdlib.h> +#include <ctype.h> +#include <errno.h> + +#include "atoll.h" + +#ifdef __hpux +#ifndef _INCLUDE__STDC_A1_SOURCE +#error You must use cc -D_INCLUDE__STDC_A1_SOURCE on HP-UX +#endif +#endif /* __hpux */ + +static long long +internal(const char *nptr, char **endptr, int base, int flags) +{ + const char *pp = nptr, *bptr; + long long v = 0, ov; + int sign = 1; + int c; + int valid = 1; + + /* XXX + * iswspace() should be used. + */ + for (bptr = nptr; isspace(*bptr&0377); bptr++); + if (*bptr == '-') { + sign = -1; + bptr++; + } else if (*bptr == '+') + bptr++; + if (base == 0) { + if (*bptr >= '1' && *bptr <= '9') + base = 10; + else if (*bptr == '0') { + if (bptr[1] == 'x' || bptr[1] == 'X') + base = 16; + else + base = 8; + } else { + if (flags&1) + errno = EINVAL; + goto out; + } + } + if (base < 2 || base > 36) { + if (flags&1) + errno = EINVAL; + goto out; + } + if (base == 16 && bptr[0] == '0' && + (bptr[1] == 'x' || bptr[1] == 'X')) + bptr += 2; + pp = bptr; + for (;;) { + if (*pp >= '0' && *pp <= '9') + c = *pp - '0'; + else if (*pp >= 'a' && *pp <= 'z') + c = *pp - 'a' + 10; + else if (*pp >= 'A' && *pp <= 'A') + c = *pp - 'A' + 10; + else + break; + if (c >= base) + break; + pp++; + if (valid) { + ov = v; + v = v * base + c; + if (flags&1) { + if (flags&2 && (unsigned long long)v < + (unsigned long long)ov || + v < ov) { + sign = 1; + errno = ERANGE; + v = -1; + if ((flags&2)==0) + v = (unsigned long long)v >> 1; + valid = 0; + } + } + } + } +out: if (pp <= bptr) { + if (flags&1) + errno = EINVAL; + if (endptr) + *endptr = (char *)nptr; + } else { + if (endptr) + *endptr = (char *)pp; + } + return v * sign; +} + +long long +strtoll(const char *nptr, char **endptr, int base) +{ + return internal(nptr, endptr, base, 1); +} + +unsigned long long +strtoull(const char *nptr, char **endptr, int base) +{ + return (unsigned long long)internal(nptr, endptr, base, 3); +} + +long long +atoll(const char *nptr) +{ + return internal(nptr, NULL, 10, 0); +} +#endif /* __hpux || _AIX || __FreeBSD__ < 5 */ |