diff --git a/src/assembler/errors.c b/src/assembler/errors.c index a32b812..5bc412f 100644 --- a/src/assembler/errors.c +++ b/src/assembler/errors.c @@ -42,6 +42,7 @@ static const char *error_descs[] = { [ED_SYM_DUPE_LABELS] = "duplicate definitions for label", [ED_SYM_NO_LABEL] = "undefined reference to label", + [ED_SYM_TOO_LONG] = "label name is too long", [ED_SYM_IS_REGISTER] = "labels cannot share names with registers", [ED_SYM_IS_CONDITION] = "labels cannot share names with condition codes", diff --git a/src/assembler/errors.h b/src/assembler/errors.h index 8ce34e4..6f5b8f3 100644 --- a/src/assembler/errors.h +++ b/src/assembler/errors.h @@ -41,6 +41,7 @@ typedef enum { ED_SYM_DUPE_LABELS, ED_SYM_NO_LABEL, + ED_SYM_TOO_LONG, ED_SYM_IS_REGISTER, ED_SYM_IS_CONDITION, diff --git a/src/assembler/inst_args.h b/src/assembler/inst_args.h index e87fbcb..be6c5d4 100644 --- a/src/assembler/inst_args.h +++ b/src/assembler/inst_args.h @@ -5,6 +5,8 @@ #include +#include "state.h" + typedef enum { AT_REGISTER, AT_IMMEDIATE, @@ -50,7 +52,9 @@ typedef struct { int8_t offset; } ASMArgIndexed; -typedef char* ASMArgLabel; +typedef struct { + char text[MAX_SYMBOL_SIZE]; +} ASMArgLabel; typedef enum { COND_NZ, COND_N, COND_NC, COND_C, COND_PO, COND_PE, COND_P, COND_M diff --git a/src/assembler/instructions.c b/src/assembler/instructions.c index 714e890..eec793c 100644 --- a/src/assembler/instructions.c +++ b/src/assembler/instructions.c @@ -143,28 +143,24 @@ static uint8_t fill_bytes_variadic(uint8_t *bytes, size_t len, ...) Return ED_NONE (0) on success or an error code on failure. */ -static ASMErrorDesc parse_arg( - ASMInstArg *arg, const char *str, size_t size, char **symbol) +static ASMErrorDesc parse_arg(ASMInstArg *arg, const char *str, size_t size) { -#define USE_PARSER(func, argtype, field) \ +#define TRY_PARSER(func, argtype, field) \ if (argparse_##func(&arg->data.field, str, size)) { \ arg->type = argtype; \ return ED_NONE; \ } DEBUG("parse_arg(): -->%.*s<-- %zu", (int) size, str, size) - USE_PARSER(register, AT_REGISTER, reg) - USE_PARSER(immediate, AT_IMMEDIATE, imm) - USE_PARSER(indirect, AT_INDIRECT, indirect) - USE_PARSER(indexed, AT_INDEXED, index) - USE_PARSER(condition, AT_CONDITION, cond) - - // AT_LABEL - // ASMArgLabel label; - + TRY_PARSER(register, AT_REGISTER, reg) + TRY_PARSER(immediate, AT_IMMEDIATE, imm) + TRY_PARSER(indirect, AT_INDIRECT, indirect) + TRY_PARSER(indexed, AT_INDEXED, index) + TRY_PARSER(condition, AT_CONDITION, cond) + TRY_PARSER(label, AT_LABEL, label) return ED_PS_ARG_SYNTAX; -#undef USE_PARSER +#undef TRY_PARSER } /* @@ -176,7 +172,6 @@ static ASMErrorDesc parse_args( ASMInstArg args[3], size_t *nargs, const char *str, size_t size) { ASMErrorDesc err; - static char *symbol = NULL; size_t start = 0, i = 0; while (i < size) { @@ -184,7 +179,7 @@ static ASMErrorDesc parse_args( if (c == ',') { if (i == start) return ED_PS_ARG_SYNTAX; - if ((err = parse_arg(&args[*nargs], str + start, i - start, &symbol))) + if ((err = parse_arg(&args[*nargs], str + start, i - start))) return err; (*nargs)++; @@ -207,7 +202,7 @@ static ASMErrorDesc parse_args( } if (i > start) { - if ((err = parse_arg(&args[*nargs], str + start, i - start, &symbol))) + if ((err = parse_arg(&args[*nargs], str + start, i - start))) return err; (*nargs)++; } diff --git a/src/assembler/parse_util.c b/src/assembler/parse_util.c index d69f792..a651244 100644 --- a/src/assembler/parse_util.c +++ b/src/assembler/parse_util.c @@ -412,6 +412,26 @@ bool argparse_indexed(ASMArgIndexed *result, const char *arg, ssize_t size) } /* + Read in a label argument and store it in *result. +*/ +bool argparse_label(ASMArgLabel *result, const char *arg, ssize_t size) +{ + if (size >= MAX_SYMBOL_SIZE) + return false; + + for (const char *i = arg; i < arg + size; i++) { + char c = *i; + if (!((c >= 'a' && c <= 'z') || (i != arg && c >= '0' && c <= '9') || + c == '_' || c == '.')) + return false; + } + + strncpy(result->text, arg, size); + result->text[size] = '\0'; + return true; +} + +/* Read in a boolean argument from the given line and store it in *result. */ DIRECTIVE_PARSE_FUNC(bool, bool) diff --git a/src/assembler/parse_util.h b/src/assembler/parse_util.h index 85bdf86..1c81927 100644 --- a/src/assembler/parse_util.h +++ b/src/assembler/parse_util.h @@ -25,6 +25,7 @@ bool argparse_condition(ASMArgCondition*, const char*, ssize_t); bool argparse_immediate(ASMArgImmediate*, const char*, ssize_t); bool argparse_indirect(ASMArgIndirect*, const char*, ssize_t); bool argparse_indexed(ASMArgIndexed*, const char*, ssize_t); +bool argparse_label(ASMArgLabel*, const char*, ssize_t); /* Preprocessor directive parsers */ bool dparse_bool(bool*, const ASMLine*, const char*); diff --git a/src/assembler/state.h b/src/assembler/state.h index c2f6f40..9746662 100644 --- a/src/assembler/state.h +++ b/src/assembler/state.h @@ -13,6 +13,7 @@ #define DEFAULT_REGION 6 // GG Export #define DEFAULT_DECLSIZE 0xC // 32 KB +#define MAX_SYMBOL_SIZE 256 #define SYMBOL_TABLE_BUCKETS 128 /* Structs */ diff --git a/src/assembler/tokenizer.c b/src/assembler/tokenizer.c index 9e51f3e..27ccb27 100644 --- a/src/assembler/tokenizer.c +++ b/src/assembler/tokenizer.c @@ -62,6 +62,9 @@ static inline int8_t default_bank_slot(uint8_t bank) static ErrorInfo* add_label_to_table( ASMSymbolTable *symtable, const ASMLine *line, size_t offset, int8_t slot) { + if (line->length - 1 >= MAX_SYMBOL_SIZE) + return error_info_create(line, ET_SYMBOL, ED_SYM_TOO_LONG); + ASMArgRegister reg; if (argparse_register(®, line->data, line->length - 1)) return error_info_create(line, ET_SYMBOL, ED_SYM_IS_REGISTER);