diff options
Diffstat (limited to 'lib/mlibc/options/ansi/generic/stdlib-stubs.cpp')
-rw-r--r-- | lib/mlibc/options/ansi/generic/stdlib-stubs.cpp | 511 |
1 files changed, 0 insertions, 511 deletions
diff --git a/lib/mlibc/options/ansi/generic/stdlib-stubs.cpp b/lib/mlibc/options/ansi/generic/stdlib-stubs.cpp deleted file mode 100644 index 86b8a9a..0000000 --- a/lib/mlibc/options/ansi/generic/stdlib-stubs.cpp +++ /dev/null @@ -1,511 +0,0 @@ - -#include <errno.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <signal.h> -#include <ctype.h> -#include <stdio.h> -#include <wchar.h> -#include <setjmp.h> -#include <limits.h> - -#include <frg/random.hpp> -#include <mlibc/debug.hpp> -#include <bits/ensure.h> -#include <bits/sigset_t.h> - -#include <mlibc/allocator.hpp> -#include <mlibc/charcode.hpp> -#include <mlibc/ansi-sysdeps.hpp> -#include <mlibc/strtofp.hpp> -#include <mlibc/strtol.hpp> -#include <mlibc/global-config.hpp> - -#if __MLIBC_POSIX_OPTION -#include <pthread.h> -#endif // __MLIBC_POSIX_OPTION - -extern "C" int __cxa_atexit(void (*function)(void *), void *argument, void *dso_tag); -void __mlibc_do_finalize(); - -namespace { - // According to the first paragraph of [C11 7.22.7], - // mblen(), mbtowc() and wctomb() have an internal state. - // The string functions mbstowcs() and wcstombs() do *not* have this state. - thread_local __mlibc_mbstate mblen_state = __MLIBC_MBSTATE_INITIALIZER; - thread_local __mlibc_mbstate mbtowc_state = __MLIBC_MBSTATE_INITIALIZER; -} - -double atof(const char *string) { - return strtod(string, NULL); -} -int atoi(const char *string) { - return strtol(string, nullptr, 10); -} -long atol(const char *string) { - return strtol(string, nullptr, 10); -} -long long atoll(const char *string) { - return strtoll(string, nullptr, 10); -} - -// POSIX extensions but are here for simplicities sake. Forward declaration is here -// to avoid exporting sigprocmask when posix is disabled. -int sigprocmask(int, const sigset_t *__restrict, sigset_t *__restrict); -extern "C" { - __attribute__((__returns_twice__)) int __sigsetjmp(sigjmp_buf buffer, int savesigs) { - buffer[0].savesigs = savesigs; - if (savesigs) - sigprocmask(0, NULL, &buffer[0].sigset); - return 0; - } -} - -__attribute__((__noreturn__)) void siglongjmp(sigjmp_buf buffer, int value) { - if (buffer[0].savesigs) - sigprocmask(SIG_SETMASK, &buffer[0].sigset, NULL); - jmp_buf b; - b[0].reg_state = buffer[0].reg_state; - longjmp(b, value); -} - -double strtod(const char *__restrict string, char **__restrict end) { - return mlibc::strtofp<double>(string, end); -} -float strtof(const char *__restrict string, char **__restrict end) { - return mlibc::strtofp<float>(string, end); -} -long double strtold(const char *__restrict string, char **__restrict end) { - return mlibc::strtofp<long double>(string, end); -} - -long strtol(const char *__restrict string, char **__restrict end, int base) { - return mlibc::stringToInteger<long, char>(string, end, base); -} -long long strtoll(const char *__restrict string, char **__restrict end, int base) { - return mlibc::stringToInteger<long long, char>(string, end, base); -} -unsigned long strtoul(const char *__restrict string, char **__restrict end, int base) { - return mlibc::stringToInteger<unsigned long, char>(string, end, base); -} -unsigned long long strtoull(const char *__restrict string, char **__restrict end, int base) { - return mlibc::stringToInteger<unsigned long long, char>(string, end, base); -} - -frg::mt19937 __mlibc_rand_engine; - -int rand() { - // rand() is specified to return a positive number so we discard the MSB. - return static_cast<int>(__mlibc_rand_engine() & 0x7FFFFFFF); -} - -static unsigned temper(unsigned x) { - x ^= x >> 11; - x ^= x << 7 & 0x9D2C5680; - x ^= x << 15 & 0xEFC60000; - x ^= x >> 18; - return x; -} - -int rand_r(unsigned *seed) { - return temper(*seed = *seed * 1103515245 + 12345) / 2; -} - -void srand(unsigned int s) { - __mlibc_rand_engine.seed(s); -} - -void *aligned_alloc(size_t alignment, size_t size) { - void *ptr; - - // alignment must be a power of two, and size % alignment must be 0 - if (alignment & (alignment - 1) || size & (alignment - 1)) { - errno = EINVAL; - return nullptr; - } - - // posix_memalign requires that the alignment is a multiple of sizeof(void *) - if (alignment < sizeof(void *)) - alignment = sizeof(void *); - - int ret = posix_memalign(&ptr, alignment, size); - if (ret) { - errno = ret; - return nullptr; - } - return ptr; - -} -void *calloc(size_t count, size_t size) { - // we want to ensure that count*size > SIZE_MAX doesn't happen - // to prevent overflowing, we divide both sides of the inequality by size and check with that - if(size && count > (SIZE_MAX / size)) { - errno = EINVAL; - return NULL; - } - - // TODO: this could be done more efficient if the OS gives us already zero'd pages - void *ptr = malloc(count * size); - if(!ptr) - return nullptr; - memset(ptr, 0, count * size); - return ptr; -} -// free() is provided by the platform -// malloc() is provided by the platform -// realloc() is provided by the platform - -void abort(void) { - sigset_t set; - sigemptyset(&set); - sigaddset(&set, SIGABRT); - if (mlibc::sys_sigprocmask) { - mlibc::sys_sigprocmask(SIG_UNBLOCK, &set, nullptr); - } - - raise(SIGABRT); - - sigfillset(&set); - sigdelset(&set, SIGABRT); - if (mlibc::sys_sigprocmask) { - mlibc::sys_sigprocmask(SIG_SETMASK, &set, nullptr); - } - - struct sigaction sa; - sa.sa_handler = SIG_DFL; - sa.sa_flags = 0; - sigemptyset(&sa.sa_mask); - - if (mlibc::sys_sigaction(SIGABRT, &sa, nullptr)) - mlibc::panicLogger() << "mlibc: sigaction failed in abort" << frg::endlog; - - if (raise(SIGABRT)) - mlibc::panicLogger() << "mlibc: raise failed in abort" << frg::endlog; - - __builtin_trap(); -} - -int atexit(void (*func)(void)) { - // TODO: the function pointer types are not compatible; - // the conversion here is undefined behavior. its fine to do - // this on the x86_64 abi though. - __cxa_atexit((void (*) (void *))func, nullptr, nullptr); - return 0; -} -int at_quick_exit(void (*func)(void)) { - (void)func; - __ensure(!"Not implemented"); - __builtin_unreachable(); -} - -void exit(int status) { - __mlibc_do_finalize(); - mlibc::sys_exit(status); -} - -void _Exit(int status) { - mlibc::sys_exit(status); -} - -// getenv() is provided by POSIX -void quick_exit(int) { - __ensure(!"Not implemented"); - __builtin_unreachable(); -} - -extern char **environ; - -int system(const char *command) { - int status = -1; - pid_t child; - - MLIBC_CHECK_OR_ENOSYS(mlibc::sys_fork && mlibc::sys_waitpid && - mlibc::sys_execve && mlibc::sys_sigprocmask && mlibc::sys_sigaction, -1); - -#if __MLIBC_POSIX_OPTION - pthread_testcancel(); -#endif // __MLIBC_POSIX_OPTION - - if (!command) { - return 1; - } - - struct sigaction new_sa, old_int, old_quit; - sigset_t new_mask, old_mask; - - new_sa.sa_handler = SIG_IGN; - new_sa.sa_flags = 0; - sigemptyset(&new_sa.sa_mask); - mlibc::sys_sigaction(SIGINT, &new_sa, &old_int); - mlibc::sys_sigaction(SIGQUIT, &new_sa, &old_quit); - - sigemptyset(&new_mask); - sigaddset(&new_mask, SIGCHLD); - mlibc::sys_sigprocmask(SIG_BLOCK, &new_mask, &old_mask); - - if (int e = mlibc::sys_fork(&child)) { - errno = e; - } else if (!child) { - mlibc::sys_sigaction(SIGINT, &old_int, nullptr); - mlibc::sys_sigaction(SIGQUIT, &old_quit, nullptr); - mlibc::sys_sigprocmask(SIG_SETMASK, &old_mask, nullptr); - - const char *args[] = { - "sh", "-c", command, nullptr - }; - - mlibc::sys_execve("/bin/sh", const_cast<char **>(args), environ); - _Exit(127); - } else { - int err; - pid_t unused; - - while ((err = mlibc::sys_waitpid(child, &status, 0, NULL, &unused)) < 0) { - if (err == EINTR) - continue; - - errno = err; - status = -1; - } - } - - mlibc::sys_sigaction(SIGINT, &old_int, nullptr); - mlibc::sys_sigaction(SIGQUIT, &old_quit, nullptr); - mlibc::sys_sigprocmask(SIG_SETMASK, &old_mask, nullptr); - - return status; -} - -char *mktemp(char *) { - __ensure(!"Not implemented"); - __builtin_unreachable(); -} - -void *bsearch(const void *key, const void *base, size_t count, size_t size, - int (*compare)(const void *, const void *)) { - // Invariant: Element is in the interval [i, j). - size_t i = 0; - size_t j = count; - - while(i < j) { - size_t k = (j - i) / 2; - auto element = reinterpret_cast<const char *>(base) + (i + k) * size; - auto res = compare(key, element); - if(res < 0) { - j = i + k; - }else if(res > 0) { - i = i + k + 1; - }else{ - return const_cast<char *>(element); - } - } - __ensure(i == j); - - return nullptr; -} - -static int qsort_callback(const void *a, const void *b, void *arg) { - auto compare = reinterpret_cast<int (*)(const void *, const void *)>(arg); - - return compare(a, b); -} - -void qsort(void *base, size_t count, size_t size, - int (*compare)(const void *, const void *)) { - return qsort_r(base, count, size, qsort_callback, (void *) compare); -} - -void qsort_r(void *base, size_t count, size_t size, - int (*compare)(const void *, const void *, void *), - void *arg) { - // TODO: implement a faster sort - for(size_t i = 0; i < count; i++) { - void *u = (void *)((uintptr_t)base + i * size); - for(size_t j = i + 1; j < count; j++) { - void *v = (void *)((uintptr_t)base + j * size); - if(compare(u, v, arg) <= 0) - continue; - - // swap u and v - char *u_bytes = (char *)u; - char *v_bytes = (char *)v; - for(size_t k = 0; k < size; k++) { - char temp = u_bytes[k]; - u_bytes[k] = v_bytes[k]; - v_bytes[k] = temp; - } - } - } -} - -int abs(int num) { - return num < 0 ? -num : num; -} - -long labs(long num) { - return num < 0 ? -num : num; -} - -long long llabs(long long num) { - return num < 0 ? -num : num; -} - -div_t div(int number, int denom) { - div_t r; - r.quot = number / denom; - r.rem = number % denom; - return r; -} - -ldiv_t ldiv(long number, long denom) { - ldiv_t r; - r.quot = number / denom; - r.rem = number % denom; - return r; -} - -lldiv_t lldiv(long long number, long long denom) { - lldiv_t r; - r.quot = number / denom; - r.rem = number % denom; - return r; -} - -int mblen(const char *mbs, size_t mb_limit) { - auto cc = mlibc::current_charcode(); - wchar_t wc; - mlibc::code_seq<const char> nseq{mbs, mbs + mb_limit}; - mlibc::code_seq<wchar_t> wseq{&wc, &wc + 1}; - - if(!mbs) { - mblen_state = __MLIBC_MBSTATE_INITIALIZER; - return cc->has_shift_states; - } - - if(auto e = cc->decode_wtranscode(nseq, wseq, mblen_state); e != mlibc::charcode_error::null) - __ensure(!"decode_wtranscode() errors are not handled"); - return nseq.it - mbs; -} - -int mbtowc(wchar_t *__restrict wc, const char *__restrict mb, size_t max_size) { - auto cc = mlibc::current_charcode(); - __ensure(max_size); - - // If wc is NULL, decode into a single local character which we discard - // to obtain the length. - wchar_t tmp_wc; - if (!wc) - wc = &tmp_wc; - - if (mb) { - if (*mb) { - mlibc::code_seq<wchar_t> wseq{wc, wc + 1}; - mlibc::code_seq<const char> nseq{mb, mb + max_size}; - auto e = cc->decode_wtranscode(nseq, wseq, mbtowc_state); - switch(e) { - // We keep the state, so we can simply return here. - case mlibc::charcode_error::input_underflow: - case mlibc::charcode_error::null: { - return nseq.it - mb; - } - case mlibc::charcode_error::illegal_input: { - errno = -EILSEQ; - return -1; - } - case mlibc::charcode_error::dirty: { - mlibc::panicLogger() << "decode_wtranscode() charcode_error::dirty errors are not handled" << frg::endlog; - break; - } - case mlibc::charcode_error::output_overflow: { - mlibc::panicLogger() << "decode_wtranscode() charcode_error::output_overflow errors are not handled" << frg::endlog; - break; - } - } - __builtin_unreachable(); - } else { - *wc = L'\0'; - return 0; // When mbs is a null byte, return 0 - } - } else { - mblen_state = __MLIBC_MBSTATE_INITIALIZER; - return cc->has_shift_states; - } -} - -int wctomb(char *, wchar_t) { - __ensure(!"Not implemented"); - __builtin_unreachable(); -} - -size_t mbstowcs(wchar_t *wcs, const char *mbs, size_t wc_limit) { - auto cc = mlibc::current_charcode(); - __mlibc_mbstate st = __MLIBC_MBSTATE_INITIALIZER; - mlibc::code_seq<const char> nseq{mbs, nullptr}; - mlibc::code_seq<wchar_t> wseq{wcs, wcs + wc_limit}; - - if(!wcs) { - size_t size; - if(auto e = cc->decode_wtranscode_length(nseq, &size, st); e != mlibc::charcode_error::null) - __ensure(!"decode_wtranscode() errors are not handled"); - return size; - } - - if(auto e = cc->decode_wtranscode(nseq, wseq, st); e != mlibc::charcode_error::null) { - __ensure(!"decode_wtranscode() errors are not handled"); - __builtin_unreachable(); - }else{ - size_t n = wseq.it - wcs; - if(n < wc_limit) // Null-terminate resulting wide string. - wcs[n] = 0; - return n; - } -} - -size_t wcstombs(char *mb_string, const wchar_t *wc_string, size_t max_size) { - return wcsrtombs(mb_string, &wc_string, max_size, 0); -} - -void free(void *ptr) { - // TODO: Print PID only if POSIX option is enabled. - if (mlibc::globalConfig().debugMalloc) { - mlibc::infoLogger() << "mlibc (PID ?): free() on " - << ptr << frg::endlog; - if((uintptr_t)ptr & 1) - mlibc::infoLogger() << __builtin_return_address(0) << frg::endlog; - } - getAllocator().free(ptr); -} - -void *malloc(size_t size) { - auto nptr = getAllocator().allocate(size); - // TODO: Print PID only if POSIX option is enabled. - if (mlibc::globalConfig().debugMalloc) - mlibc::infoLogger() << "mlibc (PID ?): malloc() returns " - << nptr << frg::endlog; - return nptr; -} - -void *realloc(void *ptr, size_t size) { - auto nptr = getAllocator().reallocate(ptr, size); - // TODO: Print PID only if POSIX option is enabled. - if (mlibc::globalConfig().debugMalloc) - mlibc::infoLogger() << "mlibc (PID ?): realloc() on " - << ptr << " returns " << nptr << frg::endlog; - return nptr; -} - -int posix_memalign(void **out, size_t align, size_t size) { - if(align < sizeof(void *)) - return EINVAL; - if(align & (align - 1)) // Make sure that align is a power of two. - return EINVAL; - auto p = getAllocator().allocate(frg::max(align, size)); - if(!p) - return ENOMEM; - // Hope that the alignment was respected. This works on the current allocator. - // TODO: Make the allocator alignment-aware. - __ensure(!(reinterpret_cast<uintptr_t>(p) & (align - 1))); - *out = p; - return 0; -} |