Added symbol management and dictionary functions for macros and labels
h3rald h3rald@h3rald.com
Thu, 27 Nov 2025 16:16:27 +0100
1 files changed,
139 insertions(+),
17 deletions(-)
jump to
M
xywasm.c
→
xywasm.c
@@ -3,8 +3,9 @@ #include "xyw.h"
#define TOKEN_MAX_LENGTH 32 #define DIRECTIVE_CONTENT_MAX_LENGTH 256 -#define COMMENT_CONTENT_MAX_LENGTH 256 #define STRING_MAX_LENGTH 256 +#define MAX_SYMBOLS 0x500 +#define MAX_REFS 0x1000 #define MODE_X 0x20 #define MODE_Y 0x40@@ -23,6 +24,21 @@ int column;
char *file; FILE *fp; } xyw_context; + +typedef enum +{ + SYMBOL_TYPE_LABEL, + SYMBOL_TYPE_MACRO, + SYMBOL_TYPE_REF +} xyw_symbol_type; + +typedef struct +{ + char *name; + xyw_symbol_type type; + xyw_short address; + char *contents; +} xyw_symbol; typedef enum {@@ -71,8 +87,90 @@
// Current write pointer xyw_short ptr = 0x0000; +// Dictionary for symbols (macros and labels) +// Actually following Uxn design here ;) +char dict[0x8000]; +char *dictnext = dict; + +// List of symbols (macros and labels) +xyw_symbol symbols[MAX_SYMBOLS]; +xyw_short symcount = 0; + +// List of references to symbols +xyw_symbol refs[MAX_REFS]; +xyw_short refcount = 0; + +//// Dictionary management + +// Stores a new string in the dictionary and returns its address +static char *dict_store(char *str) +{ + char *o = dictnext; + while (*str) + { + *dictnext++ = *str++; + } + return o; +} + +// Checks if str is already in the dictionary +// if so, returns its address, else it stores it and returns the new address +static char *dict_add(char *str) +{ + char *dict_cursor = dict; + + while (dict_cursor < dictnext) + { + char *existing_str = dict_cursor; + char *input_cursor = str; + char *existing_cursor = existing_str; + + // Compare the two strings character by character + while (*existing_cursor && *input_cursor && (*existing_cursor == *input_cursor)) + { + existing_cursor++; + input_cursor++; + } + + // If both ended at the same time, we found an exact match + if (*existing_cursor == '\0' && *input_cursor == '\0') + { + return existing_str; + } + + // Move dict_cursor to the start of the next string in the dictionary + while (*existing_cursor != '\0') + { + existing_cursor++; + } + dict_cursor = existing_cursor + 1; // skip the null terminator + } + + // Not found, store the new string and return its address + return dict_store(str); +} + //// Utilities static xyw_token_terminator next_token(xyw_context *ctx); + +static int find_symbol(char *name) +{ + for (xyw_short i = 0; i < symcount; i++) + { + for (unsigned int j = 0; j < TOKEN_MAX_LENGTH; j++) + { + if (symbols[i].name[j] != name[j]) + { + break; + } + if (name[j] == '\0') + { + return i; + } + } + } + return -1; +} static int strcmpn(const char *s1, const char *s2, unsigned int n) {@@ -151,13 +249,49 @@ (val > 0xff) ? write(PSH | MODE_W) : write(PSH);
write(val); } +static int macro(xyw_context *ctx, char *name, char *contents) +{ + if (symcount >= MAX_SYMBOLS) + { + error("Too many symbols defined"); + return -1; + } + if (find_symbol(name) != -1) + { + symbol_error(name, "Symbol already defined"); + return -1; + } + xyw_symbol *sym = &symbols[symcount++]; + sym->type = SYMBOL_TYPE_MACRO; + sym->name = dict_add(name); + sym->contents = dict_store(contents); + return 0; +} + +static int label(xyw_context *ctx, char *name) +{ + if (symcount >= MAX_SYMBOLS) + { + error("Too many symbols defined"); + return -1; + } + if (find_symbol(name) != -1) + { + symbol_error(name, "Symbol already defined"); + return -1; + } + xyw_symbol *sym = &symbols[symcount++]; + sym->type = SYMBOL_TYPE_LABEL; + sym->name = dict_add(name); + sym->address = ptr; + return 0; +} + //// Processing functions static int process_comment(xyw_context *ctx) { char c; - char comment_data[COMMENT_CONTENT_MAX_LENGTH]; - unsigned int comment_length = 0; // Process single-line comment while (fread(&c, 1, 1, ctx->fp) == 1) {@@ -168,19 +302,7 @@ ctx->column = 0;
break; } ctx->column++; - if (comment_length < COMMENT_CONTENT_MAX_LENGTH - 1) - { - comment_data[comment_length++] = c; - comment_data[comment_length] = '\0'; - } - else - { - token_error("Comment too long"); - return -1; - } } - // TODO: Remove - printf("Comment:\t%s%s\n", token, comment_data); token_type = TOKEN_TYPE_COMMENT; return 0; }@@ -407,7 +529,7 @@ {
return -1; } printf("Directive:\t.label %s\n", token); - // TODO: process label + label(ctx, token); return validate_single_directive_argument(ctx, r); }@@ -505,7 +627,7 @@ contents[length] = '\0';
} // TODO: remove printf("Macro contents:\t%s\n", contents); - // TODO: process macro + macro(ctx, token, contents); return 0; }