aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277>2006-11-25 14:44:13 +0000
committervda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277>2006-11-25 14:44:13 +0000
commitbb46b0d3a8f514681e03265bba58faff4bde89c1 (patch)
tree70735d4bd1e34de43aa3f8092446caf460bd2540
parent47ae536e1abbaa3622d5cbba374169b268070531 (diff)
downloadbusybox-w32-bb46b0d3a8f514681e03265bba58faff4bde89c1.tar.gz
busybox-w32-bb46b0d3a8f514681e03265bba58faff4bde89c1.tar.bz2
busybox-w32-bb46b0d3a8f514681e03265bba58faff4bde89c1.zip
regularize str -> num convertors
git-svn-id: svn://busybox.net/trunk/busybox@16664 69ca8d6d-28ef-0310-b511-8ec308f3f277
-rw-r--r--include/libbb.h35
-rw-r--r--include/xatonum.h94
-rw-r--r--libbb/Kbuild2
-rw-r--r--libbb/xatol.c236
-rw-r--r--libbb/xatonum.c91
-rw-r--r--libbb/xatonum_template.c175
6 files changed, 362 insertions, 271 deletions
diff --git a/include/libbb.h b/include/libbb.h
index 99a1928df..152fb7e01 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -315,40 +315,7 @@ struct suffix_mult {
315 const char *suffix; 315 const char *suffix;
316 unsigned mult; 316 unsigned mult;
317}; 317};
318unsigned long long xstrtoull(const char *numstr, int base); 318#include "xatonum.h"
319unsigned long long xatoull(const char *numstr);
320unsigned long xstrtoul_range_sfx(const char *numstr, int base,
321 unsigned long lower,
322 unsigned long upper,
323 const struct suffix_mult *suffixes);
324unsigned long xstrtoul_range(const char *numstr, int base,
325 unsigned long lower,
326 unsigned long upper);
327unsigned long xstrtoul_sfx(const char *numstr, int base,
328 const struct suffix_mult *suffixes);
329unsigned long xstrtoul(const char *numstr, int base);
330unsigned long xatoul_range_sfx(const char *numstr,
331 unsigned long lower,
332 unsigned long upper,
333 const struct suffix_mult *suffixes);
334unsigned long xatoul_sfx(const char *numstr,
335 const struct suffix_mult *suffixes);
336unsigned long xatoul_range(const char *numstr,
337 unsigned long lower,
338 unsigned long upper);
339unsigned long xatoul(const char *numstr);
340long xstrtol_range_sfx(const char *numstr, int base,
341 long lower,
342 long upper,
343 const struct suffix_mult *suffixes);
344long xstrtol_range(const char *numstr, int base, long lower, long upper);
345long xatol_range_sfx(const char *numstr,
346 long lower,
347 long upper,
348 const struct suffix_mult *suffixes);
349long xatol_range(const char *numstr, long lower, long upper);
350long xatol_sfx(const char *numstr, const struct suffix_mult *suffixes);
351long xatol(const char *numstr);
352/* Specialized: */ 319/* Specialized: */
353unsigned xatou_range(const char *numstr, unsigned lower, unsigned upper); 320unsigned xatou_range(const char *numstr, unsigned lower, unsigned upper);
354unsigned xatou_sfx(const char *numstr, const struct suffix_mult *suffixes); 321unsigned xatou_sfx(const char *numstr, const struct suffix_mult *suffixes);
diff --git a/include/xatonum.h b/include/xatonum.h
new file mode 100644
index 000000000..cdb5e7393
--- /dev/null
+++ b/include/xatonum.h
@@ -0,0 +1,94 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * ascii-to-numbers implementations for busybox
4 *
5 * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
6 *
7 * Licensed under GPLv2, see file LICENSE in this tarball for details.
8 */
9
10/* Provides extern declarations of functions */
11#define DECLARE_STR_CONV(type, T, UT) \
12\
13unsigned type xstrto##UT##_range_sfx(const char *str, int b, unsigned type l, unsigned type u, const struct suffix_mult *sfx); \
14unsigned type xstrto##UT##_range(const char *str, int b, unsigned type l, unsigned type u); \
15unsigned type xstrto##UT##_sfx(const char *str, int b, const struct suffix_mult *sfx); \
16unsigned type xstrto##UT(const char *str, int b); \
17unsigned type xato##UT##_range_sfx(const char *str, unsigned type l, unsigned type u, const struct suffix_mult *sfx); \
18unsigned type xato##UT##_range(const char *str, unsigned type l, unsigned type u); \
19unsigned type xato##UT##_sfx(const char *str, const struct suffix_mult *sfx); \
20unsigned type xato##UT(const char *str); \
21type xstrto##T##_range_sfx(const char *str, int b, type l, type u, const struct suffix_mult *sfx) ;\
22type xstrto##T##_range(const char *str, int b, type l, type u); \
23type xato##T##_range_sfx(const char *str, type l, type u, const struct suffix_mult *sfx); \
24type xato##T##_range(const char *str, type l, type u); \
25type xato##T##_sfx(const char *str, const struct suffix_mult *sfx); \
26type xato##T(const char *str); \
27
28/* Unsigned long long functions always exist */
29DECLARE_STR_CONV(long long, ll, ull)
30
31
32/* Provides extern inline definitions of functions */
33/* (useful for mapping them to the type of the same width) */
34#define DEFINE_EQUIV_STR_CONV(narrow, N, W, UN, UW) \
35\
36extern inline \
37unsigned narrow xstrto##UN##_range_sfx(const char *str, int b, unsigned narrow l, unsigned narrow u, const struct suffix_mult *sfx) \
38{ return xstrto##UW##_range_sfx(str, b, l, u, sfx); } \
39extern inline \
40unsigned narrow xstrto##UN##_range(const char *str, int b, unsigned narrow l, unsigned narrow u) \
41{ return xstrto##UW##_range(str, b, l, u); } \
42extern inline \
43unsigned narrow xstrto##UN##_sfx(const char *str, int b, const struct suffix_mult *sfx) \
44{ return xstrto##UW##_sfx(str, b, sfx); } \
45extern inline \
46unsigned narrow xstrto##UN(const char *str, int b) \
47{ return xstrto##UW(str, b); } \
48extern inline \
49unsigned narrow xato##UN##_range_sfx(const char *str, unsigned narrow l, unsigned narrow u, const struct suffix_mult *sfx) \
50{ return xato##UW##_range_sfx(str, l, u, sfx); } \
51extern inline \
52unsigned narrow xato##UN##_range(const char *str, unsigned narrow l, unsigned narrow u) \
53{ return xato##UW##_range(str, l, u); } \
54extern inline \
55unsigned narrow xato##UN##_sfx(const char *str, const struct suffix_mult *sfx) \
56{ return xato##UW##_sfx(str, sfx); } \
57extern inline \
58unsigned narrow xato##UN(const char *str) \
59{ return xato##UW(str); } \
60extern inline \
61narrow xstrto##N##_range_sfx(const char *str, int b, narrow l, narrow u, const struct suffix_mult *sfx) \
62{ return xstrto##W##_range_sfx(str, b, l, u, sfx); } \
63extern inline \
64narrow xstrto##N##_range(const char *str, int b, narrow l, narrow u) \
65{ return xstrto##W##_range(str, b, l, u); } \
66extern inline \
67narrow xato##N##_range_sfx(const char *str, narrow l, narrow u, const struct suffix_mult *sfx) \
68{ return xato##W##_range_sfx(str, l, u, sfx); } \
69extern inline \
70narrow xato##N##_range(const char *str, narrow l, narrow u) \
71{ return xato##W##_range(str, l, u); } \
72extern inline \
73narrow xato##N##_sfx(const char *str, const struct suffix_mult *sfx) \
74{ return xato##W##_sfx(str, sfx); } \
75extern inline \
76narrow xato##N(const char *str) \
77{ return xato##W(str); } \
78
79/* If long == long long, then just map them one-to-one */
80#if ULONG_MAX == ULLONG_MAX
81DEFINE_EQUIV_STR_CONV(long, l, ll, ul, ull)
82#else
83/* Else provide extern defs */
84DECLARE_STR_CONV(long, l, ul)
85#endif
86
87/* Same for int -> [long] long */
88#if UINT_MAX == ULLONG_MAX
89DEFINE_EQUIV_STR_CONV(int, i, ll, u, ull)
90#elif UINT_MAX == ULONG_MAX
91DEFINE_EQUIV_STR_CONV(int, i, l, u, ul)
92#else
93DECLARE_STR_CONV(int, i, u)
94#endif
diff --git a/libbb/Kbuild b/libbb/Kbuild
index fc4798bf3..1ddec9a8d 100644
--- a/libbb/Kbuild
+++ b/libbb/Kbuild
@@ -87,7 +87,7 @@ lib-y += vperror_msg.o
87lib-y += warn_ignoring_args.o 87lib-y += warn_ignoring_args.o
88lib-y += wfopen.o 88lib-y += wfopen.o
89lib-y += wfopen_input.o 89lib-y += wfopen_input.o
90lib-y += xatol.o 90lib-y += xatonum.o
91lib-y += xconnect.o 91lib-y += xconnect.o
92lib-y += xfuncs.o 92lib-y += xfuncs.o
93lib-y += xgetcwd.o 93lib-y += xgetcwd.o
diff --git a/libbb/xatol.c b/libbb/xatol.c
deleted file mode 100644
index cce8ad3eb..000000000
--- a/libbb/xatol.c
+++ /dev/null
@@ -1,236 +0,0 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * ascii-to-numbers implementations for busybox
4 *
5 * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
6 *
7 * Licensed under GPLv2, see file LICENSE in this tarball for details.
8 */
9
10#include "libbb.h"
11
12unsigned long long xstrtoull(const char *numstr, int base)
13{
14 unsigned long long r;
15 int old_errno;
16 char *e;
17 if ((*numstr == '-') || (isspace)(*numstr))
18 bb_error_msg_and_die("invalid number '%s'", numstr);
19 old_errno = errno;
20 errno = 0;
21 r = strtoull(numstr, &e, base);
22 if (errno || (numstr == e) || *e)
23 /* Error / no digits / illegal trailing chars */
24 bb_error_msg_and_die("invalid number '%s'", numstr);
25 /* No error. So restore errno. */
26 errno = old_errno;
27 return r;
28}
29
30unsigned long long xatoull(const char *numstr)
31{
32 return xstrtoull(numstr, 10);
33}
34
35unsigned long xstrtoul_range_sfx(const char *numstr, int base,
36 unsigned long lower,
37 unsigned long upper,
38 const struct suffix_mult *suffixes)
39{
40 unsigned long r;
41 int old_errno;
42 char *e;
43
44 /* Disallow '-' and any leading whitespace. Speed isn't critical here
45 * since we're parsing commandline args. So make sure we get the
46 * actual isspace function rather than a lnumstrer macro implementaion. */
47 if ((*numstr == '-') || (isspace)(*numstr))
48 goto inval;
49
50 /* Since this is a lib function, we're not allowed to reset errno to 0.
51 * Doing so could break an app that is deferring checking of errno.
52 * So, save the old value so that we can restore it if successful. */
53 old_errno = errno;
54 errno = 0;
55 r = strtoul(numstr, &e, base);
56 /* Do the initial validity check. Note: The standards do not
57 * guarantee that errno is set if no digits were found. So we
58 * must test for this explicitly. */
59 if (errno || (numstr == e))
60 goto inval; /* error / no digits / illegal trailing chars */
61
62 errno = old_errno; /* Ok. So restore errno. */
63
64 /* Do optional suffix parsing. Allow 'empty' suffix tables.
65 * Note that we also allow nul suffixes with associated multipliers,
66 * to allow for scaling of the numstr by some default multiplier. */
67 if (suffixes) {
68 while (suffixes->suffix) {
69 if (strcmp(suffixes->suffix, e) == 0) {
70 if (ULONG_MAX / suffixes->mult < r)
71 goto range; /* overflow! */
72 ++e;
73 r *= suffixes->mult;
74 break;
75 }
76 ++suffixes;
77 }
78 }
79
80 /* Note: trailing space is an error.
81 It would be easy enough to allow though if desired. */
82 if (*e)
83 goto inval;
84 /* Finally, check for range limits. */
85 if (r >= lower && r <= upper)
86 return r;
87 range:
88 bb_error_msg_and_die("number %s is not in %lu..%lu range",
89 numstr, lower, upper);
90 inval:
91 bb_error_msg_and_die("invalid number '%s'", numstr);
92}
93
94unsigned long xstrtoul_range(const char *numstr, int base,
95 unsigned long lower,
96 unsigned long upper)
97{
98 return xstrtoul_range_sfx(numstr, base, lower, upper, NULL);
99}
100
101unsigned long xstrtoul_sfx(const char *numstr, int base,
102 const struct suffix_mult *suffixes)
103{
104 return xstrtoul_range_sfx(numstr, base, 0, ULONG_MAX, suffixes);
105}
106
107unsigned long xstrtoul(const char *numstr, int base)
108{
109 return xstrtoul_range_sfx(numstr, base, 0, ULONG_MAX, NULL);
110}
111
112unsigned long xatoul_range_sfx(const char *numstr,
113 unsigned long lower,
114 unsigned long upper,
115 const struct suffix_mult *suffixes)
116{
117 return xstrtoul_range_sfx(numstr, 10, lower, upper, suffixes);
118}
119
120unsigned long xatoul_sfx(const char *numstr,
121 const struct suffix_mult *suffixes)
122{
123 return xstrtoul_range_sfx(numstr, 10, 0, ULONG_MAX, suffixes);
124}
125
126unsigned long xatoul_range(const char *numstr,
127 unsigned long lower,
128 unsigned long upper)
129{
130 return xstrtoul_range_sfx(numstr, 10, lower, upper, NULL);
131}
132
133unsigned long xatoul(const char *numstr)
134{
135 return xatoul_sfx(numstr, NULL);
136}
137
138/* Signed ones */
139
140long xstrtol_range_sfx(const char *numstr, int base,
141 long lower,
142 long upper,
143 const struct suffix_mult *suffixes)
144{
145 unsigned long u = LONG_MAX;
146 long r;
147 const char *p = numstr;
148
149 if ((p[0] == '-') && (p[1] != '+')) {
150 ++p;
151 ++u; /* two's complement */
152 }
153
154 r = xstrtoul_range_sfx(p, base, 0, u, suffixes);
155
156 if (*numstr == '-') {
157 r = -r;
158 }
159
160 if (r < lower || r > upper) {
161 bb_error_msg_and_die("number %s is not in %ld..%ld range",
162 numstr, lower, upper);
163 }
164
165 return r;
166}
167
168long xstrtol_range(const char *numstr, int base, long lower, long upper)
169{
170 return xstrtol_range_sfx(numstr, base, lower, upper, NULL);
171}
172
173long xatol_range_sfx(const char *numstr,
174 long lower,
175 long upper,
176 const struct suffix_mult *suffixes)
177{
178 return xstrtol_range_sfx(numstr, 10, lower, upper, suffixes);
179}
180
181long xatol_range(const char *numstr, long lower, long upper)
182{
183 return xstrtol_range_sfx(numstr, 10, lower, upper, NULL);
184}
185
186long xatol_sfx(const char *numstr, const struct suffix_mult *suffixes)
187{
188 return xstrtol_range_sfx(numstr, 10, LONG_MIN, LONG_MAX, suffixes);
189}
190
191long xatol(const char *numstr)
192{
193 return xstrtol_range_sfx(numstr, 10, LONG_MIN, LONG_MAX, NULL);
194}
195
196/* Others */
197
198unsigned xatou_range(const char *numstr, unsigned lower, unsigned upper)
199{
200 return xstrtoul_range_sfx(numstr, 10, lower, upper, NULL);
201}
202
203unsigned xatou_sfx(const char *numstr, const struct suffix_mult *suffixes)
204{
205 return xstrtoul_range_sfx(numstr, 10, 0, UINT_MAX, suffixes);
206}
207
208unsigned xatou(const char *numstr)
209{
210 return xatoul_range(numstr, 0, UINT_MAX);
211}
212
213int xatoi_range(const char *numstr, int lower, int upper)
214{
215 return xatol_range(numstr, lower, upper);
216}
217
218int xatoi(const char *numstr)
219{
220 return xatol_range(numstr, INT_MIN, INT_MAX);
221}
222
223int xatoi_u(const char *numstr)
224{
225 return xatoul_range(numstr, 0, INT_MAX);
226}
227
228uint32_t xatou32(const char *numstr)
229{
230 return xatoul_range(numstr, 0, 0xffffffff);
231}
232
233uint16_t xatou16(const char *numstr)
234{
235 return xatoul_range(numstr, 0, 0xffff);
236}
diff --git a/libbb/xatonum.c b/libbb/xatonum.c
new file mode 100644
index 000000000..910667c14
--- /dev/null
+++ b/libbb/xatonum.c
@@ -0,0 +1,91 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * ascii-to-numbers implementations for busybox
4 *
5 * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
6 *
7 * Licensed under GPLv2, see file LICENSE in this tarball for details.
8 */
9
10#include "libbb.h"
11
12#define type long long
13#define xstrtou(rest) xstrtoull##rest
14#define xstrto(rest) xstrtoll##rest
15#define xatou(rest) xatoull##rest
16#define xato(rest) xatoll##rest
17#define XSTR_UTYPE_MAX ULLONG_MAX
18#define XSTR_TYPE_MAX LLONG_MAX
19#define XSTR_TYPE_MIN LLONG_MIN
20#define XSTR_STRTOU strtoull
21#include "xatonum_template.c"
22#undef type
23#undef xstrtou
24#undef xstrto
25#undef xatou
26#undef xato
27#undef XSTR_UTYPE_MAX
28#undef XSTR_TYPE_MAX
29#undef XSTR_TYPE_MIN
30#undef XSTR_STRTOU
31
32#if ULONG_MAX != ULLONG_MAX
33#define type long
34#define xstrtou(rest) xstrtoul##rest
35#define xstrto(rest) xstrtol##rest
36#define xatou(rest) xatoul##rest
37#define xato(rest) xatol##rest
38#define XSTR_UTYPE_MAX ULONG_MAX
39#define XSTR_TYPE_MAX LONG_MAX
40#define XSTR_TYPE_MIN LONG_MIN
41#define XSTR_STRTOU strtoul
42#include "xatonum_template.c"
43#undef type
44#undef xstrtou
45#undef xstrto
46#undef xatou
47#undef xato
48#undef XSTR_UTYPE_MAX
49#undef XSTR_TYPE_MAX
50#undef XSTR_TYPE_MIN
51#undef XSTR_STRTOU
52#endif
53
54#if UINT_MAX != ULONG_MAX
55#define type int
56#define xstrtou(rest) xstrtou##rest
57#define xstrto(rest) xstrtoi##rest
58#define xatou(rest) xatou##rest
59#define xato(rest) xatoi##rest
60#define XSTR_UTYPE_MAX UINT_MAX
61#define XSTR_TYPE_MAX INT_MAX
62#define XSTR_TYPE_MIN INT_MIN
63#define XSTR_STRTOU strtoul
64#include "xatonum_template.c"
65#undef type
66#undef xstrtou
67#undef xstrto
68#undef xatou
69#undef xato
70#undef XSTR_UTYPE_MAX
71#undef XSTR_TYPE_MAX
72#undef XSTR_TYPE_MIN
73#undef XSTR_STRTOU
74#endif
75
76/* A few special cases */
77
78int xatoi_u(const char *numstr)
79{
80 return xatoul_range(numstr, 0, INT_MAX);
81}
82
83uint32_t xatou32(const char *numstr)
84{
85 return xatoul_range(numstr, 0, 0xffffffff);
86}
87
88uint16_t xatou16(const char *numstr)
89{
90 return xatoul_range(numstr, 0, 0xffff);
91}
diff --git a/libbb/xatonum_template.c b/libbb/xatonum_template.c
new file mode 100644
index 000000000..245586a5a
--- /dev/null
+++ b/libbb/xatonum_template.c
@@ -0,0 +1,175 @@
1/*
2You need to define the following (example):
3
4#define type long
5#define xstrtou(rest) xstrtoul##rest
6#define xstrto(rest) xstrtol##rest
7#define xatou(rest) xatoul##rest
8#define xato(rest) xatol##rest
9#define XSTR_UTYPE_MAX ULONG_MAX
10#define XSTR_TYPE_MAX LONG_MAX
11#define XSTR_TYPE_MIN LONG_MIN
12#define XSTR_STRTOU strtoul
13*/
14
15unsigned type xstrtou(_range_sfx)(const char *numstr, int base,
16 unsigned type lower,
17 unsigned type upper,
18 const struct suffix_mult *suffixes)
19{
20 unsigned type r;
21 int old_errno;
22 char *e;
23
24 /* Disallow '-' and any leading whitespace. Speed isn't critical here
25 * since we're parsing commandline args. So make sure we get the
26 * actual isspace function rather than a lnumstrer macro implementaion. */
27 if ((*numstr == '-') || (isspace)(*numstr))
28 goto inval;
29
30 /* Since this is a lib function, we're not allowed to reset errno to 0.
31 * Doing so could break an app that is deferring checking of errno.
32 * So, save the old value so that we can restore it if successful. */
33 old_errno = errno;
34 errno = 0;
35 r = XSTR_STRTOU(numstr, &e, base);
36 /* Do the initial validity check. Note: The standards do not
37 * guarantee that errno is set if no digits were found. So we
38 * must test for this explicitly. */
39 if (errno || (numstr == e))
40 goto inval; /* error / no digits / illegal trailing chars */
41
42 errno = old_errno; /* Ok. So restore errno. */
43
44 /* Do optional suffix parsing. Allow 'empty' suffix tables.
45 * Note that we also allow nul suffixes with associated multipliers,
46 * to allow for scaling of the numstr by some default multiplier. */
47 if (suffixes) {
48 while (suffixes->suffix) {
49 if (strcmp(suffixes->suffix, e) == 0) {
50 if (XSTR_UTYPE_MAX / suffixes->mult < r)
51 goto range; /* overflow! */
52 ++e;
53 r *= suffixes->mult;
54 break;
55 }
56 ++suffixes;
57 }
58 }
59
60 /* Note: trailing space is an error.
61 It would be easy enough to allow though if desired. */
62 if (*e)
63 goto inval;
64 /* Finally, check for range limits. */
65 if (r >= lower && r <= upper)
66 return r;
67 range:
68 bb_error_msg_and_die("number %s is not in %llu..%llu range",
69 numstr, (unsigned long long)lower,
70 (unsigned long long)upper);
71 inval:
72 bb_error_msg_and_die("invalid number '%s'", numstr);
73}
74
75unsigned type xstrtou(_range)(const char *numstr, int base,
76 unsigned type lower,
77 unsigned type upper)
78{
79 return xstrtou(_range_sfx)(numstr, base, lower, upper, NULL);
80}
81
82unsigned type xstrtou(_sfx)(const char *numstr, int base,
83 const struct suffix_mult *suffixes)
84{
85 return xstrtou(_range_sfx)(numstr, base, 0, XSTR_UTYPE_MAX, suffixes);
86}
87
88unsigned type xstrtou()(const char *numstr, int base)
89{
90 return xstrtou(_range_sfx)(numstr, base, 0, XSTR_UTYPE_MAX, NULL);
91}
92
93unsigned type xatou(_range_sfx)(const char *numstr,
94 unsigned type lower,
95 unsigned type upper,
96 const struct suffix_mult *suffixes)
97{
98 return xstrtou(_range_sfx)(numstr, 10, lower, upper, suffixes);
99}
100
101unsigned type xatou(_range)(const char *numstr,
102 unsigned type lower,
103 unsigned type upper)
104{
105 return xstrtou(_range_sfx)(numstr, 10, lower, upper, NULL);
106}
107
108unsigned type xatou(_sfx)(const char *numstr,
109 const struct suffix_mult *suffixes)
110{
111 return xstrtou(_range_sfx)(numstr, 10, 0, XSTR_UTYPE_MAX, suffixes);
112}
113
114unsigned type xatou()(const char *numstr)
115{
116 return xatou(_sfx)(numstr, NULL);
117}
118
119/* Signed ones */
120
121type xstrto(_range_sfx)(const char *numstr, int base,
122 type lower,
123 type upper,
124 const struct suffix_mult *suffixes)
125{
126 unsigned type u = XSTR_TYPE_MAX;
127 type r;
128 const char *p = numstr;
129
130 if ((p[0] == '-') && (p[1] != '+')) {
131 ++p;
132 ++u; /* two's complement */
133 }
134
135 r = xstrtou(_range_sfx)(p, base, 0, u, suffixes);
136
137 if (*numstr == '-') {
138 r = -r;
139 }
140
141 if (r < lower || r > upper) {
142 bb_error_msg_and_die("number %s is not in %lld..%lld range",
143 numstr, (long long)lower, (long long)upper);
144 }
145
146 return r;
147}
148
149type xstrto(_range)(const char *numstr, int base, type lower, type upper)
150{
151 return xstrto(_range_sfx)(numstr, base, lower, upper, NULL);
152}
153
154type xato(_range_sfx)(const char *numstr,
155 type lower,
156 type upper,
157 const struct suffix_mult *suffixes)
158{
159 return xstrto(_range_sfx)(numstr, 10, lower, upper, suffixes);
160}
161
162type xato(_range)(const char *numstr, type lower, type upper)
163{
164 return xstrto(_range_sfx)(numstr, 10, lower, upper, NULL);
165}
166
167type xato(_sfx)(const char *numstr, const struct suffix_mult *suffixes)
168{
169 return xstrto(_range_sfx)(numstr, 10, XSTR_TYPE_MIN, XSTR_TYPE_MAX, suffixes);
170}
171
172type xato()(const char *numstr)
173{
174 return xstrto(_range_sfx)(numstr, 10, XSTR_TYPE_MIN, XSTR_TYPE_MAX, NULL);
175}