From 64ac2fd842cb09e114bc6cf5d93cc2c861241e70 Mon Sep 17 00:00:00 2001 From: kdx Date: Sun, 17 Dec 2023 04:39:21 +0100 Subject: initial commit --- .gitignore | 1 + README | 1 + build.sh | 2 ++ sorth.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 99 insertions(+) create mode 100644 .gitignore create mode 100644 README create mode 100755 build.sh create mode 100644 sorth.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..204d390 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/sorth diff --git a/README b/README new file mode 100644 index 0000000..cc4270e --- /dev/null +++ b/README @@ -0,0 +1 @@ +bad forth in <100 lines of C diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..f9c52b1 --- /dev/null +++ b/build.sh @@ -0,0 +1,2 @@ +#!/bin/sh +gcc -o sorth sorth.c -g3 -O0 diff --git a/sorth.c b/sorth.c new file mode 100644 index 0000000..82cfb3a --- /dev/null +++ b/sorth.c @@ -0,0 +1,95 @@ +#include +#include +#include +#include + +long stack[1024] = {0}; +size_t stack_ptr = 0; +bool strict = false; + +static void panic(const char *msg) { + fprintf(stderr, "%s\n", msg); + exit(EXIT_FAILURE); +} + +static bool is(const char *s1, const char *s2) { + return strcmp(s1, s2) == 0; +} + +static long pop(void) { + if (stack_ptr == 0) + panic("stack undeflow"); + return stack[--stack_ptr]; +} + +static void push(long v) { + if (stack_ptr >= sizeof(stack) / sizeof(stack[0])) + panic("stack overflow"); + stack[stack_ptr++] = v; +} + +#define OP(X) } else if (strcmp(s, X) == 0) { +static void exec(const char *s) { + if (s[0] >= '0' && s[0] <= '9') { + push(atol(s)); + OP("drop") + pop(); + OP("dup") + const long a = pop(); + push(a); push(a); + OP("swap") + const long a = pop(); + const long b = pop(); + push(a); push(b); + OP("over") + const long a = pop(); + const long b = pop(); + push(a); push(b); push(a); + OP("rot") + const long a = pop(); + const long b = pop(); + const long c = pop(); + push(b); push(a); push(c); + OP("+") + push(pop() + pop()); + OP("-") + const long a = pop(); + push(pop() - a); + OP("*") + push(pop() * pop()); + OP("/") + const long a = pop(); + push(pop() / a); + OP("%") + const long a = pop(); + push(pop() % a); + OP(".s") + printf("\x1b[94m<%zu> ", stack_ptr); + for (size_t i = 0; i < stack_ptr; i++) + printf("%ld ", stack[i]); + printf("\x1b[0m\n"); + OP(".") + printf("\x1b[94m%ld\x1b[0m\n", pop()); + } else { + fprintf(stderr, "unrecognized word '%s'\n", s); + if (strict) + exit(EXIT_FAILURE); + } +} + +int main(int argc, char **argv) { + char line[1024] = {0}; + const char *delim = " \t\n\v\r"; + + if (argc > 1 && argv[1][0] == '-' && strchr(argv[1], 's')) + strict = true; + + while (fgets(line, sizeof(line) - 1, stdin)) { + char *tok = strtok(line, delim); + while (tok != NULL) { + exec(tok); + tok = strtok(NULL, delim); + } + } + return 0; +} -- cgit v1.2.3