@@ -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); | ||||