#include "forth.h" #include static inline long syscall3(long n, long a1, long a2, long a3) { long ret; __asm__ volatile ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), "d"(a3) : "rcx", "r11", "memory"); return ret; } static inline long syscall1(long n, long a1) { long ret; __asm__ volatile ("syscall" : "=a"(ret) : "a"(n), "D"(a1) : "rcx", "r11", "memory"); return ret; } void forth_putchar(char c) { char ch = c; syscall3(1, 1, (long)&ch, 1); } void forth_fflush(void) { } int forth_getchar(void) { unsigned char c; long n = syscall3(0, 0, (long)&c, 1); if (n <= 0) return FORTH_EOF; return (int)c; } void forth_panic(void) { syscall1(60, 1); __builtin_unreachable(); } int64_t forth_strtoll(const char* str, char** endptr, int base) { const char* s = str; int neg = 0; int64_t val = 0; while (forth_isspace(*s)) s++; if (*s == '-') { neg = 1; s++; } else if (*s == '+') { s++; } while (*s >= '0' && *s <= '9') { val = val * base + (*s - '0'); s++; } if (endptr) *endptr = (char*)s; return neg ? -val : val; } static void print_str(const char* s) { while (*s) forth_putchar(*s++); } static void print_int(long long v) { char buf[32]; int i = 30; int neg = 0; if (v < 0) { neg = 1; v = -v; } buf[31] = '\0'; if (v == 0) { buf[i--] = '0'; } else { while (v > 0 && i >= 0) { buf[i--] = '0' + (v % 10); v /= 10; } } if (neg) buf[i--] = '-'; print_str(&buf[i + 1]); } void forth_printf(const char* fmt, ...) { va_list ap; va_start(ap, fmt); while (*fmt) { if (*fmt == '%' && *(fmt + 1)) { fmt++; if (*fmt == 's') { print_str(va_arg(ap, const char*)); } else if (*fmt == 'c') { forth_putchar((char)va_arg(ap, int)); } else if (*fmt == '%') { forth_putchar('%'); } else if (*fmt == 'l') { if (*(fmt + 1) == 'l' && (*(fmt + 2) == 'd' || *(fmt + 2) == 'i' || *(fmt + 2) == 'u')) { fmt += 2; print_int(va_arg(ap, long long)); } } else if (*fmt == 'd' || *fmt == 'i' || *fmt == 'u') { print_int(va_arg(ap, int)); } else { forth_putchar('%'); forth_putchar(*fmt); } } else { forth_putchar(*fmt); } fmt++; } va_end(ap); } void _start(void) { forth_run(); syscall1(60, 0); __builtin_unreachable(); }