rumpk/core/cstubs.c

270 lines
6.3 KiB
C

// C runtime stubs for freestanding Nim
#include <stddef.h>
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 <stdarg.h>
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 vsnprintf(char *str, size_t size, const char *format, va_list args) {
size_t count = 0;
if (size == 0) return 0;
while (*format && count < size - 1) {
if (*format == '%' && *(format + 1)) {
format++;
if (*format == 's') {
char *s = va_arg(args, char *);
if (s) {
while (*s && count < size - 1) {
str[count++] = *s++;
}
}
} else if (*format == 'd' || *format == 'i') {
int d = va_arg(args, int);
char buf[16];
itoa(d, buf);
char *b = buf;
while (*b && count < size - 1) {
str[count++] = *b++;
}
} else {
str[count++] = '%';
if (count < size - 1) str[count++] = *format;
}
} else {
str[count++] = *format;
}
format++;
}
str[count] = '\0';
return count;
}
int snprintf(char *str, size_t size, const char *format, ...) {
va_list args;
va_start(args, format);
int ret = vsnprintf(str, size, format, args);
va_end(args);
return ret;
}
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 sprintf(char *str, const char *format, ...) {
va_list args;
va_start(args, format);
// Unsafe sprintf limit
int ret = vsnprintf(str, 2048, format, args);
va_end(args);
return ret;
}
double strtod(const char *nptr, char **endptr) {
if (endptr) *endptr = (char*)nptr + strlen(nptr); // Fake endptr
return (double)atoi(nptr);
}
// qsort uses existing memcpy
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;