From fdd8bb9e8a1000a952999c33ad5ad73dfb7d20a7 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Wed, 6 May 2015 00:42:14 -0500 Subject: [PATCH] Pass argparse args as a struct to make keeping track of deftabs easier. --- src/assembler/instructions.c | 27 ++++++----- src/assembler/instructions.h | 3 +- src/assembler/parse_util.c | 108 ++++++++++++++++++++++--------------------- src/assembler/parse_util.h | 20 +++++--- src/assembler/state.c | 10 ++++ src/assembler/state.h | 1 + src/assembler/tokenizer.c | 9 ++-- 7 files changed, 103 insertions(+), 75 deletions(-) diff --git a/src/assembler/instructions.c b/src/assembler/instructions.c index eec793c..f009df5 100644 --- a/src/assembler/instructions.c +++ b/src/assembler/instructions.c @@ -49,21 +49,20 @@ #define INST_FUNC(mnemonic) \ static ASMErrorDesc parse_inst_##mnemonic( \ - uint8_t **bytes, size_t *length, char **symbol, const char *arg, size_t size) + uint8_t **bytes, size_t *length, char **symbol, ASMArgParseInfo ap_info) \ #define INST_ERROR(desc) return ED_PS_##desc; #define INST_TAKES_NO_ARGS \ - if (arg) \ + if (ap_info.arg) \ INST_ERROR(TOO_MANY_ARGS) \ - (void) size; #define INST_TAKES_ARGS(lo, hi) \ - if (!arg) \ + if (!ap_info.arg) \ INST_ERROR(TOO_FEW_ARGS) \ ASMInstArg args[3]; \ size_t nargs = 0; \ - ASMErrorDesc err = parse_args(args, &nargs, arg, size); \ + ASMErrorDesc err = parse_args(args, &nargs, ap_info); \ if (err) \ return err; \ if (nargs < lo) \ @@ -143,14 +142,16 @@ 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) +static ASMErrorDesc parse_arg( + ASMInstArg *arg, const char *str, size_t size, ASMDefineTable *deftable) { #define TRY_PARSER(func, argtype, field) \ - if (argparse_##func(&arg->data.field, str, size)) { \ + if (argparse_##func(&arg->data.field, info)) { \ arg->type = argtype; \ return ED_NONE; \ } + ASMArgParseInfo info = {.arg = str, .size = size, .deftable = deftable}; DEBUG("parse_arg(): -->%.*s<-- %zu", (int) size, str, size) TRY_PARSER(register, AT_REGISTER, reg) TRY_PARSER(immediate, AT_IMMEDIATE, imm) @@ -164,22 +165,24 @@ static ASMErrorDesc parse_arg(ASMInstArg *arg, const char *str, size_t size) } /* - Parse an argument string int ASMInstArg objects. + Parse an argument string into ASMInstArg objects. Return ED_NONE (0) on success or an error code on failure. */ static ASMErrorDesc parse_args( - ASMInstArg args[3], size_t *nargs, const char *str, size_t size) + ASMInstArg args[3], size_t *nargs, ASMArgParseInfo ap_info) { ASMErrorDesc err; - size_t start = 0, i = 0; + ASMDefineTable *dt = ap_info.deftable; + const char *str = ap_info.arg; + size_t size = ap_info.size, start = 0, i = 0; while (i < size) { char c = str[i]; if (c == ',') { if (i == start) return ED_PS_ARG_SYNTAX; - if ((err = parse_arg(&args[*nargs], str + start, i - start))) + if ((err = parse_arg(&args[*nargs], str + start, i - start, dt))) return err; (*nargs)++; @@ -202,7 +205,7 @@ static ASMErrorDesc parse_args( } if (i > start) { - if ((err = parse_arg(&args[*nargs], str + start, i - start))) + if ((err = parse_arg(&args[*nargs], str + start, i - start, dt))) return err; (*nargs)++; } diff --git a/src/assembler/instructions.h b/src/assembler/instructions.h index 1aa0fc3..6a032f3 100644 --- a/src/assembler/instructions.h +++ b/src/assembler/instructions.h @@ -6,6 +6,7 @@ #include #include "errors.h" +#include "parse_util.h" #define MIN_MNEMONIC_SIZE 2 #define MAX_MNEMONIC_SIZE 4 @@ -13,7 +14,7 @@ /* Typedefs */ typedef ASMErrorDesc (*ASMInstParser)( - uint8_t**, size_t*, char**, const char*, size_t); + uint8_t**, size_t*, char**, ASMArgParseInfo); /* Functions */ diff --git a/src/assembler/parse_util.c b/src/assembler/parse_util.c index a651244..209a285 100644 --- a/src/assembler/parse_util.c +++ b/src/assembler/parse_util.c @@ -25,15 +25,15 @@ */ /* - Adjust *arg_ptr / *size_ptr for an indirect argument, like (hl) or (ix+*). + Adjust *ap_info for an indirect argument, like (hl) or (ix+*). - *size_ptr must be > 2 to begin with, and is assured to be > 0 on success. - The two arguments are not modified on failure. + ap_info->size must be > 2 to begin with, and will always be > 0 on success. + *ap_info is not modified on failure. */ -static bool adjust_for_indirection(const char **arg_ptr, ssize_t *size_ptr) +static bool adjust_for_indirection(ASMArgParseInfo *ap_info) { - const char *arg = *arg_ptr; - ssize_t size = *size_ptr; + const char *arg = ap_info->arg; + ssize_t size = ap_info->size; if (arg[0] != '(' || arg[size - 1] != ')') return false; @@ -50,8 +50,8 @@ static bool adjust_for_indirection(const char **arg_ptr, ssize_t *size_ptr) return false; } - *arg_ptr = arg; - *size_ptr = size; + ap_info->arg = arg; + ap_info->size = size; return true; } @@ -208,19 +208,19 @@ bool parse_bytes(uint8_t **result, size_t *length, const char *arg, ssize_t size /* Read in a register argument and store it in *result. */ -bool argparse_register(ASMArgRegister *result, const char *arg, ssize_t size) +bool argparse_register(ASMArgRegister *result, ASMArgParseInfo ai) { - if (size < 1 || size > 3) + if (ai.size < 1 || ai.size > 3) return false; char buf[3] = {'\0'}; - switch (size) { - case 3: buf[2] = LCASE(arg[2]); - case 2: buf[1] = LCASE(arg[1]); - case 1: buf[0] = LCASE(arg[0]); + switch (ai.size) { + case 3: buf[2] = LCASE(ai.arg[2]); + case 2: buf[1] = LCASE(ai.arg[1]); + case 1: buf[0] = LCASE(ai.arg[0]); } - switch (size) { + switch (ai.size) { case 1: switch (buf[0]) { case 'a': return (*result = REG_A), true; @@ -263,18 +263,18 @@ bool argparse_register(ASMArgRegister *result, const char *arg, ssize_t size) /* Read in a condition argument and store it in *result. */ -bool argparse_condition(ASMArgCondition *result, const char *arg, ssize_t size) +bool argparse_condition(ASMArgCondition *result, ASMArgParseInfo ai) { - if (size < 1 || size > 2) + if (ai.size < 1 || ai.size > 2) return false; char buf[2] = {'\0'}; - switch (size) { - case 2: buf[1] = LCASE(arg[1]); - case 1: buf[0] = LCASE(arg[0]); + switch (ai.size) { + case 2: buf[1] = LCASE(ai.arg[1]); + case 1: buf[0] = LCASE(ai.arg[0]); } - switch (size) { + switch (ai.size) { case 1: switch (buf[0]) { case 'n': return (*result = COND_N), true; @@ -298,23 +298,25 @@ bool argparse_condition(ASMArgCondition *result, const char *arg, ssize_t size) /* Read in an immediate argument and store it in *result. */ -bool argparse_immediate(ASMArgImmediate *result, const char *arg, ssize_t size) +bool argparse_immediate(ASMArgImmediate *result, ASMArgParseInfo ai) { + if (ai.size <= 0) + return false; + + // TODO: lookup here for definition table + bool negative = false; ssize_t i = 0; - if (size <= 0) - return false; - - while (arg[i] == '-' || arg[i] == '+' || arg[i] == ' ') { - if (arg[i] == '-') + while (ai.arg[i] == '-' || ai.arg[i] == '+' || ai.arg[i] == ' ') { + if (ai.arg[i] == '-') negative = !negative; - if (++i >= size) + if (++i >= ai.size) return false; } uint32_t uval; - if (!parse_uint32_t(&uval, arg + i, size - i) || uval > UINT16_MAX) + if (!parse_uint32_t(&uval, ai.arg + i, ai.size - i) || uval > UINT16_MAX) return false; int32_t sval = negative ? -uval : uval; @@ -351,20 +353,20 @@ bool argparse_immediate(ASMArgImmediate *result, const char *arg, ssize_t size) /* Read in an indirect argument and store it in *result. */ -bool argparse_indirect(ASMArgIndirect *result, const char *arg, ssize_t size) +bool argparse_indirect(ASMArgIndirect *result, ASMArgParseInfo ai) { - if (size < 3 || !adjust_for_indirection(&arg, &size)) + if (ai.size < 3 || !adjust_for_indirection(&ai)) return false; ASMArgRegister reg; ASMArgImmediate imm; - if (argparse_register(®, arg, size)) { + if (argparse_register(®, ai)) { if (reg == REG_BC || reg == REG_DE || reg == REG_HL) { result->type = AT_REGISTER; result->addr.reg = reg; return true; } - } else if (argparse_immediate(&imm, arg, size)) { + } else if (argparse_immediate(&imm, ai)) { if (imm.mask & IMM_U16) { result->type = AT_IMMEDIATE; result->addr.imm = imm; @@ -377,31 +379,31 @@ bool argparse_indirect(ASMArgIndirect *result, const char *arg, ssize_t size) /* Read in an indexed argument and store it in *result. */ -bool argparse_indexed(ASMArgIndexed *result, const char *arg, ssize_t size) +bool argparse_indexed(ASMArgIndexed *result, ASMArgParseInfo ai) { - if (size < 4 || !adjust_for_indirection(&arg, &size) || size < 2) + if (ai.size < 4 || !adjust_for_indirection(&ai) || ai.size < 2) return false; ASMArgRegister reg; - if (arg[0] != 'i') + if (ai.arg[0] != 'i') return false; - if (arg[1] == 'x') + if (ai.arg[1] == 'x') reg = REG_IX; - else if (arg[1] == 'y') + else if (ai.arg[1] == 'y') reg = REG_IY; else return false; - arg += 2; - size -= 2; - if (size > 0 && arg[0] == ' ') { - arg++; - size--; + ai.arg += 2; + ai.size -= 2; + if (ai.size > 0 && ai.arg[0] == ' ') { + ai.arg++; + ai.size--; } - if (size > 0) { + if (ai.size > 0) { ASMArgImmediate imm; - if (!argparse_immediate(&imm, arg, size) || !(imm.mask & IMM_S8)) + if (!argparse_immediate(&imm, ai) || !(imm.mask & IMM_S8)) return false; result->offset = imm.sval; } else { @@ -414,20 +416,22 @@ 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) +bool argparse_label(ASMArgLabel *result, ASMArgParseInfo ai) { - if (size >= MAX_SYMBOL_SIZE) + if (ai.size <= 0 || ai.size >= MAX_SYMBOL_SIZE) return false; - for (const char *i = arg; i < arg + size; i++) { + // TODO: check for deftable + + for (const char *i = ai.arg; i < ai.arg + ai.size; i++) { char c = *i; - if (!((c >= 'a' && c <= 'z') || (i != arg && c >= '0' && c <= '9') || - c == '_' || c == '.')) + if (!((c >= 'a' && c <= 'z') || c == '_' || c == '.' || + (i != ai.arg && c >= '0' && c <= '9'))) return false; } - strncpy(result->text, arg, size); - result->text[size] = '\0'; + strncpy(result->text, ai.arg, ai.size); + result->text[ai.size] = '\0'; return true; } diff --git a/src/assembler/parse_util.h b/src/assembler/parse_util.h index 1c81927..ab2003c 100644 --- a/src/assembler/parse_util.h +++ b/src/assembler/parse_util.h @@ -11,6 +11,14 @@ #define dparse__Bool dparse_bool +/* Structs */ + +typedef struct { + const char *arg; + ssize_t size; + ASMDefineTable *deftable; +} ASMArgParseInfo; + /* Functions */ /* General parsers */ @@ -20,12 +28,12 @@ bool parse_string(char**, size_t*, const char*, ssize_t); bool parse_bytes(uint8_t**, size_t*, const char*, ssize_t); /* Instruction argument parsers */ -bool argparse_register(ASMArgRegister*, const char*, ssize_t); -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); +bool argparse_register(ASMArgRegister*, ASMArgParseInfo); +bool argparse_condition(ASMArgCondition*, ASMArgParseInfo); +bool argparse_immediate(ASMArgImmediate*, ASMArgParseInfo); +bool argparse_indirect(ASMArgIndirect*, ASMArgParseInfo); +bool argparse_indexed(ASMArgIndexed*, ASMArgParseInfo); +bool argparse_label(ASMArgLabel*, ASMArgParseInfo); /* Preprocessor directive parsers */ bool dparse_bool(bool*, const ASMLine*, const char*); diff --git a/src/assembler/state.c b/src/assembler/state.c index f0477d7..089a0e9 100644 --- a/src/assembler/state.c +++ b/src/assembler/state.c @@ -184,6 +184,16 @@ void asm_deftable_insert(ASMDefineTable *tab, ASMDefine *define) hash_table_insert(tab, (HashNode*) define); } +/* + Remove an ASMDefine from the define table. + + Return true if the node was removed, or false if it was not found. +*/ +bool asm_deftable_remove(ASMDefineTable *tab, const char *key) +{ + return hash_table_remove(tab, key); +} + #ifdef DEBUG_MODE /* DEBUG FUNCTION: Print out an ASMLine list to stdout. diff --git a/src/assembler/state.h b/src/assembler/state.h index ad4990b..1a3646b 100644 --- a/src/assembler/state.h +++ b/src/assembler/state.h @@ -110,6 +110,7 @@ const ASMSymbol* asm_symtable_find(const ASMSymbolTable*, const char*); void asm_symtable_insert(ASMSymbolTable*, ASMSymbol*); const ASMDefine* asm_deftable_find(const ASMDefineTable*, const char*); void asm_deftable_insert(ASMDefineTable*, ASMDefine*); +bool asm_deftable_remove(ASMDefineTable*, const char*); #ifdef DEBUG_MODE void asm_lines_print(const ASMLine*); diff --git a/src/assembler/tokenizer.c b/src/assembler/tokenizer.c index 4cfc782..042fc15 100644 --- a/src/assembler/tokenizer.c +++ b/src/assembler/tokenizer.c @@ -94,12 +94,13 @@ static ErrorInfo* add_label_to_table( if (line->length - 1 >= MAX_SYMBOL_SIZE) return error_info_create(line, ET_SYMBOL, ED_SYM_TOO_LONG); + ASMArgParseInfo info = {.arg = line->data, .size = line->length - 1}; ASMArgRegister reg; - if (argparse_register(®, line->data, line->length - 1)) + if (argparse_register(®, info)) return error_info_create(line, ET_SYMBOL, ED_SYM_IS_REGISTER); ASMArgCondition cond; - if (argparse_condition(&cond, line->data, line->length - 1)) + if (argparse_condition(&cond, info)) return error_info_create(line, ET_SYMBOL, ED_SYM_IS_CONDITION); char *symbol = strndup(line->data, line->length - 1); @@ -301,8 +302,8 @@ static ErrorInfo* parse_instruction( if (!parser) return error_info_create(line, ET_PARSER, ED_PS_OP_UNKNOWN); - // TODO: pass deftab here? - ASMErrorDesc edesc = parser(&bytes, &length, &symbol, argstart, arglen); + ASMArgParseInfo ai = {.arg = argstart, .size = arglen, .deftable = deftab}; + ASMErrorDesc edesc = parser(&bytes, &length, &symbol, ai); if (edesc != ED_NONE) return error_info_create(line, ET_PARSER, edesc);