summaryrefslogtreecommitdiff
path: root/05/stdlib.h
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2022-02-16 15:41:30 -0500
committerpommicket <pommicket@gmail.com>2022-02-16 15:41:30 -0500
commit3a3f6cc424de23c5b4705644b6377ffee2491b31 (patch)
tree41ae3d6414befe8ed1bddc4699b2fc197c35bfee /05/stdlib.h
parentc6f1a399afc367271ada1d58f09fc00e3d298ce8 (diff)
stdlib.h
Diffstat (limited to '05/stdlib.h')
-rw-r--r--05/stdlib.h174
1 files changed, 174 insertions, 0 deletions
diff --git a/05/stdlib.h b/05/stdlib.h
index e98156b..c2f83eb 100644
--- a/05/stdlib.h
+++ b/05/stdlib.h
@@ -3,6 +3,21 @@
#include <stdc_common.h>
+#define EXIT_FAILURE (-1)
+#define EXIT_SUCCESS 0
+#define RAND_MAX 2147483647
+// @NONSTANDARD: we don't define MB_CUR_MAX or any of the mbtowc functions
+
+typedef struct {
+ int quot;
+ int rem;
+} div_t;
+
+typedef struct {
+ long quot;
+ long rem;
+} ldiv_t;
+
char *getenv(const char *name) {
int i, j;
for (i = 0; _envp[i]; ++i) {
@@ -16,4 +31,163 @@ char *getenv(const char *name) {
return NULL;
}
+double atof(const char *nptr) {
+ return strtod(nptr, NULL);
+}
+
+int atoi(const char *nptr) {
+ return _clamp_long_to_int(strtol(nptr, NULL, 10));
+}
+
+long atol(const char *nptr) {
+ return strtol(nptr, NULL, 10);
+}
+
+int rand(void) {
+ // https://en.wikipedia.org/wiki/Linear_congruential_generator
+ // we're using musl/newlib's constants
+ _rand_seed = 6364136223846793005 * _rand_seed + 1;
+ return _rand_seed >> 33;
+}
+
+void srand(unsigned seed) {
+ _rand_seed = seed;
+}
+
+void *calloc(size_t nmemb, size_t size) {
+ if (nmemb > 0xffffffffffffffff / size)
+ return NULL;
+ // NB: our malloc implementation returns zeroed memory
+ return malloc(nmemb * size);
+}
+
+void *realloc(void *ptr, size_t size) {
+ if (!ptr) return malloc(size);
+ if (!size) {
+ free(ptr);
+ return NULL;
+ }
+ uint64_t *memory = (char *)ptr - 16;
+ uint64_t old_size = *memory;
+ uint64_t *new_memory = _mremap(memory, old_size, size, MREMAP_MAYMOVE);
+ if ((uint64_t)new_memory > 0xffffffffffff0000) return NULL;
+ *new_memory = size;
+ return (char *)new_memory + 16;
+}
+
+
+int atexit(void (*func)(void)) {
+ if (_n_exit_handlers >= 32) return -1;
+ _exit_handlers[_n_exit_handlers++] = func;
+ return 0;
+}
+
+int system(const char *string) {
+ if (!string) return 1;
+
+ int pid = fork();
+ if (pid < 0) {
+ return -1;
+ } else if (pid == 0) {
+ // child
+ char *argv[] = {
+ "/bin/sh",
+ "-c",
+ 0,
+ 0
+ };
+ argv[2] = string;
+ execve("/bin/sh", argv, _envp);
+ // on success, execve does not return.
+ _Exit(-1);
+ } else {
+ // parent
+ int status = 0;
+ int ret = wait4(pid, &status, 0, NULL);
+ if (ret != pid) return -1;
+ if (_WIFSIGNALED(status)) return -1;
+ return _WEXITSTATUS(status);
+ }
+
+}
+
+void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) {
+ size_t lo = 0;
+ size_t hi = nmemb;
+ while (lo < hi) {
+ size_t mid = (lo + hi) >> 1;
+ void *elem = (char *)base + mid * size;
+ int cmp = compar(key, elem);
+ if (cmp < 0) {
+ // key < elem
+ hi = mid;
+ } else if (cmp) {
+ // key > elem
+ lo = mid + 1;
+ } else {
+ return elem;
+ }
+ }
+ return NULL;
+}
+
+void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) {
+ // quicksort
+ if (nmemb < 2) return;
+
+ void *temp = malloc(size);
+ void *mid = (char *)base + ((nmemb >> 1) * size); // choose middle element to speed up sorting an already-sorted array
+ size_t pivot_index = 0, i;
+ for (i = 0; i < nmemb; ++i) {
+ void *elem = (char *)base + i * size;
+ if (compar(elem, mid) < 0)
+ ++pivot_index;
+ }
+ void *pivot = (char *)base + pivot_index * size;
+ memcpy(temp, pivot, size);
+ memcpy(pivot, mid, size);
+ memcpy(mid, temp, size);
+
+ char *l, *r = (char *)base + (nmemb-1) * size;
+ for (l = base; l < r;) {
+ if (compar(l, pivot) > 0) {
+ // swap l and r
+ memcpy(temp, l, size);
+ memcpy(l, r, size);
+ memcpy(r, temp, size);
+ r -= size;
+ } else {
+ // l is already in the right place
+ l += size;
+ }
+ }
+
+ qsort(base, pivot_index, size, compar);
+ qsort((char *)pivot + size, nmemb - 1 - pivot_index, size, compar);
+
+ free(temp);
+}
+
+int abs(int x) {
+ return x >= 0 ? x : -x;
+}
+
+long labs(long x) {
+ return x >= 0 ? x : -x;
+}
+
+div_t div(int numer, int denom) {
+ div_t d;
+ d.quot = numer / denom;
+ d.rem = numer % denom;
+ return d;
+}
+
+ldiv_t ldiv(long numer, long denom) {
+ ldiv_t d;
+ d.quot = numer / denom;
+ d.rem = numer % denom;
+ return d;
+}
+
#endif // _STDLIB_H