More stdlib.h implementation + commenting + atexit()
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
apio 2023-01-06 19:40:25 +01:00
parent 50509baea6
commit c3653cd4e6
Signed by: apio
GPG Key ID: B8A7D06E42258954
5 changed files with 155 additions and 15 deletions

View File

@ -1,9 +1,16 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
void bye()
{
console_print("byeee!\n");
}
int main() int main()
{ {
for (int i = 0; i < strtol("010", NULL, 0); i++) { console_print("."); } atexit(bye);
for (int i = 0; i < atoi("8"); i++) { console_print("."); }
console_print("\n"); console_print("\n");
} }

View File

@ -7,6 +7,7 @@ set(SOURCES
src/unistd.cpp src/unistd.cpp
src/errno.cpp src/errno.cpp
src/string.cpp src/string.cpp
src/atexit.cpp
) )
if(${ARCH} STREQUAL "x86_64") if(${ARCH} STREQUAL "x86_64")

View File

@ -1,21 +1,26 @@
/* stdlib.h: General utilities header. */
#ifndef _STDLIB_H #ifndef _STDLIB_H
#define _STDLIB_H #define _STDLIB_H
#include <bits/attrs.h> #include <bits/attrs.h>
#include <stddef.h> #include <stddef.h>
/* The result of a division operation on two integers. */
typedef struct typedef struct
{ {
int quot; int quot;
int rem; int rem;
} div_t; } div_t;
/* The result of a division operation on two long integers. */
typedef struct typedef struct
{ {
long quot; long quot;
long rem; long rem;
} ldiv_t; } ldiv_t;
/* The result of a division operation on two long long integers. */
typedef struct typedef struct
{ {
long long quot; long long quot;
@ -27,12 +32,22 @@ extern "C"
{ {
#endif #endif
int abs(int); /* Returns the absolute value of v. */
long labs(long); int abs(int v);
long long llabs(long long);
div_t div(int, int); /* Returns the absolute value of v. */
long labs(long v);
/* Returns the absolute value of v. */
long long llabs(long long v);
/* Returns the result of dividing num by den, including the remainder. */
div_t div(int num, int den);
/* Returns the result of dividing num by den, including the remainder. */
ldiv_t ldiv(long, long); ldiv_t ldiv(long, long);
/* Returns the result of dividing num by den, including the remainder. */
lldiv_t lldiv(long long, long long); lldiv_t lldiv(long long, long long);
void* malloc(size_t); void* malloc(size_t);
@ -40,25 +55,42 @@ extern "C"
void* realloc(void*, size_t); void* realloc(void*, size_t);
void free(void*); void free(void*);
/* Aborts the program without performing any normal cleanup. */
__noreturn void abort(); __noreturn void abort();
int atexit(void (*)(void));
int atoi(const char*); /* Registers a handler to be run at normal program termination. */
long atol(const char*); int atexit(void (*func)(void));
long long atoll(const char*);
/* Parses a decimal integer from the provided string. */
int atoi(const char* s);
/* Parses a decimal integer from the provided string. */
long atol(const char* s);
/* Parses a decimal integer from the provided string. */
long long atoll(const char* s);
double atof(const char*); double atof(const char*);
double strtod(const char*, char**); double strtod(const char*, char**);
long strtol(const char*, char**, int); /* Parses an integer of the specified base from the string str, storing the first non-number character in endptr if
unsigned long strtoul(const char*, char**, int); * nonnull. */
long strtol(const char* str, char** endptr, int base);
/* Parses an unsigned integer of the specified base from the string str, storing the first non-number character in
* endptr if nonnull. */
unsigned long strtoul(const char* str, char** endptr, int base);
int rand(); int rand();
void srand(int); void srand(int);
/* Exits the program normally, performing any registered cleanup actions. */
__noreturn void exit(int); __noreturn void exit(int);
/* Exits the program abnormally, without performing any registered cleanup actions. */
__noreturn void _Exit(int);
int system(const char*); int system(const char*);
char* getenv(const char*); char* getenv(const char*);

28
libc/src/atexit.cpp Normal file
View File

@ -0,0 +1,28 @@
#include <stdlib.h>
typedef void (*atexit_func_t)(void);
const int ATEXIT_MAX_FUNCS = 48;
int atexit_registered_funcs = 0;
atexit_func_t atexit_funcs[ATEXIT_MAX_FUNCS];
extern "C"
{
int atexit(atexit_func_t func)
{
if (atexit_registered_funcs == ATEXIT_MAX_FUNCS) return -1;
atexit_funcs[atexit_registered_funcs++] = func;
return 0;
}
__noreturn void exit(int status)
{
while (atexit_registered_funcs--) { atexit_funcs[atexit_registered_funcs](); }
_Exit(status);
}
}

View File

@ -1,19 +1,91 @@
#include <limits.h>
#include <luna/NumberParsing.h> #include <luna/NumberParsing.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <unistd.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" extern "C"
{ {
// FIXME: Check for overflow in both strtol() and strtoul(). 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) long strtol(const char* str, char** endptr, int base)
{ {
return (long)parse_signed_integer(str, const_cast<const char**>(endptr), 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) unsigned long strtoul(const char* str, char** endptr, int base)
{ {
return (unsigned long)parse_unsigned_integer(str, const_cast<const char**>(endptr), 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() __noreturn void abort()
@ -22,7 +94,7 @@ extern "C"
__builtin_unreachable(); __builtin_unreachable();
} }
__noreturn void exit(int) __noreturn void _Exit(int)
{ {
syscall(SYS_exit); syscall(SYS_exit);
__builtin_unreachable(); __builtin_unreachable();