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 static __attribute__((unused)) 27 long atol(const char *s) 28 { 29 unsigned long ret = 0; 30 unsigned long d; 31 int neg = 0; 32 33 if (*s == '-') { 34 neg = 1; 35 s++; 36 } 37 38 while (1) { 39 d = (*s++) - '0'; 40 if (d > 9) 41 break; 42 ret *= 10; 43 ret += d; 44 } 45 46 return neg ? -ret : ret; 47 } 48 49 static __attribute__((unused)) 50 int atoi(const char *s) 51 { 52 return atol(s); 53 } 54 55 /* Converts the unsigned long integer <in> to its string representation into 56 * buffer <buffer>, which must be long enough to store the number and the 57 * trailing zero (21 bytes for 18446744073709551615 in 64-bit, 11 for 58 * 4294967295 in 32-bit). The buffer is filled from the first byte, and the 59 * number of characters emitted (not counting the trailing zero) is returned. 60 * The function is constructed in a way to optimize the code size and avoid 61 * any divide that could add a dependency on large external functions. 62 */ 63 static __attribute__((unused)) 64 int utoa_r(unsigned long in, char *buffer) 65 { 66 unsigned long lim; 67 int digits = 0; 68 int pos = (~0UL > 0xfffffffful) ? 19 : 9; 69 int dig; 70 71 do { 72 for (dig = 0, lim = 1; dig < pos; dig++) 73 lim *= 10; 74 75 if (digits || in >= lim || !pos) { 76 for (dig = 0; in >= lim; dig++) 77 in -= lim; 78 buffer[digits++] = '0' + dig; 79 } 80 } while (pos--); 81 82 buffer[digits] = 0; 83 return digits; 84 } 85 86 /* Converts the signed long integer <in> to its string representation into 87 * buffer <buffer>, which must be long enough to store the number and the 88 * trailing zero (21 bytes for -9223372036854775808 in 64-bit, 12 for 89 * -2147483648 in 32-bit). The buffer is filled from the first byte, and the 90 * number of characters emitted (not counting the trailing zero) is returned. 91 */ 92 static __attribute__((unused)) 93 int itoa_r(long in, char *buffer) 94 { 95 char *ptr = buffer; 96 int len = 0; 97 98 if (in < 0) { 99 in = -in; 100 *(ptr++) = '-'; 101 len++; 102 } 103 len += utoa_r(in, ptr); 104 return len; 105 } 106 107 /* for historical compatibility, same as above but returns the pointer to the 108 * buffer. 109 */ 110 static inline __attribute__((unused)) 111 char *ltoa_r(long in, char *buffer) 112 { 113 itoa_r(in, buffer); 114 return buffer; 115 } 116 117 /* converts long integer <in> to a string using the static itoa_buffer and 118 * returns the pointer to that string. 119 */ 120 static inline __attribute__((unused)) 121 char *itoa(long in) 122 { 123 itoa_r(in, itoa_buffer); 124 return itoa_buffer; 125 } 126 127 /* converts long integer <in> to a string using the static itoa_buffer and 128 * returns the pointer to that string. Same as above, for compatibility. 129 */ 130 static inline __attribute__((unused)) 131 char *ltoa(long in) 132 { 133 itoa_r(in, itoa_buffer); 134 return itoa_buffer; 135 } 136 137 /* converts unsigned long integer <in> to a string using the static itoa_buffer 138 * and returns the pointer to that string. 139 */ 140 static inline __attribute__((unused)) 141 char *utoa(unsigned long in) 142 { 143 utoa_r(in, itoa_buffer); 144 return itoa_buffer; 145 } 146 147 /* Converts the unsigned 64-bit integer <in> to its string representation into 148 * buffer <buffer>, which must be long enough to store the number and the 149 * trailing zero (21 bytes for 18446744073709551615). The buffer is filled from 150 * the first byte, and the number of characters emitted (not counting the 151 * trailing zero) is returned. The function is constructed in a way to optimize 152 * the code size and avoid any divide that could add a dependency on large 153 * external functions. 154 */ 155 static __attribute__((unused)) 156 int u64toa_r(uint64_t in, char *buffer) 157 { 158 unsigned long long lim; 159 int digits = 0; 160 int pos = 19; /* start with the highest possible digit */ 161 int dig; 162 163 do { 164 for (dig = 0, lim = 1; dig < pos; dig++) 165 lim *= 10; 166 167 if (digits || in >= lim || !pos) { 168 for (dig = 0; in >= lim; dig++) 169 in -= lim; 170 buffer[digits++] = '0' + dig; 171 } 172 } while (pos--); 173 174 buffer[digits] = 0; 175 return digits; 176 } 177 178 /* Converts the signed 64-bit integer <in> to its string representation into 179 * buffer <buffer>, which must be long enough to store the number and the 180 * trailing zero (21 bytes for -9223372036854775808). The buffer is filled from 181 * the first byte, and the number of characters emitted (not counting the 182 * trailing zero) is returned. 183 */ 184 static __attribute__((unused)) 185 int i64toa_r(int64_t in, char *buffer) 186 { 187 char *ptr = buffer; 188 int len = 0; 189 190 if (in < 0) { 191 in = -in; 192 *(ptr++) = '-'; 193 len++; 194 } 195 len += u64toa_r(in, ptr); 196 return len; 197 } 198 199 /* converts int64_t <in> to a string using the static itoa_buffer and returns 200 * the pointer to that string. 201 */ 202 static inline __attribute__((unused)) 203 char *i64toa(int64_t in) 204 { 205 i64toa_r(in, itoa_buffer); 206 return itoa_buffer; 207 } 208 209 /* converts uint64_t <in> to a string using the static itoa_buffer and returns 210 * the pointer to that string. 211 */ 212 static inline __attribute__((unused)) 213 char *u64toa(uint64_t in) 214 { 215 u64toa_r(in, itoa_buffer); 216 return itoa_buffer; 217 } 218 219 static __attribute__((unused)) 220 int msleep(unsigned int msecs) 221 { 222 struct timeval my_timeval = { msecs / 1000, (msecs % 1000) * 1000 }; 223 224 if (sys_select(0, 0, 0, 0, &my_timeval) < 0) 225 return (my_timeval.tv_sec * 1000) + 226 (my_timeval.tv_usec / 1000) + 227 !!(my_timeval.tv_usec % 1000); 228 else 229 return 0; 230 } 231 232 /* This one is not marked static as it's needed by libgcc for divide by zero */ 233 __attribute__((weak,unused)) 234 int raise(int signal) 235 { 236 return kill(getpid(), signal); 237 } 238 239 static __attribute__((unused)) 240 unsigned int sleep(unsigned int seconds) 241 { 242 struct timeval my_timeval = { seconds, 0 }; 243 244 if (sys_select(0, 0, 0, 0, &my_timeval) < 0) 245 return my_timeval.tv_sec + !!my_timeval.tv_usec; 246 else 247 return 0; 248 } 249 250 static __attribute__((unused)) 251 int tcsetpgrp(int fd, pid_t pid) 252 { 253 return ioctl(fd, TIOCSPGRP, &pid); 254 } 255 256 #endif /* _NOLIBC_STDLIB_H */ 257