// C runtime stubs for freestanding Nim
#include <stddef.h>

/* 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
