#include #include #include #include #include #include #include #include #include template static inline ResultT __generic_div(ArgT a, ArgT b) { ResultT result; result.quot = a / b; result.rem = a % b; if (a >= 0 && result.rem < 0) { result.quot++; result.rem -= b; } return result; } extern "C" { int abs(int v) { return __builtin_abs(v); } long labs(long v) { return __builtin_labs(v); } long long llabs(long long v) { return __builtin_llabs(v); } div_t div(int num, int den) { return __generic_div(num, den); } ldiv_t ldiv(long num, long den) { return __generic_div(num, den); } lldiv_t lldiv(long long num, long long den) { return __generic_div(num, den); } int atoi(const char* s) { return (int)strtol(s, NULL, 10); } long atol(const char* s) { return strtol(s, NULL, 10); } // Assuming LP64, long long == long. long long atoll(const char* s) { return (long long)strtol(s, NULL, 10); } // These checks are only necessary on LLP64 platforms, where long won't match size_t/ssize_t. Probably redundant // then (since Luna follows the regular LP64 model), but oh well... long strtol(const char* str, char** endptr, int base) { isize rc = parse_signed_integer(str, const_cast(endptr), base); if (rc > (isize)LONG_MAX) return LONG_MAX; if (rc < (isize)LONG_MIN) return LONG_MIN; return rc; } unsigned long strtoul(const char* str, char** endptr, int base) { usize rc = parse_unsigned_integer(str, const_cast(endptr), base); if (rc > (usize)ULONG_MAX) return ULONG_MAX; return rc; } __noreturn void abort() { syscall(SYS_exit, 255); __builtin_unreachable(); } __noreturn void _Exit(int status) { syscall(SYS_exit, status); __builtin_unreachable(); } size_t mbstowcs(wchar_t* buf, const char* src, size_t max) { if (max == 0) return 0; size_t result = (size_t)-1; Utf8StringDecoder decoder(src); if (!buf) { decoder.code_points().try_set_value_or_error(result, errno); return result; } decoder.decode(buf, max).try_set_value_or_error(result, errno); return result; } size_t wcstombs(char* buf, const wchar_t* src, size_t max) { if (max == 0) return 0; size_t result = (size_t)-1; Utf8StringEncoder encoder(src); if (!buf) { encoder.byte_length().try_set_value_or_error(result, errno); return result; } encoder.encode(buf, max).try_set_value_or_error(result, errno); return result; } void* malloc(size_t size) { auto rc = malloc_impl(size); if (rc.has_error()) { errno = rc.error(); return nullptr; } return rc.value(); } void* calloc(size_t nmemb, size_t size) { auto rc = calloc_impl(nmemb, size); if (rc.has_error()) { errno = rc.error(); return nullptr; } return rc.value(); } void* realloc(void* ptr, size_t size) { auto rc = realloc_impl(ptr, size); if (rc.has_error()) { errno = rc.error(); return nullptr; } return rc.value(); } void free(void* ptr) { free_impl(ptr); } int system(const char* cmd) { if (!cmd) { // FIXME: Check if there is a shell available in the system. errno = ENOTSUP; return -1; } pid_t child = fork(); if (child == 0) { execl("/bin/sh", "sh", "-c", cmd, NULL); _Exit(127); } if (child < 0) return -1; int status; waitpid(child, &status, 0); return status; } }