xref: /openbmc/linux/tools/include/nolibc/stdlib.h (revision f0f04f28d5ae483b3b354cb3b63a3bab0b00cee4)
1 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
2 /*
3  * stdlib function definitions for NOLIBC
4  * Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
5  */
6 
7 #ifndef _NOLIBC_STDLIB_H
8 #define _NOLIBC_STDLIB_H
9 
10 #include "std.h"
11 #include "arch.h"
12 #include "types.h"
13 #include "sys.h"
14 
15 
16 /* Buffer used to store int-to-ASCII conversions. Will only be implemented if
17  * any of the related functions is implemented. The area is large enough to
18  * store "18446744073709551615" or "-9223372036854775808" and the final zero.
19  */
20 static __attribute__((unused)) char itoa_buffer[21];
21 
22 /*
23  * As much as possible, please keep functions alphabetically sorted.
24  */
25 
26 /* must be exported, as it's used by libgcc for various divide functions */
27 __attribute__((weak,unused,noreturn,section(".text.nolibc_abort")))
28 void abort(void)
29 {
30 	sys_kill(sys_getpid(), SIGABRT);
31 	for (;;);
32 }
33 
34 static __attribute__((unused))
35 long atol(const char *s)
36 {
37 	unsigned long ret = 0;
38 	unsigned long d;
39 	int neg = 0;
40 
41 	if (*s == '-') {
42 		neg = 1;
43 		s++;
44 	}
45 
46 	while (1) {
47 		d = (*s++) - '0';
48 		if (d > 9)
49 			break;
50 		ret *= 10;
51 		ret += d;
52 	}
53 
54 	return neg ? -ret : ret;
55 }
56 
57 static __attribute__((unused))
58 int atoi(const char *s)
59 {
60 	return atol(s);
61 }
62 
63 /* Converts the unsigned long integer <in> to its hex representation into
64  * buffer <buffer>, which must be long enough to store the number and the
65  * trailing zero (17 bytes for "ffffffffffffffff" or 9 for "ffffffff"). The
66  * buffer is filled from the first byte, and the number of characters emitted
67  * (not counting the trailing zero) is returned. The function is constructed
68  * in a way to optimize the code size and avoid any divide that could add a
69  * dependency on large external functions.
70  */
71 static __attribute__((unused))
72 int utoh_r(unsigned long in, char *buffer)
73 {
74 	signed char pos = (~0UL > 0xfffffffful) ? 60 : 28;
75 	int digits = 0;
76 	int dig;
77 
78 	do {
79 		dig = in >> pos;
80 		in -= (uint64_t)dig << pos;
81 		pos -= 4;
82 		if (dig || digits || pos < 0) {
83 			if (dig > 9)
84 				dig += 'a' - '0' - 10;
85 			buffer[digits++] = '0' + dig;
86 		}
87 	} while (pos >= 0);
88 
89 	buffer[digits] = 0;
90 	return digits;
91 }
92 
93 /* converts unsigned long <in> to an hex string using the static itoa_buffer
94  * and returns the pointer to that string.
95  */
96 static inline __attribute__((unused))
97 char *utoh(unsigned long in)
98 {
99 	utoh_r(in, itoa_buffer);
100 	return itoa_buffer;
101 }
102 
103 /* Converts the unsigned long integer <in> to its string representation into
104  * buffer <buffer>, which must be long enough to store the number and the
105  * trailing zero (21 bytes for 18446744073709551615 in 64-bit, 11 for
106  * 4294967295 in 32-bit). The buffer is filled from the first byte, and the
107  * number of characters emitted (not counting the trailing zero) is returned.
108  * The function is constructed in a way to optimize the code size and avoid
109  * any divide that could add a dependency on large external functions.
110  */
111 static __attribute__((unused))
112 int utoa_r(unsigned long in, char *buffer)
113 {
114 	unsigned long lim;
115 	int digits = 0;
116 	int pos = (~0UL > 0xfffffffful) ? 19 : 9;
117 	int dig;
118 
119 	do {
120 		for (dig = 0, lim = 1; dig < pos; dig++)
121 			lim *= 10;
122 
123 		if (digits || in >= lim || !pos) {
124 			for (dig = 0; in >= lim; dig++)
125 				in -= lim;
126 			buffer[digits++] = '0' + dig;
127 		}
128 	} while (pos--);
129 
130 	buffer[digits] = 0;
131 	return digits;
132 }
133 
134 /* Converts the signed long integer <in> to its string representation into
135  * buffer <buffer>, which must be long enough to store the number and the
136  * trailing zero (21 bytes for -9223372036854775808 in 64-bit, 12 for
137  * -2147483648 in 32-bit). The buffer is filled from the first byte, and the
138  * number of characters emitted (not counting the trailing zero) is returned.
139  */
140 static __attribute__((unused))
141 int itoa_r(long in, char *buffer)
142 {
143 	char *ptr = buffer;
144 	int len = 0;
145 
146 	if (in < 0) {
147 		in = -in;
148 		*(ptr++) = '-';
149 		len++;
150 	}
151 	len += utoa_r(in, ptr);
152 	return len;
153 }
154 
155 /* for historical compatibility, same as above but returns the pointer to the
156  * buffer.
157  */
158 static inline __attribute__((unused))
159 char *ltoa_r(long in, char *buffer)
160 {
161 	itoa_r(in, buffer);
162 	return buffer;
163 }
164 
165 /* converts long integer <in> to a string using the static itoa_buffer and
166  * returns the pointer to that string.
167  */
168 static inline __attribute__((unused))
169 char *itoa(long in)
170 {
171 	itoa_r(in, itoa_buffer);
172 	return itoa_buffer;
173 }
174 
175 /* converts long integer <in> to a string using the static itoa_buffer and
176  * returns the pointer to that string. Same as above, for compatibility.
177  */
178 static inline __attribute__((unused))
179 char *ltoa(long in)
180 {
181 	itoa_r(in, itoa_buffer);
182 	return itoa_buffer;
183 }
184 
185 /* converts unsigned long integer <in> to a string using the static itoa_buffer
186  * and returns the pointer to that string.
187  */
188 static inline __attribute__((unused))
189 char *utoa(unsigned long in)
190 {
191 	utoa_r(in, itoa_buffer);
192 	return itoa_buffer;
193 }
194 
195 /* Converts the unsigned 64-bit integer <in> to its hex representation into
196  * buffer <buffer>, which must be long enough to store the number and the
197  * trailing zero (17 bytes for "ffffffffffffffff"). The buffer is filled from
198  * the first byte, and the number of characters emitted (not counting the
199  * trailing zero) is returned. The function is constructed in a way to optimize
200  * the code size and avoid any divide that could add a dependency on large
201  * external functions.
202  */
203 static __attribute__((unused))
204 int u64toh_r(uint64_t in, char *buffer)
205 {
206 	signed char pos = 60;
207 	int digits = 0;
208 	int dig;
209 
210 	do {
211 		if (sizeof(long) >= 8) {
212 			dig = (in >> pos) & 0xF;
213 		} else {
214 			/* 32-bit platforms: avoid a 64-bit shift */
215 			uint32_t d = (pos >= 32) ? (in >> 32) : in;
216 			dig = (d >> (pos & 31)) & 0xF;
217 		}
218 		if (dig > 9)
219 			dig += 'a' - '0' - 10;
220 		pos -= 4;
221 		if (dig || digits || pos < 0)
222 			buffer[digits++] = '0' + dig;
223 	} while (pos >= 0);
224 
225 	buffer[digits] = 0;
226 	return digits;
227 }
228 
229 /* converts uint64_t <in> to an hex string using the static itoa_buffer and
230  * returns the pointer to that string.
231  */
232 static inline __attribute__((unused))
233 char *u64toh(uint64_t in)
234 {
235 	u64toh_r(in, itoa_buffer);
236 	return itoa_buffer;
237 }
238 
239 /* Converts the unsigned 64-bit integer <in> to its string representation into
240  * buffer <buffer>, which must be long enough to store the number and the
241  * trailing zero (21 bytes for 18446744073709551615). The buffer is filled from
242  * the first byte, and the number of characters emitted (not counting the
243  * trailing zero) is returned. The function is constructed in a way to optimize
244  * the code size and avoid any divide that could add a dependency on large
245  * external functions.
246  */
247 static __attribute__((unused))
248 int u64toa_r(uint64_t in, char *buffer)
249 {
250 	unsigned long long lim;
251 	int digits = 0;
252 	int pos = 19; /* start with the highest possible digit */
253 	int dig;
254 
255 	do {
256 		for (dig = 0, lim = 1; dig < pos; dig++)
257 			lim *= 10;
258 
259 		if (digits || in >= lim || !pos) {
260 			for (dig = 0; in >= lim; dig++)
261 				in -= lim;
262 			buffer[digits++] = '0' + dig;
263 		}
264 	} while (pos--);
265 
266 	buffer[digits] = 0;
267 	return digits;
268 }
269 
270 /* Converts the signed 64-bit integer <in> to its string representation into
271  * buffer <buffer>, which must be long enough to store the number and the
272  * trailing zero (21 bytes for -9223372036854775808). The buffer is filled from
273  * the first byte, and the number of characters emitted (not counting the
274  * trailing zero) is returned.
275  */
276 static __attribute__((unused))
277 int i64toa_r(int64_t in, char *buffer)
278 {
279 	char *ptr = buffer;
280 	int len = 0;
281 
282 	if (in < 0) {
283 		in = -in;
284 		*(ptr++) = '-';
285 		len++;
286 	}
287 	len += u64toa_r(in, ptr);
288 	return len;
289 }
290 
291 /* converts int64_t <in> to a string using the static itoa_buffer and returns
292  * the pointer to that string.
293  */
294 static inline __attribute__((unused))
295 char *i64toa(int64_t in)
296 {
297 	i64toa_r(in, itoa_buffer);
298 	return itoa_buffer;
299 }
300 
301 /* converts uint64_t <in> to a string using the static itoa_buffer and returns
302  * the pointer to that string.
303  */
304 static inline __attribute__((unused))
305 char *u64toa(uint64_t in)
306 {
307 	u64toa_r(in, itoa_buffer);
308 	return itoa_buffer;
309 }
310 
311 #endif /* _NOLIBC_STDLIB_H */
312