103100a63Svk /*
203100a63Svk * Copyright (c) 2004 Ted Unangst and Todd Miller
303100a63Svk * All rights reserved.
403100a63Svk *
503100a63Svk * Permission to use, copy, modify, and distribute this software for any
603100a63Svk * purpose with or without fee is hereby granted, provided that the above
703100a63Svk * copyright notice and this permission notice appear in all copies.
803100a63Svk *
903100a63Svk * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1003100a63Svk * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1103100a63Svk * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1203100a63Svk * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1303100a63Svk * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1403100a63Svk * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1503100a63Svk * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1603100a63Svk */
1703100a63Svk
18*223750d9SAndy Fiddaman /*
19*223750d9SAndy Fiddaman * Copyright 2023 Oxide Computer Company
20*223750d9SAndy Fiddaman */
21*223750d9SAndy Fiddaman
2203100a63Svk #include <errno.h>
2303100a63Svk #include <limits.h>
2403100a63Svk #include <stdlib.h>
2503100a63Svk
264585130bSYuri Pankov #define INVALID 1
274585130bSYuri Pankov #define TOOSMALL 2
284585130bSYuri Pankov #define TOOLARGE 3
29*223750d9SAndy Fiddaman #define BADBASE 4
30*223750d9SAndy Fiddaman
31*223750d9SAndy Fiddaman #define MBASE ('z' - 'a' + 1 + 10)
3203100a63Svk
334585130bSYuri Pankov long long
strtonumx(const char * numstr,long long minval,long long maxval,const char ** errstrp,int base)34*223750d9SAndy Fiddaman strtonumx(const char *numstr, long long minval, long long maxval,
35*223750d9SAndy Fiddaman const char **errstrp, int base)
3603100a63Svk {
3703100a63Svk long long ll = 0;
3803100a63Svk int error = 0;
394585130bSYuri Pankov char *ep;
4003100a63Svk struct errval {
4103100a63Svk const char *errstr;
4203100a63Svk int err;
43*223750d9SAndy Fiddaman } ev[5] = {
4403100a63Svk { NULL, 0 },
4503100a63Svk { "invalid", EINVAL },
4603100a63Svk { "too small", ERANGE },
4703100a63Svk { "too large", ERANGE },
48*223750d9SAndy Fiddaman { "unparsable; invalid base specified", EINVAL },
4903100a63Svk };
5003100a63Svk
5103100a63Svk ev[0].err = errno;
5203100a63Svk errno = 0;
534585130bSYuri Pankov if (minval > maxval) {
5403100a63Svk error = INVALID;
55*223750d9SAndy Fiddaman } else if (base < 0 || base > MBASE || base == 1) {
56*223750d9SAndy Fiddaman error = BADBASE;
574585130bSYuri Pankov } else {
58*223750d9SAndy Fiddaman ll = strtoll(numstr, &ep, base);
5903100a63Svk if (numstr == ep || *ep != '\0')
6003100a63Svk error = INVALID;
6103100a63Svk else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
6203100a63Svk error = TOOSMALL;
6303100a63Svk else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
6403100a63Svk error = TOOLARGE;
6503100a63Svk }
6603100a63Svk if (errstrp != NULL)
6703100a63Svk *errstrp = ev[error].errstr;
6803100a63Svk errno = ev[error].err;
69*223750d9SAndy Fiddaman if (error != 0)
7003100a63Svk ll = 0;
7103100a63Svk
724585130bSYuri Pankov return (ll);
7303100a63Svk }
74*223750d9SAndy Fiddaman
75*223750d9SAndy Fiddaman long long
strtonum(const char * numstr,long long minval,long long maxval,const char ** errstrp)76*223750d9SAndy Fiddaman strtonum(const char *numstr, long long minval, long long maxval,
77*223750d9SAndy Fiddaman const char **errstrp)
78*223750d9SAndy Fiddaman {
79*223750d9SAndy Fiddaman return (strtonumx(numstr, minval, maxval, errstrp, 10));
80*223750d9SAndy Fiddaman }
81