0001
0002
0003
0004
0005
0006
0007 #ifndef _NOLIBC_STDLIB_H
0008 #define _NOLIBC_STDLIB_H
0009
0010 #include "std.h"
0011 #include "arch.h"
0012 #include "types.h"
0013 #include "sys.h"
0014 #include "string.h"
0015
0016 struct nolibc_heap {
0017 size_t len;
0018 char user_p[] __attribute__((__aligned__));
0019 };
0020
0021
0022
0023
0024
0025 static __attribute__((unused)) char itoa_buffer[21];
0026
0027
0028
0029
0030
0031
0032 __attribute__((weak,unused,noreturn,section(".text.nolibc_abort")))
0033 void abort(void)
0034 {
0035 sys_kill(sys_getpid(), SIGABRT);
0036 for (;;);
0037 }
0038
0039 static __attribute__((unused))
0040 long atol(const char *s)
0041 {
0042 unsigned long ret = 0;
0043 unsigned long d;
0044 int neg = 0;
0045
0046 if (*s == '-') {
0047 neg = 1;
0048 s++;
0049 }
0050
0051 while (1) {
0052 d = (*s++) - '0';
0053 if (d > 9)
0054 break;
0055 ret *= 10;
0056 ret += d;
0057 }
0058
0059 return neg ? -ret : ret;
0060 }
0061
0062 static __attribute__((unused))
0063 int atoi(const char *s)
0064 {
0065 return atol(s);
0066 }
0067
0068 static __attribute__((unused))
0069 void free(void *ptr)
0070 {
0071 struct nolibc_heap *heap;
0072
0073 if (!ptr)
0074 return;
0075
0076 heap = container_of(ptr, struct nolibc_heap, user_p);
0077 munmap(heap, heap->len);
0078 }
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088 static __attribute__((unused))
0089 char *_getenv(const char *name, char **environ)
0090 {
0091 int idx, i;
0092
0093 if (environ) {
0094 for (idx = 0; environ[idx]; idx++) {
0095 for (i = 0; name[i] && name[i] == environ[idx][i];)
0096 i++;
0097 if (!name[i] && environ[idx][i] == '=')
0098 return &environ[idx][i+1];
0099 }
0100 }
0101 return NULL;
0102 }
0103
0104 static inline __attribute__((unused,always_inline))
0105 char *getenv(const char *name)
0106 {
0107 extern char **environ;
0108 return _getenv(name, environ);
0109 }
0110
0111 static __attribute__((unused))
0112 void *malloc(size_t len)
0113 {
0114 struct nolibc_heap *heap;
0115
0116
0117 len = sizeof(*heap) + len;
0118 len = (len + 4095UL) & -4096UL;
0119 heap = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE,
0120 -1, 0);
0121 if (__builtin_expect(heap == MAP_FAILED, 0))
0122 return NULL;
0123
0124 heap->len = len;
0125 return heap->user_p;
0126 }
0127
0128 static __attribute__((unused))
0129 void *calloc(size_t size, size_t nmemb)
0130 {
0131 size_t x = size * nmemb;
0132
0133 if (__builtin_expect(size && ((x / size) != nmemb), 0)) {
0134 SET_ERRNO(ENOMEM);
0135 return NULL;
0136 }
0137
0138
0139
0140
0141
0142 return malloc(x);
0143 }
0144
0145 static __attribute__((unused))
0146 void *realloc(void *old_ptr, size_t new_size)
0147 {
0148 struct nolibc_heap *heap;
0149 size_t user_p_len;
0150 void *ret;
0151
0152 if (!old_ptr)
0153 return malloc(new_size);
0154
0155 heap = container_of(old_ptr, struct nolibc_heap, user_p);
0156 user_p_len = heap->len - sizeof(*heap);
0157
0158
0159
0160
0161
0162 if (user_p_len >= new_size)
0163 return old_ptr;
0164
0165 ret = malloc(new_size);
0166 if (__builtin_expect(!ret, 0))
0167 return NULL;
0168
0169 memcpy(ret, heap->user_p, heap->len);
0170 munmap(heap, heap->len);
0171 return ret;
0172 }
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182 static __attribute__((unused))
0183 int utoh_r(unsigned long in, char *buffer)
0184 {
0185 signed char pos = (~0UL > 0xfffffffful) ? 60 : 28;
0186 int digits = 0;
0187 int dig;
0188
0189 do {
0190 dig = in >> pos;
0191 in -= (uint64_t)dig << pos;
0192 pos -= 4;
0193 if (dig || digits || pos < 0) {
0194 if (dig > 9)
0195 dig += 'a' - '0' - 10;
0196 buffer[digits++] = '0' + dig;
0197 }
0198 } while (pos >= 0);
0199
0200 buffer[digits] = 0;
0201 return digits;
0202 }
0203
0204
0205
0206
0207 static inline __attribute__((unused))
0208 char *utoh(unsigned long in)
0209 {
0210 utoh_r(in, itoa_buffer);
0211 return itoa_buffer;
0212 }
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222 static __attribute__((unused))
0223 int utoa_r(unsigned long in, char *buffer)
0224 {
0225 unsigned long lim;
0226 int digits = 0;
0227 int pos = (~0UL > 0xfffffffful) ? 19 : 9;
0228 int dig;
0229
0230 do {
0231 for (dig = 0, lim = 1; dig < pos; dig++)
0232 lim *= 10;
0233
0234 if (digits || in >= lim || !pos) {
0235 for (dig = 0; in >= lim; dig++)
0236 in -= lim;
0237 buffer[digits++] = '0' + dig;
0238 }
0239 } while (pos--);
0240
0241 buffer[digits] = 0;
0242 return digits;
0243 }
0244
0245
0246
0247
0248
0249
0250
0251 static __attribute__((unused))
0252 int itoa_r(long in, char *buffer)
0253 {
0254 char *ptr = buffer;
0255 int len = 0;
0256
0257 if (in < 0) {
0258 in = -in;
0259 *(ptr++) = '-';
0260 len++;
0261 }
0262 len += utoa_r(in, ptr);
0263 return len;
0264 }
0265
0266
0267
0268
0269 static inline __attribute__((unused))
0270 char *ltoa_r(long in, char *buffer)
0271 {
0272 itoa_r(in, buffer);
0273 return buffer;
0274 }
0275
0276
0277
0278
0279 static inline __attribute__((unused))
0280 char *itoa(long in)
0281 {
0282 itoa_r(in, itoa_buffer);
0283 return itoa_buffer;
0284 }
0285
0286
0287
0288
0289 static inline __attribute__((unused))
0290 char *ltoa(long in)
0291 {
0292 itoa_r(in, itoa_buffer);
0293 return itoa_buffer;
0294 }
0295
0296
0297
0298
0299 static inline __attribute__((unused))
0300 char *utoa(unsigned long in)
0301 {
0302 utoa_r(in, itoa_buffer);
0303 return itoa_buffer;
0304 }
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314 static __attribute__((unused))
0315 int u64toh_r(uint64_t in, char *buffer)
0316 {
0317 signed char pos = 60;
0318 int digits = 0;
0319 int dig;
0320
0321 do {
0322 if (sizeof(long) >= 8) {
0323 dig = (in >> pos) & 0xF;
0324 } else {
0325
0326 uint32_t d = (pos >= 32) ? (in >> 32) : in;
0327 dig = (d >> (pos & 31)) & 0xF;
0328 }
0329 if (dig > 9)
0330 dig += 'a' - '0' - 10;
0331 pos -= 4;
0332 if (dig || digits || pos < 0)
0333 buffer[digits++] = '0' + dig;
0334 } while (pos >= 0);
0335
0336 buffer[digits] = 0;
0337 return digits;
0338 }
0339
0340
0341
0342
0343 static inline __attribute__((unused))
0344 char *u64toh(uint64_t in)
0345 {
0346 u64toh_r(in, itoa_buffer);
0347 return itoa_buffer;
0348 }
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358 static __attribute__((unused))
0359 int u64toa_r(uint64_t in, char *buffer)
0360 {
0361 unsigned long long lim;
0362 int digits = 0;
0363 int pos = 19;
0364 int dig;
0365
0366 do {
0367 for (dig = 0, lim = 1; dig < pos; dig++)
0368 lim *= 10;
0369
0370 if (digits || in >= lim || !pos) {
0371 for (dig = 0; in >= lim; dig++)
0372 in -= lim;
0373 buffer[digits++] = '0' + dig;
0374 }
0375 } while (pos--);
0376
0377 buffer[digits] = 0;
0378 return digits;
0379 }
0380
0381
0382
0383
0384
0385
0386
0387 static __attribute__((unused))
0388 int i64toa_r(int64_t in, char *buffer)
0389 {
0390 char *ptr = buffer;
0391 int len = 0;
0392
0393 if (in < 0) {
0394 in = -in;
0395 *(ptr++) = '-';
0396 len++;
0397 }
0398 len += u64toa_r(in, ptr);
0399 return len;
0400 }
0401
0402
0403
0404
0405 static inline __attribute__((unused))
0406 char *i64toa(int64_t in)
0407 {
0408 i64toa_r(in, itoa_buffer);
0409 return itoa_buffer;
0410 }
0411
0412
0413
0414
0415 static inline __attribute__((unused))
0416 char *u64toa(uint64_t in)
0417 {
0418 u64toa_r(in, itoa_buffer);
0419 return itoa_buffer;
0420 }
0421
0422 #endif