// C runtime stubs for freestanding Nim #include void *memcpy(void *dest, const void *src, size_t n) { unsigned char *d = dest; const unsigned char *s = src; while (n--) *d++ = *s++; return dest; } void *memset(void *s, int c, size_t n) { unsigned char *p = s; while (n--) *p++ = (unsigned char)c; return s; } void *memmove(void *dest, const void *src, size_t n) { unsigned char *d = dest; const unsigned char *s = src; if (d < s) { while (n--) *d++ = *s++; } else { d += n; s += n; while (n--) *--d = *--s; } return dest; } int memcmp(const void *s1, const void *s2, size_t n) { const unsigned char *p1 = s1, *p2 = s2; while (n--) { if (*p1 != *p2) return *p1 - *p2; p1++; p2++; } return 0; } size_t strlen(const char *s) { size_t len = 0; while (*s++) len++; return len; } char *strcpy(char *dest, const char *src) { char *d = dest; while ((*d++ = *src++)); return dest; } int strcmp(const char *s1, const char *s2) { while (*s1 && (*s1 == *s2)) { s1++; s2++; } return *(unsigned char*)s1 - *(unsigned char*)s2; } int strncmp(const char *s1, const char *s2, size_t n) { while (n && *s1 && (*s1 == *s2)) { s1++; s2++; n--; } if (n == 0) return 0; return *(unsigned char*)s1 - *(unsigned char*)s2; } char *strncpy(char *dest, const char *src, size_t n) { char *d = dest; while (n && (*d++ = *src++)) n--; while (n--) *d++ = '\0'; return dest; } // abort is used by Nim panic void abort(void) { /* Call Nim panic */ extern void panic(const char*); panic("abort() called"); while(1) {} } /* Stdio stubs - these call into Zig UART */ extern void console_write(const char*, unsigned long); int puts(const char *s) { if (s) { unsigned long len = strlen(s); console_write(s, len); console_write("\n", 1); } return 0; } int putchar(int c) { char buf[1] = {(char)c}; console_write(buf, 1); return c; } #include void itoa(int n, char s[]) { int i, sign; if ((sign = n) < 0) n = -n; i = 0; do { s[i++] = n % 10 + '0'; } while ((n /= 10) > 0); if (sign < 0) s[i++] = '-'; s[i] = '\0'; // reverse for (int j = 0, k = i-1; j < k; j++, k--) { char temp = s[j]; s[j] = s[k]; s[k] = temp; } } int printf(const char *format, ...) { va_list args; va_start(args, format); while (*format) { if (*format == '%' && *(format + 1)) { format++; if (*format == 's') { char *s = va_arg(args, char *); if (s) console_write(s, strlen(s)); } else if (*format == 'd') { int d = va_arg(args, int); char buf[16]; itoa(d, buf); console_write(buf, strlen(buf)); } else { putchar('%'); putchar(*format); } } else { putchar(*format); } format++; } va_end(args); return 0; } int fprintf(void *stream, const char *format, ...) { return printf(format); } int fflush(void *stream) { return 0; } unsigned long fwrite(const void *ptr, unsigned long size, unsigned long nmemb, void *stream) { console_write(ptr, size * nmemb); return nmemb; } /* Signal stubs - no signals in freestanding */ typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler) { (void)signum; (void)handler; return (sighandler_t)0; } int raise(int sig) { (void)sig; return 0; } /* Exit stubs */ void exit(int status) { extern void panic(const char*); panic("exit() called - system halt"); while(1) {} } void _Exit(int status) { exit(status); } int atoi(const char *nptr) { int res = 0; while (*nptr >= '0' && *nptr <= '9') { res = res * 10 + (*nptr - '0'); nptr++; } return res; } int errno = 0; /* LwIP sys_now implementation */ extern unsigned int get_ticks(void); unsigned int sys_now(void) { return get_ticks(); }