all repos — xyw @ e7b0091e1182cf65bf6a36916938471e5f0d81c6

A minimal virtual machine and assembler for terminals.

Implemented macro expansion.
h3rald h3rald@h3rald.com
Fri, 28 Nov 2025 11:14:00 +0100
commit

e7b0091e1182cf65bf6a36916938471e5f0d81c6

parent

f83a7dbb763d4fb93754290349ed0ee3954daf65

1 files changed, 91 insertions(+), 10 deletions(-)

jump to
M xywasm.cxywasm.c

@@ -19,10 +19,16 @@ #define PSH 0x01

typedef struct { + enum + { + SRC_FILE, + SRC_STRING + } src; int line; int column; char *file; FILE *fp; + const char *sp; } xyw_context; typedef enum

@@ -108,6 +114,7 @@ while (*str)

{ *dictnext++ = *str++; } + *dictnext++ = '\0'; return o; }

@@ -148,8 +155,11 @@ // Not found, store the new string and return its address

return dict_store(str); } +//// Forward declarations +static xyw_token_terminator next_token(xyw_context *ctx); +static int assemble_string(xyw_context *ctx, const char *text); + //// Utilities -static xyw_token_terminator next_token(xyw_context *ctx); static int find_symbol(char *name) {

@@ -309,8 +319,23 @@ static int process_comment(xyw_context *ctx)

{ char c; // Process single-line comment - while (fread(&c, 1, 1, ctx->fp) == 1) + while (1) { + if (ctx->src == SRC_FILE) + { + if (fread(&c, 1, 1, ctx->fp) != 1) + { + break; + } + } + else + { + if (!ctx->sp || *ctx->sp == '\0') + { + break; + } + c = *ctx->sp++; + } // Ignore all characters until end of line if (c == '\n') {

@@ -531,7 +556,10 @@ {

xyw_symbol *sym = &symbols[i]; if (sym->type == SYMBOL_TYPE_MACRO) { - // TODO: Expand macro + printf("-> Macro:\t%s\n", sym->contents); + assemble_string(ctx, sym->contents); + ctx->src = SRC_FILE; + ctx->sp = NULL; } else if (sym->type == SYMBOL_TYPE_LABEL) {

@@ -548,7 +576,7 @@ }

else { // Store reference to be resolved later - printf("-> Ref:\t%s\n", token); + printf("-> Reference:\t%s\n", token); if (ref(ctx, token) != 0) { return -1;

@@ -668,8 +696,23 @@ printf("Directive:\t.macro %s\n", token);

char c; char contents[DIRECTIVE_CONTENT_MAX_LENGTH]; int length = 0; - while (fread(&c, 1, 1, ctx->fp)) + while (1) { + if (ctx->src == SRC_FILE) + { + if (fread(&c, 1, 1, ctx->fp) != 1) + { + break; + } + } + else + { + if (!ctx->sp || *ctx->sp == '\0') + { + break; + } + c = *ctx->sp++; + } if (c == '\n') { ctx->line++;

@@ -690,8 +733,6 @@ ctx->column++;

contents[length++] = c; contents[length] = '\0'; } - // TODO: remove - printf("Macro contents:\t%s\n", contents); macro(ctx, token, contents); return 0; }

@@ -788,8 +829,24 @@ char c;

int in_string = 0; token_length = 0; token[0] = '\0'; - while (fread(&c, 1, 1, ctx->fp) == 1) + while (1) { + // Read next character from active source + if (ctx->src == SRC_FILE) + { + if (fread(&c, 1, 1, ctx->fp) != 1) + { + break; + } + } + else + { + if (!ctx->sp || *ctx->sp == '\0') + { + break; + } + c = *ctx->sp++; + } if (c == '\n') { if (in_string)

@@ -862,7 +919,7 @@ return TOKEN_END_EOF;

} // Read a file and process its tokens -static int process_file(xyw_context *ctx) +static int assemble_file(xyw_context *ctx) { ctx->fp = fopen(ctx->file, "r"); if (!ctx->fp)

@@ -870,6 +927,9 @@ {

error("Could not open file"); return -1; } + // Set source mode to file + ctx->src = SRC_FILE; + ctx->sp = NULL; int r; while (1) {

@@ -887,6 +947,27 @@ fclose(ctx->fp);

return r; } +// Process tokens from an in-memory string buffer (mainly for macro body) +static int assemble_string(xyw_context *ctx, const char *text) +{ + ctx->src = SRC_STRING; + ctx->sp = text; + int r; + while (1) + { + r = next_token(ctx); + if (r == TOKEN_END_EOF || r == TOKEN_END_INVALID) + { + break; + } + if (process_token(ctx) != 0) + { + break; + } + } + return r; +} + ///// Public API int xyw_assemble(const char *input, const char *output)

@@ -895,7 +976,7 @@ xyw_context ctx;

ctx.file = (char *)input; ctx.line = 1; ctx.column = 1; - if (process_file(&ctx) != 0) + if (assemble_file(&ctx) != 0) { return -1; }