More stdlib.h implementation + commenting + atexit()
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
50509baea6
commit
c3653cd4e6
@ -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");
|
||||||
}
|
}
|
||||||
|
@ -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")
|
||||||
|
@ -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
28
libc/src/atexit.cpp
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
||||||
|
Loading…
Reference in New Issue
Block a user