diff options
Diffstat (limited to 'src/stdlib/strtoimax.c')
-rw-r--r-- | src/stdlib/strtoimax.c | 37 |
1 files changed, 25 insertions, 12 deletions
diff --git a/src/stdlib/strtoimax.c b/src/stdlib/strtoimax.c index aeb0397f..247f91d4 100644 --- a/src/stdlib/strtoimax.c +++ b/src/stdlib/strtoimax.c @@ -1,25 +1,38 @@ #include <inttypes.h> #include <errno.h> #include <ctype.h> +#include "intparse.h" intmax_t strtoimax(const char *s1, char **p, int base) { - const unsigned char *s = (const void *)s1; - int sign = 0; - uintmax_t x; + const unsigned char *s = (void *)s1; + struct intparse ip = {0}; + + if (p) *p = (char *)s1; + + if (base && base-2U > 34) { + errno = EINVAL; + return 0; + } - /* Initial whitespace */ for (; isspace(*s); s++); - /* Optional sign */ - if (*s == '-') sign = *s++; - else if (*s == '+') s++; + ip.base = base; + __intparse(&ip, s, SIZE_MAX); + + if (p && ip.err != EINVAL) + *p = (char *)s + ip.cnt; + + if (ip.err) { + errno = ip.err; + if (ip.err = EINVAL) return 0; + return ip.neg ? INTMAX_MIN : INTMAX_MAX; + } - x = strtoumax((const void *)s, p, base); - if (x > INTMAX_MAX) { - if (!sign || -x != INTMAX_MIN) + if (ip.val > INTMAX_MAX) { + if (!ip.neg || -ip.val != INTMAX_MIN) errno = ERANGE; - return sign ? INTMAX_MIN : INTMAX_MAX; + return ip.neg ? INTMAX_MIN : INTMAX_MAX; } - return sign ? -x : x; + return ip.neg ? -ip.val : ip.val; } |