2023-01-13 19:00:20 +00:00
|
|
|
#include <errno.h>
|
2023-01-06 18:40:25 +00:00
|
|
|
#include <limits.h>
|
2023-01-13 19:00:20 +00:00
|
|
|
#include <luna/Heap.h>
|
2023-01-06 12:31:14 +00:00
|
|
|
#include <luna/NumberParsing.h>
|
2023-05-02 18:45:43 +00:00
|
|
|
#include <luna/Sort.h>
|
2023-01-06 20:01:37 +00:00
|
|
|
#include <luna/Utf8.h>
|
2023-01-06 12:31:14 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <sys/syscall.h>
|
2023-04-08 10:18:52 +00:00
|
|
|
#include <sys/wait.h>
|
2023-01-06 12:31:14 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
|
2023-01-06 18:40:25 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2023-01-06 12:31:14 +00:00
|
|
|
extern "C"
|
|
|
|
{
|
2023-01-06 18:40:25 +00:00
|
|
|
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...
|
2023-01-06 12:31:14 +00:00
|
|
|
long strtol(const char* str, char** endptr, int base)
|
|
|
|
{
|
2023-01-06 18:40:25 +00:00
|
|
|
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;
|
2023-01-06 12:31:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
unsigned long strtoul(const char* str, char** endptr, int base)
|
|
|
|
{
|
2023-01-06 18:40:25 +00:00
|
|
|
usize rc = parse_unsigned_integer(str, const_cast<const char**>(endptr), base);
|
|
|
|
|
|
|
|
if (rc > (usize)ULONG_MAX) return ULONG_MAX;
|
|
|
|
|
|
|
|
return rc;
|
2023-01-06 12:31:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
__noreturn void abort()
|
|
|
|
{
|
2023-03-23 21:25:56 +00:00
|
|
|
syscall(SYS_exit, 255);
|
2023-01-06 12:31:14 +00:00
|
|
|
__builtin_unreachable();
|
|
|
|
}
|
|
|
|
|
2023-03-23 21:25:56 +00:00
|
|
|
__noreturn void _Exit(int status)
|
2023-01-06 12:31:14 +00:00
|
|
|
{
|
2023-03-23 21:25:56 +00:00
|
|
|
syscall(SYS_exit, status);
|
2023-01-06 12:31:14 +00:00
|
|
|
__builtin_unreachable();
|
|
|
|
}
|
2023-01-06 20:01:37 +00:00
|
|
|
|
|
|
|
size_t mbstowcs(wchar_t* buf, const char* src, size_t max)
|
|
|
|
{
|
|
|
|
if (max == 0) return 0;
|
2023-04-07 08:55:22 +00:00
|
|
|
size_t result = (size_t)-1;
|
2023-01-06 20:01:37 +00:00
|
|
|
|
|
|
|
Utf8StringDecoder decoder(src);
|
|
|
|
|
2023-04-07 08:55:22 +00:00
|
|
|
if (!buf)
|
|
|
|
{
|
|
|
|
decoder.code_points().try_set_value_or_error(result, errno);
|
|
|
|
return result;
|
|
|
|
}
|
2023-01-06 20:01:37 +00:00
|
|
|
|
2023-04-07 08:55:22 +00:00
|
|
|
decoder.decode(buf, max).try_set_value_or_error(result, errno);
|
|
|
|
return result;
|
2023-01-06 20:01:37 +00:00
|
|
|
}
|
2023-01-13 19:00:20 +00:00
|
|
|
|
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;
|
2023-04-07 08:55:22 +00:00
|
|
|
size_t result = (size_t)-1;
|
2023-01-14 10:59:08 +00:00
|
|
|
|
|
|
|
Utf8StringEncoder encoder(src);
|
|
|
|
|
2023-04-07 08:55:22 +00:00
|
|
|
if (!buf)
|
|
|
|
{
|
|
|
|
encoder.byte_length().try_set_value_or_error(result, errno);
|
|
|
|
return result;
|
|
|
|
}
|
2023-01-14 10:59:08 +00:00
|
|
|
|
2023-04-07 08:55:22 +00:00
|
|
|
encoder.encode(buf, max).try_set_value_or_error(result, errno);
|
|
|
|
return result;
|
2023-01-14 10:59:08 +00:00
|
|
|
}
|
|
|
|
|
2023-01-13 19:00:20 +00:00
|
|
|
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);
|
|
|
|
}
|
2023-04-08 10:18:52 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2023-05-02 18:45:43 +00:00
|
|
|
|
|
|
|
void qsort(void* base, size_t nmemb, size_t size, int (*compar)(const void*, const void*))
|
|
|
|
{
|
|
|
|
c_quicksort(base, nmemb, size, compar);
|
|
|
|
}
|
2023-05-02 19:20:24 +00:00
|
|
|
|
|
|
|
static unsigned next = 42;
|
|
|
|
|
|
|
|
int rand()
|
|
|
|
{
|
|
|
|
next = next * 1103515245 + 12345;
|
|
|
|
return (int)((unsigned)(next / 65536) % 32768);
|
|
|
|
}
|
|
|
|
|
|
|
|
void srand(unsigned int seed)
|
|
|
|
{
|
|
|
|
next = seed;
|
|
|
|
}
|
2023-01-06 12:31:14 +00:00
|
|
|
}
|