Implementing directives, refactoring.
h3rald h3rald@h3rald.com
Thu, 27 Nov 2025 13:52:54 +0100
1 files changed,
203 insertions(+),
104 deletions(-)
jump to
M
xywasm.c
→
xywasm.c
@@ -35,6 +35,16 @@ TOKEN_TYPE_STRING,
TOKEN_TYPE_SYMBOL } xyw_token_type; +typedef enum +{ + TOKEN_END_EOF = 0, + TOKEN_END_EOS, + TOKEN_END_EOL, + TOKEN_END_SPACE, + TOKEN_END_COMMENT, + TOKEN_END_INVALID +} xyw_token_terminator; + // Instruction mnemonics static char instructions[][4] = { "BRK", "PSH", "POP", "NOT",@@ -50,6 +60,7 @@ // The token being processed
static char token[TOKEN_MAX_LENGTH]; static unsigned int token_length = 0; static xyw_token_type token_type = TOKEN_TYPE_UNKNOWN; +static xyw_short token_value = 0; // Directive identifier static char directive[TOKEN_MAX_LENGTH];@@ -66,6 +77,7 @@ // Current write pointer
xyw_short ptr = 0x0100; //// Utilities +static xyw_token_terminator next_token(xyw_context *ctx); static int strcmpn(const char *s1, const char *s2, unsigned int n) {@@ -118,6 +130,21 @@ directive_data_length = 0;
directive_data[0] = '\0'; } +static int validate_single_directive_argument(xyw_context *ctx, xyw_token_terminator r) +{ + while (r != TOKEN_END_EOL && r != TOKEN_END_EOF && r != TOKEN_END_COMMENT) + { + r = next_token(ctx); + if (r == TOKEN_END_EOL || r == TOKEN_END_EOF || r == TOKEN_END_COMMENT) + { + break; + } + token_error("Too many tokens after directive"); + return -1; + } + return 0; +} + // Write raw bytecode data static inline void write(xyw_short val) {@@ -201,6 +228,7 @@ }
// TODO: Remove printf("Hex number:\t%s\t(%04X) [directive: %s]\n", token, value, directive_length > 0 ? directive : "N/A"); token_type = TOKEN_TYPE_NUMBER; + token_value = value; return 0; }@@ -229,6 +257,7 @@ }
// TODO: Remove printf("Binary number:\t%s\t(%04X) [directive: %s]\n", token, value, directive_length > 0 ? directive : "N/A"); token_type = TOKEN_TYPE_NUMBER; + token_value = value; return 0; }@@ -263,9 +292,26 @@ }
// TODO: Remove printf("Decimal number:\t%s\t(%04X) [directive: %s]\n", token, value, directive_length > 0 ? directive : "N/A"); token_type = TOKEN_TYPE_NUMBER; + token_value = value; return 0; } +static int process_number(xyw_context *ctx) +{ + if (token[0] == '$') + { + return process_hex_number(ctx); + } + else if (token[0] == '%') + { + return process_binary_number(ctx); + } + else + { + return process_decimal_number(ctx); + } +} + static int process_instruction(xyw_context *ctx) { (void)ctx;@@ -310,6 +356,7 @@ byte_to_binary(opcode, bits);
printf("Instruction:\t%s\t(%02X - %s) [directive: %s]\n", token, opcode, bits, directive_length > 0 ? directive : "N/A"); write(opcode); token_type = TOKEN_TYPE_INSTRUCTION; + token_value = opcode; return 0; } }@@ -339,18 +386,92 @@ token_type = TOKEN_TYPE_SYMBOL;
return 0; } -// Returns: 1 token processed, 0 EOF, -1 error -static int next_token(xyw_context *ctx); +static int process_directive_org(xyw_context *ctx) +{ + xyw_token_terminator r = next_token(ctx); + if (process_number(ctx) != 0) + { + return -1; + } + printf("Directive:\t.org %s\n", token); + // TODO: process org + return validate_single_directive_argument(ctx, r); +} static int process_directive_label(xyw_context *ctx) { - int r = next_token(ctx); - if (r != 1 || token_type != TOKEN_TYPE_SYMBOL) + xyw_token_terminator r = next_token(ctx); + if (process_symbol(ctx) != 0) { - token_error("Expected symbol after .label directive"); return -1; } - // TODO: store label info + printf("Directive:\t.label %s\n", token); + // TODO: process label + return validate_single_directive_argument(ctx, r); +} + +static int process_directive_include(xyw_context *ctx) +{ + xyw_token_terminator r = next_token(ctx); + if (r != TOKEN_END_EOS) + { + token_error("Expected string after .include directive"); + return -1; + } + process_string(ctx); + printf("Directive:\t.include %s\n", token); + // TODO: process include + return validate_single_directive_argument(ctx, r); +} + +static int process_directive_string(xyw_context *ctx) +{ + xyw_token_terminator r = next_token(ctx); + if (r != TOKEN_END_EOS) + { + token_error("Expected string after .string directive"); + return -1; + } + process_string(ctx); + printf("Directive:\t.string %s\n", token); + // TODO: process string + return validate_single_directive_argument(ctx, r); +} + +static int process_directive_byte(xyw_context *ctx) +{ + xyw_token_terminator r; + printf("Directive:\t.byte\n"); + while (1) + { + r = next_token(ctx); + if (process_number(ctx) != 0) + { + return -1; + } + if (r == TOKEN_END_EOL || r == TOKEN_END_EOF || r == TOKEN_END_COMMENT) + { + break; + } + write((xyw_byte)token_value); + } + return 0; +} + +static int process_directive_macro(xyw_context *ctx) +{ + xyw_token_terminator r; + printf("Directive:\t.macro\n"); + while (1) + { + r = next_token(ctx); + // TODO: Store macro contents + if (r == TOKEN_END_EOL || r == TOKEN_END_EOF || r == TOKEN_END_COMMENT) + { + break; + } + write((xyw_byte)token_value); + } return 0; }@@ -366,20 +487,48 @@ {
directive[i] = token[i]; } directive[directive_length] = '\0'; - // TODO: Remove - printf("Directive:\t%s\n", token); token_type = TOKEN_TYPE_DIRECTIVE; // TODO: Process directive if (strcmpn(directive, ".label", 6) == 0) { return process_directive_label(ctx); } + else if (strcmpn(directive, ".include", 8) == 0) + { + return process_directive_include(ctx); + } + else if (strcmpn(directive, ".string", 7) == 0) + { + return process_directive_string(ctx); + } + else if (strcmpn(directive, ".org", 4) == 0) + { + return process_directive_org(ctx); + } + else if (strcmpn(directive, ".byte", 5) == 0) + { + return process_directive_byte(ctx); + } + else if (strcmpn(directive, ".macro", 6) == 0) + { + return process_directive_macro(ctx); + } + else + { + token_error("Unknown directive"); + return -1; + } + reset_directive(); return 0; } // Process and validate tokens static int process_token(xyw_context *ctx) { + if (token_length == 0) + { + return 0; + } if (token[0] == ';') { return process_comment(ctx);@@ -416,7 +565,7 @@ token_error("Unrecognized token");
return -1; } -static int next_token(xyw_context *ctx) +static xyw_token_terminator next_token(xyw_context *ctx) { unsigned char c; token_length = 0;@@ -427,139 +576,82 @@ while (fread(&c, 1, 1, ctx->fp) == 1)
{ if (!in_string && c == '\n') { - if (token_length > 0) - { - if (process_token(ctx) != 0) - return -1; - token_length = 0; - token[0] = '\0'; - ctx->line++; - ctx->column = 1; - reset_directive(); - return 1; - } ctx->line++; ctx->column = 1; - reset_directive(); - continue; + return TOKEN_END_EOL; } - if (!in_string && token_length == 0 && c == ';') + else if (!in_string && token_length == 0 && c == ';') { token[token_length++] = (char)c; token[token_length] = '\0'; ctx->column++; - if (process_token(ctx) != 0) - return -1; - token_length = 0; - token[0] = '\0'; - return 1; + return TOKEN_END_COMMENT; } - if (c == '"') + else if (c == '"') { ctx->column++; - if (!in_string) + if (token_length > STRING_MAX_LENGTH) { - in_string = 1; - if (token_length < STRING_MAX_LENGTH - 1) - { - token[token_length++] = (char)c; - token[token_length] = '\0'; - } - else - { - token_error("Token too long"); - return -1; - } - continue; + token_error("Token too long"); + return TOKEN_END_INVALID; } - else + token[token_length++] = (char)c; + token[token_length] = '\0'; + if (in_string) { - if (token_length < STRING_MAX_LENGTH - 1) - { - token[token_length++] = (char)c; - token[token_length] = '\0'; - } - else - { - token_error("Token too long"); - return -1; - } - if (process_token(ctx) != 0) - return -1; - token_length = 0; - token[0] = '\0'; - in_string = 0; - return 1; + return TOKEN_END_EOS; } + in_string = 1; } else if (in_string) { ctx->column++; - if (token_length < STRING_MAX_LENGTH - 1) - { - token[token_length++] = (char)c; - token[token_length] = '\0'; - } - else + if (token_length > STRING_MAX_LENGTH) { token_error("Token too long"); - return -1; + return TOKEN_END_INVALID; } - continue; + token[token_length++] = (char)c; + token[token_length] = '\0'; } + // Whitespace characters else if (c == ' ' || c == '\t') { + ctx->column++; if (token_length > 0) { - if (process_token(ctx) != 0) - return -1; - token_length = 0; - token[0] = '\0'; - ctx->column++; - return 1; + return TOKEN_END_SPACE; } - ctx->column++; - continue; } + // Non-whitespace, non-control characters else if (c > 0x20 && c != 0x7f) { ctx->column++; - if (token_length < TOKEN_MAX_LENGTH - 1) + if (token_length > TOKEN_MAX_LENGTH) { - token[token_length++] = (char)c; - token[token_length] = '\0'; - if (directive_length > 0) - { - if (directive_data_length >= DIRECTIVE_CONTENT_MAX_LENGTH - 1) - { - token_error("Directive data too long"); - return -1; - } - directive_data[directive_data_length++] = (char)c; - directive_data[directive_data_length] = '\0'; - } + token_error("Token too long"); + return TOKEN_END_INVALID; } - else + token[token_length++] = (char)c; + token[token_length] = '\0'; + if (directive_length > 0) { - token_error("Token too long"); - return -1; + if (directive_data_length >= DIRECTIVE_CONTENT_MAX_LENGTH - 1) + { + token_error("Directive data too long"); + return TOKEN_END_INVALID; + } + directive_data[directive_data_length++] = (char)c; + directive_data[directive_data_length] = '\0'; } } else { token_error("Invalid character encountered"); - return -1; + return TOKEN_END_INVALID; } } - if (token_length > 0) - { - if (process_token(ctx) != 0) - return -1; - token_length = 0; - token[0] = '\0'; - return 1; // last token at EOF - } - return 0; // EOF no token + return TOKEN_END_EOF; // EOF no token } // Read a file and process its tokens@@ -571,11 +663,18 @@ {
error("Could not open file"); return -1; } - int r; - while ((r = next_token(ctx)) == 1) + while (1) { - // tokens processed inline + r = next_token(ctx); + if (r == TOKEN_END_EOF || r == TOKEN_END_INVALID) + { + break; + } + if (process_token(ctx) != 0) + { + break; + } } fclose(ctx->fp); return r;