Add more compat code for non GNU environments
[oweals/busybox.git] / include / xatonum.h
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 PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
11
12 /* Provides extern declarations of functions */
13 #define DECLARE_STR_CONV(type, T, UT) \
14 \
15 unsigned type xstrto##UT##_range_sfx(const char *str, int b, unsigned type l, unsigned type u, const struct suffix_mult *sfx) FAST_FUNC; \
16 unsigned type xstrto##UT##_range(const char *str, int b, unsigned type l, unsigned type u) FAST_FUNC; \
17 unsigned type xstrto##UT##_sfx(const char *str, int b, const struct suffix_mult *sfx) FAST_FUNC; \
18 unsigned type xstrto##UT(const char *str, int b) FAST_FUNC; \
19 unsigned type xato##UT##_range_sfx(const char *str, unsigned type l, unsigned type u, const struct suffix_mult *sfx) FAST_FUNC; \
20 unsigned type xato##UT##_range(const char *str, unsigned type l, unsigned type u) FAST_FUNC; \
21 unsigned type xato##UT##_sfx(const char *str, const struct suffix_mult *sfx) FAST_FUNC; \
22 unsigned type xato##UT(const char *str) FAST_FUNC; \
23 type xstrto##T##_range_sfx(const char *str, int b, type l, type u, const struct suffix_mult *sfx) FAST_FUNC; \
24 type xstrto##T##_range(const char *str, int b, type l, type u) FAST_FUNC; \
25 type xstrto##T(const char *str, int b) FAST_FUNC; \
26 type xato##T##_range_sfx(const char *str, type l, type u, const struct suffix_mult *sfx) FAST_FUNC; \
27 type xato##T##_range(const char *str, type l, type u) FAST_FUNC; \
28 type xato##T##_sfx(const char *str, const struct suffix_mult *sfx) FAST_FUNC; \
29 type xato##T(const char *str) FAST_FUNC; \
30
31 /* Unsigned long long functions always exist */
32 DECLARE_STR_CONV(long long, ll, ull)
33
34
35 /* Provides inline definitions of functions */
36 /* (useful for mapping them to the type of the same width) */
37 #define DEFINE_EQUIV_STR_CONV(narrow, N, W, UN, UW) \
38 \
39 static ALWAYS_INLINE \
40 unsigned narrow xstrto##UN##_range_sfx(const char *str, int b, unsigned narrow l, unsigned narrow u, const struct suffix_mult *sfx) \
41 { return xstrto##UW##_range_sfx(str, b, l, u, sfx); } \
42 static ALWAYS_INLINE \
43 unsigned narrow xstrto##UN##_range(const char *str, int b, unsigned narrow l, unsigned narrow u) \
44 { return xstrto##UW##_range(str, b, l, u); } \
45 static ALWAYS_INLINE \
46 unsigned narrow xstrto##UN##_sfx(const char *str, int b, const struct suffix_mult *sfx) \
47 { return xstrto##UW##_sfx(str, b, sfx); } \
48 static ALWAYS_INLINE \
49 unsigned narrow xstrto##UN(const char *str, int b) \
50 { return xstrto##UW(str, b); } \
51 static ALWAYS_INLINE \
52 unsigned narrow xato##UN##_range_sfx(const char *str, unsigned narrow l, unsigned narrow u, const struct suffix_mult *sfx) \
53 { return xato##UW##_range_sfx(str, l, u, sfx); } \
54 static ALWAYS_INLINE \
55 unsigned narrow xato##UN##_range(const char *str, unsigned narrow l, unsigned narrow u) \
56 { return xato##UW##_range(str, l, u); } \
57 static ALWAYS_INLINE \
58 unsigned narrow xato##UN##_sfx(const char *str, const struct suffix_mult *sfx) \
59 { return xato##UW##_sfx(str, sfx); } \
60 static ALWAYS_INLINE \
61 unsigned narrow xato##UN(const char *str) \
62 { return xato##UW(str); } \
63 static ALWAYS_INLINE \
64 narrow xstrto##N##_range_sfx(const char *str, int b, narrow l, narrow u, const struct suffix_mult *sfx) \
65 { return xstrto##W##_range_sfx(str, b, l, u, sfx); } \
66 static ALWAYS_INLINE \
67 narrow xstrto##N##_range(const char *str, int b, narrow l, narrow u) \
68 { return xstrto##W##_range(str, b, l, u); } \
69 static ALWAYS_INLINE \
70 narrow xstrto##N(const char *str, int b) \
71 { return xstrto##W(str, b); } \
72 static ALWAYS_INLINE \
73 narrow xato##N##_range_sfx(const char *str, narrow l, narrow u, const struct suffix_mult *sfx) \
74 { return xato##W##_range_sfx(str, l, u, sfx); } \
75 static ALWAYS_INLINE \
76 narrow xato##N##_range(const char *str, narrow l, narrow u) \
77 { return xato##W##_range(str, l, u); } \
78 static ALWAYS_INLINE \
79 narrow xato##N##_sfx(const char *str, const struct suffix_mult *sfx) \
80 { return xato##W##_sfx(str, sfx); } \
81 static ALWAYS_INLINE \
82 narrow xato##N(const char *str) \
83 { return xato##W(str); } \
84
85 /* If long == long long, then just map them one-to-one */
86 #if ULONG_MAX == ULLONG_MAX
87 DEFINE_EQUIV_STR_CONV(long, l, ll, ul, ull)
88 #else
89 /* Else provide extern defs */
90 DECLARE_STR_CONV(long, l, ul)
91 #endif
92
93 /* Same for int -> [long] long */
94 #if UINT_MAX == ULLONG_MAX
95 DEFINE_EQUIV_STR_CONV(int, i, ll, u, ull)
96 #elif UINT_MAX == ULONG_MAX
97 DEFINE_EQUIV_STR_CONV(int, i, l, u, ul)
98 #else
99 DECLARE_STR_CONV(int, i, u)
100 #endif
101
102 /* Specialized */
103
104 uint32_t BUG_xatou32_unimplemented(void);
105 static ALWAYS_INLINE uint32_t xatou32(const char *numstr)
106 {
107         if (UINT_MAX == 0xffffffff)
108                 return xatou(numstr);
109         if (ULONG_MAX == 0xffffffff)
110                 return xatoul(numstr);
111         return BUG_xatou32_unimplemented();
112 }
113
114 /* Non-aborting kind of convertors: bb_strto[u][l]l */
115
116 /* On exit: errno = 0 only if there was non-empty, '\0' terminated value
117  * errno = EINVAL if value was not '\0' terminated, but otherwise ok
118  *    Return value is still valid, caller should just check whether end[0]
119  *    is a valid terminating char for particular case. OTOH, if caller
120  *    requires '\0' terminated input, [s]he can just check errno == 0.
121  * errno = ERANGE if value had alphanumeric terminating char ("1234abcg").
122  * errno = ERANGE if value is out of range, missing, etc.
123  * errno = ERANGE if value had minus sign for strtouXX (even "-0" is not ok )
124  *    return value is all-ones in this case.
125  */
126
127 unsigned long long bb_strtoull(const char *arg, char **endp, int base) FAST_FUNC;
128 long long bb_strtoll(const char *arg, char **endp, int base) FAST_FUNC;
129
130 #if ULONG_MAX == ULLONG_MAX
131 static ALWAYS_INLINE
132 unsigned long bb_strtoul(const char *arg, char **endp, int base)
133 { return bb_strtoull(arg, endp, base); }
134 static ALWAYS_INLINE
135 long bb_strtol(const char *arg, char **endp, int base)
136 { return bb_strtoll(arg, endp, base); }
137 #else
138 unsigned long bb_strtoul(const char *arg, char **endp, int base) FAST_FUNC;
139 long bb_strtol(const char *arg, char **endp, int base) FAST_FUNC;
140 #endif
141
142 #if UINT_MAX == ULLONG_MAX
143 static ALWAYS_INLINE
144 unsigned bb_strtou(const char *arg, char **endp, int base)
145 { return bb_strtoull(arg, endp, base); }
146 static ALWAYS_INLINE
147 int bb_strtoi(const char *arg, char **endp, int base)
148 { return bb_strtoll(arg, endp, base); }
149 #elif UINT_MAX == ULONG_MAX
150 static ALWAYS_INLINE
151 unsigned bb_strtou(const char *arg, char **endp, int base)
152 { return bb_strtoul(arg, endp, base); }
153 static ALWAYS_INLINE
154 int bb_strtoi(const char *arg, char **endp, int base)
155 { return bb_strtol(arg, endp, base); }
156 #else
157 unsigned bb_strtou(const char *arg, char **endp, int base) FAST_FUNC;
158 int bb_strtoi(const char *arg, char **endp, int base) FAST_FUNC;
159 #endif
160
161 uint32_t BUG_bb_strtou32_unimplemented(void);
162 static ALWAYS_INLINE
163 uint32_t bb_strtou32(const char *arg, char **endp, int base)
164 {
165         if (sizeof(uint32_t) == sizeof(unsigned))
166                 return bb_strtou(arg, endp, base);
167         if (sizeof(uint32_t) == sizeof(unsigned long))
168                 return bb_strtoul(arg, endp, base);
169         return BUG_bb_strtou32_unimplemented();
170 }
171
172 /* Floating point */
173
174 double bb_strtod(const char *arg, char **endp) FAST_FUNC;
175
176 POP_SAVED_FUNCTION_VISIBILITY