#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); __builtin_unreachable(); } __noreturn void _Exit(int) { syscall(SYS_exit); __builtin_unreachable(); } // FIXME: This is walking a UTF-8 string twice. Once to decode, and another to count code points. size_t mbstowcs(wchar_t* buf, const char* src, size_t max) { if (max == 0) return 0; Utf8StringDecoder decoder(src); auto rc = decoder.decode(buf, max); if (rc.has_error()) return (size_t)-1; size_t code_points = decoder.code_points().value_or(0); if (code_points >= max) return max - 1; return code_points; } }