Luna/libc/src/stdlib.cpp

167 lines
3.5 KiB
C++
Raw Normal View History

#define _LUNA_SYSTEM_ERROR_EXTENSIONS
#include <errno.h>
#include <limits.h>
#include <luna/Heap.h>
#include <luna/NumberParsing.h>
#include <luna/Utf8.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <unistd.h>
template <typename ArgT, typename ResultT> 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<int, div_t>(num, den);
}
ldiv_t ldiv(long num, long den)
{
return __generic_div<long, ldiv_t>(num, den);
}
lldiv_t lldiv(long long num, long long den)
{
return __generic_div<long long, lldiv_t>(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<const char**>(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<const char**>(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;
Utf8StringDecoder decoder(src);
if (!buf) { return decoder.code_points().value_or((size_t)-1); }
return decoder.decode(buf, max).value_or((size_t)-1);
}
2023-01-14 10:59:08 +00:00
size_t wcstombs(char* buf, const wchar_t* src, size_t max)
{
if (max == 0) return 0;
Utf8StringEncoder encoder(src);
if (!buf) { return encoder.byte_length().value_or((size_t)-1); }
return encoder.encode(buf, max).value_or((size_t)-1);
}
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);
}
}