diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h index d1d9110..2e1e40a 100644 --- a/libc/include/stdlib.h +++ b/libc/include/stdlib.h @@ -3,7 +3,28 @@ #include -void* malloc(const size_t size); -void free(const void* ptr); +#define EXIT_SUCCESS 0 +#define EXIT_FAILURE 1 +#define RAND_MAX 0x7FFFFFF + +/* Memory allocation */ +void* malloc(size_t size); +void* calloc(size_t count, size_t size); +void* realloc(void* ptr, size_t size); +void free(void* ptr); + +/* Process controll */ +void _Exit(int status); +void exit(int status); + +// TODO: move atoi() here + +/* Random number generator */ +int rand(void); +void srand(unsigned int seed); + +/* Sort & search */ +void qsort(void* base, size_t nmemb, size_t size, int (*compar)(const void*, const void*)); +void* bsearch(const void* key, const void* base, size_t nmemb, size_t size, int (*compar)(const void*, const void*)); #endif diff --git a/libc/include/syscall.h b/libc/include/syscall.h index af9ebe6..4e4348e 100644 --- a/libc/include/syscall.h +++ b/libc/include/syscall.h @@ -17,16 +17,6 @@ typedef enum { SYS_SLEEP, } SYSCALL_NUMBERS; -typedef enum { - O_CREAT = 0x01, // Create if does not exist - O_RDONLY = 0x02, // Read only - O_WRONLY = 0x04, // Write only - O_RDWR = 0x08, // Read and write - O_APPEND = 0x10, // Always writes at the end (appends) - O_TRUNC = 0x20, // Truncate file size and position to 0 on Open - O_BIN = 0x40, // Read bytes, not text -} OFLAGS; - int syscall(int nr, int arg0, int arg1, int arg2); /* Syscall wrappers */ diff --git a/libc/stdlib/alloc.c b/libc/stdlib/alloc.c new file mode 100644 index 0000000..7006b72 --- /dev/null +++ b/libc/stdlib/alloc.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include + +void* malloc(size_t size) { + return (void*)syscall(SYS_MALLOC, size, 0, 0); +} + +void* calloc(size_t count, size_t size) { + size_t total = count * size; + void* ptr = malloc(total); + + if (!ptr) { return NULL; } + memset(ptr, 0, total); + + return ptr; +} + +void* realloc(void* ptr, size_t size) { + if (size == 0) { + free(ptr); + return NULL; + } + + if (ptr == NULL) { return malloc(size); } + + void* newptr = malloc(size); + if (!newptr) { return NULL; } + + // TODO: retrieve the old size + memcpy(newptr, ptr, size); + + free(ptr); + return newptr; +} + +void free(void* ptr) { + syscall(SYS_FREE, (int)ptr, 0, 0); +} + diff --git a/libc/stdlib/exit.c b/libc/stdlib/exit.c new file mode 100644 index 0000000..c179cfd --- /dev/null +++ b/libc/stdlib/exit.c @@ -0,0 +1,15 @@ +#include +#include + +// Exits without cleaning up +void _Exit(int status) { + syscall(SYS_EXIT, status, 0, 0); +} + +void exit(int status) { + // TODO: Close open files + // TODO: Free malloced buffers + + _Exit(status); +} + diff --git a/libc/stdlib/rand.c b/libc/stdlib/rand.c new file mode 100644 index 0000000..d3ff2c6 --- /dev/null +++ b/libc/stdlib/rand.c @@ -0,0 +1,15 @@ +#include + +// taken from glibc +#define RAND_A 1103515245 +#define RAND_C 12345 + +static size_t _next = 1; + +int rand(void) { + _next = (RAND_A * _next + RAND_C) & RAND_MAX; + return (int)(_next % (size_t)(RAND_MAX + 1)); +} + +void srand(size_t seed) { _next = seed; } + diff --git a/libc/stdlib/search.c b/libc/stdlib/search.c new file mode 100644 index 0000000..27dab9a --- /dev/null +++ b/libc/stdlib/search.c @@ -0,0 +1,25 @@ +#include +#include + +void* bsearch(const void* key, const void* base, size_t nitem, size_t size, int (*compar)(const void*, const void*)) { + size_t left = 0; + size_t right = nitem; + + while (left < right) { + size_t mid = left + (right - left) / 2; + void* midEl = (char*)base + mid * size; + + int cmp = compar(key, midEl); + + if (cmp < 0) { + right = mid; + } else if (cmp > 0) { + left = mid + 1; + } else { + return midEl; + } + } + + return NULL; +} + diff --git a/libc/stdlib/sort.c b/libc/stdlib/sort.c new file mode 100644 index 0000000..eabd421 --- /dev/null +++ b/libc/stdlib/sort.c @@ -0,0 +1,37 @@ +#include +#include +#include + +void swap(void* a, void* b, size_t size) { + char temp[size]; + memcpy(temp, a, size); + memcpy(a, b, size); + memcpy(b, temp, size); +} + +void* partition(void* base, size_t nitem, size_t size, int (*compar)(const void*, const void*)) { + char* pivot = (char*)base + (nitem - 1) * size; + char* i = (char*)base; + + for (char* j = (char*)base; j < pivot; j += size) { + if (compar(j, pivot) < 0) { + swap(i, j, size); + i += size; + } + } + + swap(i, pivot, size); + return i; +} + +void qsort(void* base, size_t nitem, size_t size, int (*compar)(const void*, const void*)) { + if (nitem <= 1) { return; } + + char* pivot = (char*)partition(base, nitem, size, compar); + size_t lsize = (pivot - (char*)base) / size; + size_t rsize = nitem - lsize - 1; + + qsort(base, lsize, size, compar); + qsort(pivot + size, rsize, size, compar); +} + diff --git a/libc/stdlib/stdlib.c b/libc/stdlib/stdlib.c deleted file mode 100644 index 5c623ea..0000000 --- a/libc/stdlib/stdlib.c +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include -#include - -void* malloc(const uint32_t size) { - return (void*)syscall(SYS_MALLOC, size, 0, 0); -} - -void free(const void* ptr) { - syscall(SYS_FREE, (int)ptr, 0, 0); -} -