| @@ -42,6 +42,7 @@ static const char *error_descs[] = { | |||||
| [ED_SYM_DUPE_LABELS] = "duplicate definitions for label", | [ED_SYM_DUPE_LABELS] = "duplicate definitions for label", | ||||
| [ED_SYM_NO_LABEL] = "undefined reference to 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_REGISTER] = "labels cannot share names with registers", | ||||
| [ED_SYM_IS_CONDITION] = "labels cannot share names with condition codes", | [ED_SYM_IS_CONDITION] = "labels cannot share names with condition codes", | ||||
| @@ -41,6 +41,7 @@ typedef enum { | |||||
| ED_SYM_DUPE_LABELS, | ED_SYM_DUPE_LABELS, | ||||
| ED_SYM_NO_LABEL, | ED_SYM_NO_LABEL, | ||||
| ED_SYM_TOO_LONG, | |||||
| ED_SYM_IS_REGISTER, | ED_SYM_IS_REGISTER, | ||||
| ED_SYM_IS_CONDITION, | ED_SYM_IS_CONDITION, | ||||
| @@ -5,6 +5,8 @@ | |||||
| #include <stdint.h> | #include <stdint.h> | ||||
| #include "state.h" | |||||
| typedef enum { | typedef enum { | ||||
| AT_REGISTER, | AT_REGISTER, | ||||
| AT_IMMEDIATE, | AT_IMMEDIATE, | ||||
| @@ -50,7 +52,9 @@ typedef struct { | |||||
| int8_t offset; | int8_t offset; | ||||
| } ASMArgIndexed; | } ASMArgIndexed; | ||||
| typedef char* ASMArgLabel; | |||||
| typedef struct { | |||||
| char text[MAX_SYMBOL_SIZE]; | |||||
| } ASMArgLabel; | |||||
| typedef enum { | typedef enum { | ||||
| COND_NZ, COND_N, COND_NC, COND_C, COND_PO, COND_PE, COND_P, COND_M | COND_NZ, COND_N, COND_NC, COND_C, COND_PO, COND_PE, COND_P, COND_M | ||||
| @@ -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. | 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)) { \ | if (argparse_##func(&arg->data.field, str, size)) { \ | ||||
| arg->type = argtype; \ | arg->type = argtype; \ | ||||
| return ED_NONE; \ | return ED_NONE; \ | ||||
| } | } | ||||
| DEBUG("parse_arg(): -->%.*s<-- %zu", (int) size, str, size) | 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; | 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) | ASMInstArg args[3], size_t *nargs, const char *str, size_t size) | ||||
| { | { | ||||
| ASMErrorDesc err; | ASMErrorDesc err; | ||||
| static char *symbol = NULL; | |||||
| size_t start = 0, i = 0; | size_t start = 0, i = 0; | ||||
| while (i < size) { | while (i < size) { | ||||
| @@ -184,7 +179,7 @@ static ASMErrorDesc parse_args( | |||||
| if (c == ',') { | if (c == ',') { | ||||
| if (i == start) | if (i == start) | ||||
| return ED_PS_ARG_SYNTAX; | 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; | return err; | ||||
| (*nargs)++; | (*nargs)++; | ||||
| @@ -207,7 +202,7 @@ static ASMErrorDesc parse_args( | |||||
| } | } | ||||
| if (i > start) { | 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; | return err; | ||||
| (*nargs)++; | (*nargs)++; | ||||
| } | } | ||||
| @@ -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. | Read in a boolean argument from the given line and store it in *result. | ||||
| */ | */ | ||||
| DIRECTIVE_PARSE_FUNC(bool, bool) | DIRECTIVE_PARSE_FUNC(bool, bool) | ||||
| @@ -25,6 +25,7 @@ bool argparse_condition(ASMArgCondition*, const char*, ssize_t); | |||||
| bool argparse_immediate(ASMArgImmediate*, const char*, ssize_t); | bool argparse_immediate(ASMArgImmediate*, const char*, ssize_t); | ||||
| bool argparse_indirect(ASMArgIndirect*, const char*, ssize_t); | bool argparse_indirect(ASMArgIndirect*, const char*, ssize_t); | ||||
| bool argparse_indexed(ASMArgIndexed*, const char*, ssize_t); | bool argparse_indexed(ASMArgIndexed*, const char*, ssize_t); | ||||
| bool argparse_label(ASMArgLabel*, const char*, ssize_t); | |||||
| /* Preprocessor directive parsers */ | /* Preprocessor directive parsers */ | ||||
| bool dparse_bool(bool*, const ASMLine*, const char*); | bool dparse_bool(bool*, const ASMLine*, const char*); | ||||
| @@ -13,6 +13,7 @@ | |||||
| #define DEFAULT_REGION 6 // GG Export | #define DEFAULT_REGION 6 // GG Export | ||||
| #define DEFAULT_DECLSIZE 0xC // 32 KB | #define DEFAULT_DECLSIZE 0xC // 32 KB | ||||
| #define MAX_SYMBOL_SIZE 256 | |||||
| #define SYMBOL_TABLE_BUCKETS 128 | #define SYMBOL_TABLE_BUCKETS 128 | ||||
| /* Structs */ | /* Structs */ | ||||
| @@ -62,6 +62,9 @@ static inline int8_t default_bank_slot(uint8_t bank) | |||||
| static ErrorInfo* add_label_to_table( | static ErrorInfo* add_label_to_table( | ||||
| ASMSymbolTable *symtable, const ASMLine *line, size_t offset, int8_t slot) | 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; | ASMArgRegister reg; | ||||
| if (argparse_register(®, line->data, line->length - 1)) | if (argparse_register(®, line->data, line->length - 1)) | ||||
| return error_info_create(line, ET_SYMBOL, ED_SYM_IS_REGISTER); | return error_info_create(line, ET_SYMBOL, ED_SYM_IS_REGISTER); | ||||