diff options
Diffstat (limited to 'userland/libc/stdlib')
-rw-r--r-- | userland/libc/stdlib/abort.c | 10 | ||||
-rw-r--r-- | userland/libc/stdlib/abs.c | 3 | ||||
-rw-r--r-- | userland/libc/stdlib/atexit.c | 6 | ||||
-rw-r--r-- | userland/libc/stdlib/atof.c | 5 | ||||
-rw-r--r-- | userland/libc/stdlib/atoi.c | 4 | ||||
-rw-r--r-- | userland/libc/stdlib/getenv.c | 6 | ||||
-rw-r--r-- | userland/libc/stdlib/mkstemp.c | 14 | ||||
-rw-r--r-- | userland/libc/stdlib/qsort.c | 29 | ||||
-rw-r--r-- | userland/libc/stdlib/rand.c | 17 | ||||
-rw-r--r-- | userland/libc/stdlib/srand.c | 8 | ||||
-rw-r--r-- | userland/libc/stdlib/strtod.c | 70 | ||||
-rw-r--r-- | userland/libc/stdlib/strtol.c | 52 | ||||
-rw-r--r-- | userland/libc/stdlib/strtold.c | 9 | ||||
-rw-r--r-- | userland/libc/stdlib/strtoul.c | 72 | ||||
-rw-r--r-- | userland/libc/stdlib/system.c | 17 |
15 files changed, 322 insertions, 0 deletions
diff --git a/userland/libc/stdlib/abort.c b/userland/libc/stdlib/abort.c new file mode 100644 index 0000000..7fd747e --- /dev/null +++ b/userland/libc/stdlib/abort.c @@ -0,0 +1,10 @@ +#include <assert.h> +#include <stdlib.h> + +// https://pubs.opengroup.org/onlinepubs/9699919799/functions/abort.html +void abort(void) { + printf("aborting!!!!\n"); + assert(0); + for (;;) + ; +} diff --git a/userland/libc/stdlib/abs.c b/userland/libc/stdlib/abs.c new file mode 100644 index 0000000..1079beb --- /dev/null +++ b/userland/libc/stdlib/abs.c @@ -0,0 +1,3 @@ +#include <stdlib.h> + +int abs(int i) { return (i < 0) ? (-i) : (i); } diff --git a/userland/libc/stdlib/atexit.c b/userland/libc/stdlib/atexit.c new file mode 100644 index 0000000..0e401ff --- /dev/null +++ b/userland/libc/stdlib/atexit.c @@ -0,0 +1,6 @@ +#include <stdlib.h> + +int atexit(void (*func)(void)) { + //TODO + return 0; +} diff --git a/userland/libc/stdlib/atof.c b/userland/libc/stdlib/atof.c new file mode 100644 index 0000000..8524f8b --- /dev/null +++ b/userland/libc/stdlib/atof.c @@ -0,0 +1,5 @@ +#include <stdlib.h> + +double atof(const char *str) { + return strtod(str,(char **)NULL); +} diff --git a/userland/libc/stdlib/atoi.c b/userland/libc/stdlib/atoi.c new file mode 100644 index 0000000..2183306 --- /dev/null +++ b/userland/libc/stdlib/atoi.c @@ -0,0 +1,4 @@ +#include <stdlib.h> + +// https://pubs.opengroup.org/onlinepubs/9699919799/ +int atoi(const char *str) { return (int)strtol(str, (char **)NULL, 10); } diff --git a/userland/libc/stdlib/getenv.c b/userland/libc/stdlib/getenv.c new file mode 100644 index 0000000..9a6a4e5 --- /dev/null +++ b/userland/libc/stdlib/getenv.c @@ -0,0 +1,6 @@ +#include <stdlib.h> + +char *getenv(const char *name) { + // FIXME + return NULL; +} diff --git a/userland/libc/stdlib/mkstemp.c b/userland/libc/stdlib/mkstemp.c new file mode 100644 index 0000000..1ea8790 --- /dev/null +++ b/userland/libc/stdlib/mkstemp.c @@ -0,0 +1,14 @@ +#include <fcntl.h> +#include <stdlib.h> + +char rand_char(void) { return 'A' + (rand() % 10); } + +int mkstemp(char *template) { + // FIXME: Incomplete + const char *s = template; + for (; *template; template ++) { + if ('X' == *template) + *template = rand_char(); + } + return open(s, O_RDWR, O_CREAT); +} diff --git a/userland/libc/stdlib/qsort.c b/userland/libc/stdlib/qsort.c new file mode 100644 index 0000000..3f87db5 --- /dev/null +++ b/userland/libc/stdlib/qsort.c @@ -0,0 +1,29 @@ +#include <stdlib.h> +#include <string.h> + +// https://pubs.opengroup.org/onlinepubs/9699919799/functions/qsort.html +void qsort(void *base, size_t nel, size_t width, + int (*compar)(const void *, const void *)) { + // If the nel argument has the value zero, the comparison function pointed to + // by compar shall not be called and no rearrangement shall take place. + if (0 == nel) + return; + + // AB + // Results in negative + // BA + // Results in positive + + // Using bubblesort + unsigned char *p = base; + for (size_t i = 1; i < nel; i++) { + for (size_t j = 0; j < nel; j++) { + if (compar((p + i * width), (p + j * width)) < 0) { + unsigned char tmp[width]; + memcpy(tmp, (p + i * width), width); + memcpy((p + i * width), (p + j * width), width); + memcpy((p + j * width), tmp, width); + } + } + } +} diff --git a/userland/libc/stdlib/rand.c b/userland/libc/stdlib/rand.c new file mode 100644 index 0000000..e186af7 --- /dev/null +++ b/userland/libc/stdlib/rand.c @@ -0,0 +1,17 @@ +#include <stdint.h> +#include <stdlib.h> + +uint32_t xorshift(uint32_t x) { + uint32_t f = x; + x ^= x << 13; + x ^= x >> 17; + x ^= x << 5; + return f + x; +} + +extern uint32_t __INTERNAL_RNG_STATE; +int rand(void) { + uint32_t x = xorshift(__INTERNAL_RNG_STATE); + __INTERNAL_RNG_STATE++; + return x; +} diff --git a/userland/libc/stdlib/srand.c b/userland/libc/stdlib/srand.c new file mode 100644 index 0000000..a35185a --- /dev/null +++ b/userland/libc/stdlib/srand.c @@ -0,0 +1,8 @@ +#include <stdint.h> +#include <stdlib.h> + +uint32_t __INTERNAL_RNG_STATE; +void srand(unsigned int seed) { + __INTERNAL_RNG_STATE = seed; + __INTERNAL_RNG_STATE = rand(); // rand() used the internal rng state +} diff --git a/userland/libc/stdlib/strtod.c b/userland/libc/stdlib/strtod.c new file mode 100644 index 0000000..2c83879 --- /dev/null +++ b/userland/libc/stdlib/strtod.c @@ -0,0 +1,70 @@ +#include <ctype.h> +#include <stdlib.h> +#include <assert.h> + +int ctoi(char c) { return c - '0'; } + +double strtod(const char *restrict nptr, char **restrict endptr) { + double r = 0; + // An initial, possibly empty, sequence of white-space characters (as + // specified by isspace()) + for (; isspace(*nptr); nptr++) + ; + + // A subject sequence interpreted as a floating-point constant or representing + // infinity or NaN + + { + // The expected form of the subject sequence is an optional '+' or '-' sign + int sign = 0; + int exp_sign = 0; + if ('+' == *nptr) { + sign = 0; + nptr++; + } else if ('-' == *nptr) { + sign = 1; + nptr++; + } + + // A non-empty sequence of decimal digits optionally containing a radix + // character + double exp = 0; + for (; isdigit(*nptr); nptr++) { + r *= 10; + r += ctoi(*nptr); + } + if ('.' == *nptr) { + double div = 10; + for (; isdigit(*nptr); nptr++) { + r += ctoi(*nptr) / div; + div *= 10; + } + } + r *= (sign) ? (-1) : (1); + + // then an optional exponent part consisting of the character 'e' or + // the character 'E' + if ('e' == tolower(*nptr)) { + // optionally followed by a '+' or '-' character + if ('+' == *nptr) { + exp_sign = 0; + nptr++; + } else if ('-' == *nptr) { + exp_sign = 1; + nptr++; + } + // and then followed by one or more decimal digits + for (; isdigit(*nptr); nptr++) { + exp *= 10; + exp += ctoi(*nptr); + } + exp *= (exp_sign) ? (-1) : (1); + } + assert(0 == exp); // TODO + } + + // A final string of one or more unrecognized characters, including the + // terminating NUL character of the input string + ; + return r; +} diff --git a/userland/libc/stdlib/strtol.c b/userland/libc/stdlib/strtol.c new file mode 100644 index 0000000..7aa7760 --- /dev/null +++ b/userland/libc/stdlib/strtol.c @@ -0,0 +1,52 @@ +#include <errno.h> +#include <limits.h> +#include <stdlib.h> +#include <assert.h> + +extern int errno; +extern int get_value(char c, long base); + +// https://pubs.opengroup.org/onlinepubs/9699919799/functions/strtol.html +long strtol(const char *str, char **restrict endptr, int base) { + long ret_value = 0; + if (endptr) + *endptr = str; + // Ignore inital white-space sequence + for (; *str && isspace(*str); str++) + ; + if (!*str) + return ret_value; + + int sign = 0; + if ('-' == *str) { + // FIXME + sign = 1; + str++; + assert(0); + } else if ('+' == *str) { + str++; + } + + if (0 == base) { + // FIXME + assert(0); + } + + if (2 <= base && 36 >= base) { + for (; *str; str++) { + ret_value *= base; + int val = get_value(*str, base); + if (ret_value > LONG_MAX - val) { + errno = ERANGE; + return 0; + } + ret_value += val; + } + } else { + errno = EINVAL; + return 0; + } + if (endptr) + *endptr = str; + return ret_value; +} diff --git a/userland/libc/stdlib/strtold.c b/userland/libc/stdlib/strtold.c new file mode 100644 index 0000000..222464e --- /dev/null +++ b/userland/libc/stdlib/strtold.c @@ -0,0 +1,9 @@ +#include <assert.h> +#include <stdlib.h> + +long double strtold(const char *restrict nptr, char **restrict endptr) { + // TODO + // I will do this some other day + assert(NULL); + return 0; +} diff --git a/userland/libc/stdlib/strtoul.c b/userland/libc/stdlib/strtoul.c new file mode 100644 index 0000000..4d9a51d --- /dev/null +++ b/userland/libc/stdlib/strtoul.c @@ -0,0 +1,72 @@ +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <limits.h> + +extern int errno; +int get_value(char c, long base) { + int r; + if (c >= '0' && c <= '9') + r = c - '0'; + else if (c >= 'A' && c <= 'Z') + r = c - 'A'; + else if (c >= 'a' && c <= 'z') + r = c - 'a'; + else + return -1; + if (r >= base) + return -1; + return r; +} + +// https://pubs.opengroup.org/onlinepubs/9699919799/functions/strtoul.html +unsigned long strtoul(const char *restrict str, char **restrict endptr, + int base) { + unsigned long ret_value = 0; + if (endptr) + *endptr = str; + // Ignore inital white-space sequence + for (; *str && isspace(*str); str++) + ; + if (!*str) + return ret_value; + + int sign = 0; + if ('-' == *str) { + // FIXME + sign = 1; + str++; + assert(0); + } else if ('+' == *str) { + str++; + } + + if (0 == base) { + // FIXME + assert(0); + } + + if (2 <= base && 36 >= base) { + for (; *str; str++) { + ret_value *= base; + int val = get_value(*str, base); + /* + if (-1 == val) { + errno = ERANGE; + return 0; + }*/ + if (ret_value > ULONG_MAX - val) { + errno = ERANGE; + return 0; + } + + ret_value += val; + } + } else { + errno = EINVAL; + return 0; + } + if (endptr) + *endptr = str; + return ret_value; +} diff --git a/userland/libc/stdlib/system.c b/userland/libc/stdlib/system.c new file mode 100644 index 0000000..d951c5c --- /dev/null +++ b/userland/libc/stdlib/system.c @@ -0,0 +1,17 @@ +#include <stdlib.h> + +int system(const char *command) { + if (!command) + return NULL; + int pid = fork(); + if (0 == pid) { + char *argv[2]; + argv[0] = "/sh"; + argv[1] = command; + execv("/sh", argv); + } + // FIXME: Use waitpid + int rc; + (void)wait(&rc); + return rc; +} |