xref: /openbmc/linux/tools/include/nolibc/stdlib.h (revision 56d68a3c1f41ca0843fd9151654c35f4925d911b)
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  * As much as possible, please keep functions alphabetically sorted.
17  */
18 
19 static __attribute__((unused))
20 long atol(const char *s)
21 {
22 	unsigned long ret = 0;
23 	unsigned long d;
24 	int neg = 0;
25 
26 	if (*s == '-') {
27 		neg = 1;
28 		s++;
29 	}
30 
31 	while (1) {
32 		d = (*s++) - '0';
33 		if (d > 9)
34 			break;
35 		ret *= 10;
36 		ret += d;
37 	}
38 
39 	return neg ? -ret : ret;
40 }
41 
42 static __attribute__((unused))
43 int atoi(const char *s)
44 {
45 	return atol(s);
46 }
47 
48 /* performs the opposite of atol() using a user-fed buffer. The buffer must be
49  * at least 21 bytes long (large enough for "-9223372036854775808").
50  */
51 static __attribute__((unused))
52 const char *ltoa_r(long in, char *buffer)
53 {
54 	char       *pos = buffer + 21 - 1;
55 	int         neg = in < 0;
56 	unsigned long n = neg ? -in : in;
57 
58 	*pos-- = '\0';
59 	do {
60 		*pos-- = '0' + n % 10;
61 		n /= 10;
62 		if (pos < buffer)
63 			return pos + 1;
64 	} while (n);
65 
66 	if (neg)
67 		*pos-- = '-';
68 	return pos + 1;
69 }
70 
71 /* performs the opposite of atol() using a statically allocated buffer */
72 static __attribute__((unused))
73 const char *ltoa(long in)
74 {
75 	/* large enough for -9223372036854775808 */
76 	static char buffer[21];
77 	return ltoa_r(in, buffer);
78 }
79 
80 static __attribute__((unused))
81 int msleep(unsigned int msecs)
82 {
83 	struct timeval my_timeval = { msecs / 1000, (msecs % 1000) * 1000 };
84 
85 	if (sys_select(0, 0, 0, 0, &my_timeval) < 0)
86 		return (my_timeval.tv_sec * 1000) +
87 			(my_timeval.tv_usec / 1000) +
88 			!!(my_timeval.tv_usec % 1000);
89 	else
90 		return 0;
91 }
92 
93 /* This one is not marked static as it's needed by libgcc for divide by zero */
94 __attribute__((weak,unused))
95 int raise(int signal)
96 {
97 	return kill(getpid(), signal);
98 }
99 
100 static __attribute__((unused))
101 unsigned int sleep(unsigned int seconds)
102 {
103 	struct timeval my_timeval = { seconds, 0 };
104 
105 	if (sys_select(0, 0, 0, 0, &my_timeval) < 0)
106 		return my_timeval.tv_sec + !!my_timeval.tv_usec;
107 	else
108 		return 0;
109 }
110 
111 static __attribute__((unused))
112 int tcsetpgrp(int fd, pid_t pid)
113 {
114 	return ioctl(fd, TIOCSPGRP, &pid);
115 }
116 
117 #endif /* _NOLIBC_STDLIB_H */
118