// C runtime stubs for freestanding Nim #include /* Duplicates provided by libnexus.a (clib.o) */ #if 0 void *memcpy(void *dest, const void *src, size_t n) { ... } void *memset(void *s, int c, size_t n) { ... } void *memmove(void *dest, const void *src, size_t n) { ... } int memcmp(const void *s1, const void *s2, size_t n) { ... } /* Externs from libnexus.a */ extern size_t strlen(const char *s); extern int atoi(const char *nptr); extern int strncmp(const char *s1, const char *s2, size_t n); char *strcpy(char *dest, const char *src) { ... } int strcmp(const char *s1, const char *s2) { ... } char *strncpy(char *dest, const char *src, size_t n) { ... } #endif // panic is used by abort/exit void panic(const char* msg) { extern void console_write(const char*, unsigned long); extern size_t strlen(const char*); console_write("\n[KERNEL PANIC] ", 16); if (msg) console_write(msg, strlen(msg)); else console_write("Unknown Error", 13); console_write("\n", 1); while(1) { // Halt } } // abort is used by Nim panic void abort(void) { panic("abort() called"); while(1) {} } #if 0 /* Stdio stubs - these call into Zig UART */ extern void console_write(const char*, unsigned long); int puts(const char *s) { ... } int putchar(int c) { ... } // ... (printf, etc) int snprintf(char *str, size_t size, const char *format, ...) { ... } int fflush(void *stream) { ... } unsigned long fwrite(const void *ptr, unsigned long size, unsigned long nmemb, void *stream) { ... } sighandler_t signal(int signum, sighandler_t handler) { ... } int raise(int sig) { ... } int sprintf(char *str, const char *format, ...) { ... } double strtod(const char *nptr, char **endptr) { ... } #endif /* Exit stubs */ void exit(int status) { extern void panic(const char*); panic("exit() called - system halt"); while(1) {} } void _Exit(int status) { exit(status); } // qsort uses existing memcpy // Note: We need memcpy for qsort! // libnexus.a provides memcpy. We need to declare it. extern void *memcpy(void *dest, const void *src, size_t n); void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) { // Bubble sort for simplicity (O(n^2)) if (nmemb < 2) return; char *b = (char *)base; char tmp[256]; // Max item size 256 bytes for swap // Verify size? If size > 256, we fail or use loop. // mu_Container* is pointer size (8). for (size_t i = 0; i < nmemb - 1; i++) { for (size_t j = 0; j < nmemb - i - 1; j++) { char *p1 = b + j * size; char *p2 = b + (j + 1) * size; if (compar(p1, p2) > 0) { // Swap if (size <= 256) { memcpy(tmp, p1, size); memcpy(p1, p2, size); memcpy(p2, tmp, size); } } } } } // int errno = 0; // Provided by clib.c