--- strtonum.c.orig 2006-03-14 21:53:03.000000000 +0200 +++ strtonum.c 2012-03-12 13:05:40.000000000 +0200 @@ -24,45 +24,51 @@ __FBSDID("$FreeBSD: src/lib/libc/stdlib/ #include #include -#define INVALID 1 -#define TOOSMALL 2 -#define TOOLARGE 3 +#define INVALID 0 +#define TOOSMALL 1 +#define TOOLARGE 2 long long strtonum(const char *numstr, long long minval, long long maxval, const char **errstrp) { - long long ll = 0; - char *ep; - int error = 0; - struct errval { - const char *errstr; - int err; - } ev[4] = { - { NULL, 0 }, - { "invalid", EINVAL }, - { "too small", ERANGE }, - { "too large", ERANGE }, + static const struct { + const char *errstr; + int errnum; + } ev[] = { + [INVALID] = { "invalid", EINVAL }, + [TOOSMALL] = { "too small", ERANGE }, + [TOOLARGE] = { "too large", ERANGE } }; - ev[0].err = errno; - errno = 0; + int error; + if (minval > maxval) error = INVALID; else { + long long ll; + char *ep; + int errno_save; + + errno_save = errno; + errno = 0; ll = strtoll(numstr, &ep, 10); - if (errno == EINVAL || numstr == ep || *ep != '\0') + error = errno; + if (error == EINVAL || numstr == ep || *ep != '\0') error = INVALID; - else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval) + else if ((ll == LLONG_MIN && error == ERANGE) || ll < minval) error = TOOSMALL; - else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval) + else if ((ll == LLONG_MAX && error == ERANGE) || ll > maxval) error = TOOLARGE; + else { + errno = errno_save; + if (errstrp != NULL) + *errstrp = NULL; + return (ll); + } } if (errstrp != NULL) *errstrp = ev[error].errstr; - errno = ev[error].err; - if (error) - ll = 0; - - return (ll); + errno = ev[error].errnum; + return (0); }