all repos — xyw @ cf8a9e21d67f43af1b211a89a3ee4e40360997ec

A minimal virtual machine and assembler for terminals.

Fixes.
h3rald h3rald@h3rald.com
Tue, 25 Nov 2025 15:58:30 +0100
commit

cf8a9e21d67f43af1b211a89a3ee4e40360997ec

parent

58b58d8a62dff2b23014809f40dbe6ac4acb9a6c

1 files changed, 60 insertions(+), 36 deletions(-)

jump to
M xywasm.cxywasm.c

@@ -2,8 +2,8 @@ #include <stdio.h>

#include "xyw.h" #define TOKEN_MAX_LENGTH 32 -#define DIRECTIVE_MAX_LENGTH 256 -#define COMMENT_MAX_LENGTH 256 +#define DIRECTIVE_CONTENT_MAX_LENGTH 256 +#define COMMENT_CONTENT_MAX_LENGTH 256 #define MODE_X 0x20 #define MODE_Y 0x40

@@ -11,6 +11,7 @@ #define MODE_W 0x80

#define error(msg) fprintf(stderr, "Error - %s [%s]\n", msg, ctx->file) #define token_error(msg) fprintf(stderr, "Error - %s: %s [%s - Ln %d, Col %d]\n", token, msg, ctx->file, ctx->line, ctx->column) +#define symbol_error(symbol, msg) fprintf(stderr, "Error - %s: %s [%s - Ln %d, Col %d]\n", symbol, msg, ctx->file, ctx->line, ctx->column) typedef struct {

@@ -35,6 +36,10 @@ // The token being processed

static char token[TOKEN_MAX_LENGTH]; static unsigned int token_length = 0; +// Directive data +static char directive_data[DIRECTIVE_CONTENT_MAX_LENGTH]; +static unsigned int directive_data_length = 0; + // Bytecode to be written xyw_byte data[0xffff - 0x0100];

@@ -67,12 +72,44 @@ }

str[8] = '\0'; } +static int validate_symbol(xyw_context *ctx, char *str, unsigned int start_index, unsigned int length) +{ + // symbols must start with a letter or underscore, + // and they can contain letters, numbers, underscores, dashes, or dots. + if (!((str[start_index] >= 'A' && str[start_index] <= 'Z') || (str[start_index] >= 'a' && str[start_index] <= 'z') || str[start_index] == '_')) + { + symbol_error(str, "symbol must start with a letter or underscore"); + return -1; + } + for (unsigned int i = start_index + 1; i < length; i++) + { + char c = str[i]; + if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_' || c == '-' || c == '.')) + { + symbol_error(str, "symbol can only contain letters, numbers, underscores, dashes, or dots"); + return -1; + } + } + return 0; +} + +//// Directive handlers + +static int directive_label(xyw_context *ctx) +{ + if (validate_symbol(ctx, directive_data, 1, directive_data_length) != 0) + { + return -1; + } + return 0; +} + //// Parsing functions static int parse_comment(xyw_context *ctx) { char c; - char comment_data[COMMENT_MAX_LENGTH]; + char comment_data[COMMENT_CONTENT_MAX_LENGTH]; unsigned int comment_length = 0; // Process single-line comment while (fread(&c, 1, 1, ctx->fp) == 1)

@@ -84,7 +121,7 @@ ctx->column = 1;

break; } ctx->column++; - if (comment_length < COMMENT_MAX_LENGTH - 1) + if (comment_length < COMMENT_CONTENT_MAX_LENGTH - 1) { comment_data[comment_length++] = c; comment_data[comment_length] = '\0';

@@ -243,30 +280,9 @@ }

return -1; } -static int validate_identifier(xyw_context *ctx, unsigned int start_index) -{ - // Identifiers must start with a letter or underscore, - // and they can contain letters, numbers, underscores, dashes, or dots. - if (!((token[start_index] >= 'A' && token[start_index] <= 'Z') || (token[start_index] >= 'a' && token[start_index] <= 'z') || token[start_index] == '_')) - { - token_error("Invalid start character for identifier"); - return -1; - } - for (unsigned int i = start_index + 1; i < token_length; i++) - { - char c = token[i]; - if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_' || c == '-' || c == '.')) - { - token_error("Invalid contains invalid characters"); - return -1; - } - } - return 0; -} - static int parse_symbol(xyw_context *ctx) { - if (validate_identifier(ctx, 0) != 0) + if (validate_symbol(ctx, token, 0, token_length) != 0) { return -1; }

@@ -278,27 +294,23 @@ }

static int parse_directive(xyw_context *ctx) { - if (validate_identifier(ctx, 1) != 0) + if (validate_symbol(ctx, token, 1, token_length) != 0) { return -1; } // Parse labels starting with . until end of line char c; - char directive_data[DIRECTIVE_MAX_LENGTH]; - unsigned int directive_length = 0; while (fread(&c, 1, 1, ctx->fp) == 1) { + ctx->column++; if (c == '\n') { - ctx->line++; - ctx->column = 1; break; } - ctx->column++; - if (directive_length < DIRECTIVE_MAX_LENGTH - 1) + if (directive_data_length < DIRECTIVE_CONTENT_MAX_LENGTH - 1) { - directive_data[directive_length++] = c; - directive_data[directive_length] = '\0'; + directive_data[directive_data_length++] = c; + directive_data[directive_data_length] = '\0'; } else {

@@ -309,7 +321,18 @@ }

// TODO: Remove printf("Directive:\t%s\t(%s)\n", token, directive_data); // TODO: Process directive - return 0; + int result = 0; + if (strcmpn(token, ".label", 6) == 0) + { + result = directive_label(ctx); + } + // Advance to next line + ctx->line++; + ctx->column = 1; + // Reset directive data + directive_data_length = 0; + directive_data[0] = '\0'; + return result; } static int parse_token(xyw_context *ctx)

@@ -346,6 +369,7 @@ token_error("Unrecognized token");

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