From 0fe98bd04872a576880a9a14f2b4b861da6670d8 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Sat, 18 Apr 2015 22:03:24 -0500 Subject: [PATCH] Support string arguments to .rom_size, .rom_declsize. --- src/assembler/parse_util.c | 96 ++++++++++++++++++++++++++------------------ src/assembler/parse_util.h | 10 ++--- src/assembler/preprocessor.c | 9 +++-- 3 files changed, 68 insertions(+), 47 deletions(-) diff --git a/src/assembler/parse_util.c b/src/assembler/parse_util.c index 8635b9f..3f89355 100644 --- a/src/assembler/parse_util.c +++ b/src/assembler/parse_util.c @@ -10,13 +10,20 @@ #define MAX_REGION_SIZE 32 +#define PARSE_FUNC_HEADER(name, type) \ + bool parse_##name(type *result, const ASMLine *line, const char *directive) + /* - Read in a boolean argument from the given line and store it in *result. + All public functions in this file follow the same return conventions: + + - Return true on success and false on failure. + - *result is only modified on success. +*/ - Return true on success and false on failure; in the latter case, *result is - not modified. +/* + Read in a boolean argument from the given line and store it in *result. */ -bool parse_bool(bool *result, const ASMLine *line, const char *directive) +PARSE_FUNC_HEADER(bool, bool) { size_t offset = DIRECTIVE_OFFSET(line, directive) + 1; const char *arg = line->data + offset; @@ -52,15 +59,11 @@ bool parse_bool(bool *result, const ASMLine *line, const char *directive) /* Read in a 32-bit int argument from the given line and store it in *result. - - Return true on success and false on failure; in the latter case, *result is - not modified. */ -bool parse_uint32_t(uint32_t *result, const ASMLine *line, const char *directive) +PARSE_FUNC_HEADER(uint32_t, uint32_t) { - size_t offset = DIRECTIVE_OFFSET(line, directive) + 1; - const char *str = line->data + offset; - const char *end = str + line->length - offset; + const char *str = line->data + DIRECTIVE_OFFSET(line, directive) + 1; + const char *end = line->data + line->length; if (end - str <= 0) return false; @@ -100,11 +103,8 @@ bool parse_uint32_t(uint32_t *result, const ASMLine *line, const char *directive /* Read in a 16-bit int argument from the given line and store it in *result. - - Return true on success and false on failure; in the latter case, *result is - not modified. */ -bool parse_uint16_t(uint16_t *result, const ASMLine *line, const char *directive) +PARSE_FUNC_HEADER(uint16_t, uint16_t) { uint32_t value; if (parse_uint32_t(&value, line, directive) && value <= UINT16_MAX) @@ -114,11 +114,8 @@ bool parse_uint16_t(uint16_t *result, const ASMLine *line, const char *directive /* Read in an 8-bit int argument from the given line and store it in *result. - - Return true on success and false on failure; in the latter case, *result is - not modified. */ -bool parse_uint8_t(uint8_t *result, const ASMLine *line, const char *directive) +PARSE_FUNC_HEADER(uint8_t, uint8_t) { uint32_t value; if (parse_uint32_t(&value, line, directive) && value <= UINT8_MAX) @@ -128,32 +125,54 @@ bool parse_uint8_t(uint8_t *result, const ASMLine *line, const char *directive) /* Parse a ROM size string in an ASMLine and store it in *result. - - Return true on success and false on failure; in the latter case, *result is - not modified. */ -bool parse_rom_size(uint32_t *result, const ASMLine *line) +PARSE_FUNC_HEADER(rom_size, uint32_t) { - uint32_t bytes; - if (!parse_uint32_t(&bytes, line, DIR_ROM_SIZE)) + const char *arg = line->data + DIRECTIVE_OFFSET(line, directive) + 1; + const char *end = line->data + line->length - 1; + + if (end - arg < 5) + return false; + if (*(arg++) != '"' || *(end--) != '"') + return false; + if (*end != 'B' && *end != 'b') return false; + end--; + + uint32_t factor; + if (*end == 'K' || *end == 'k') + factor = 1 << 10; + else if (*end == 'M' || *end == 'm') + factor = 1 << 20; + else + return false; + end--; - if (size_bytes_to_code(bytes)) - return (*result = bytes), true; - return false; + if (*end != ' ') + return false; + + uint32_t value = 0; + while (arg < end) { + if (*arg < '0' || *arg > '9') + return false; + value = (value * 10) + (*arg - '0'); + if (value > UINT16_MAX) + return false; + arg++; + } + + *result = value * factor; + return true; } /* Parse a region code string in an ASMLine and store it in *result. - - Return true on success and false on failure; in the latter case, *result is - not modified. */ -bool parse_region_string(uint8_t *result, const ASMLine *line) +PARSE_FUNC_HEADER(region_string, uint8_t) { char buffer[MAX_REGION_SIZE]; - size_t offset = DIRECTIVE_OFFSET(line, DIR_ROM_REGION) + 1; + size_t offset = DIRECTIVE_OFFSET(line, directive) + 1; const char *arg = line->data + offset; ssize_t len = line->length - offset; @@ -173,15 +192,14 @@ bool parse_region_string(uint8_t *result, const ASMLine *line) /* Parse a size code in an ASMLine and store it in *result. - - Return true on success and false on failure; in the latter case, *result is - not modified. */ -bool parse_size_code(uint8_t *result, const ASMLine *line) +PARSE_FUNC_HEADER(size_code, uint8_t) { uint32_t bytes; - if (!parse_uint32_t(&bytes, line, DIR_ROM_DECLSIZE)) - return false; + if (!parse_uint32_t(&bytes, line, directive)) { + if (!parse_rom_size(&bytes, line, directive)) + return false; + } uint8_t code = size_bytes_to_code(bytes); if (code) diff --git a/src/assembler/parse_util.h b/src/assembler/parse_util.h index 05dd933..e5ce7e5 100644 --- a/src/assembler/parse_util.h +++ b/src/assembler/parse_util.h @@ -8,15 +8,15 @@ #include "state.h" -#define parse__Bool parse_bool +#define parse_bool parse__Bool /* Functions */ -bool parse_bool(bool*, const ASMLine*, const char*); +bool parse__Bool(bool*, const ASMLine*, const char*); bool parse_uint32_t(uint32_t*, const ASMLine*, const char*); bool parse_uint16_t(uint16_t*, const ASMLine*, const char*); bool parse_uint8_t(uint8_t*, const ASMLine*, const char*); -bool parse_rom_size(uint32_t*, const ASMLine*); -bool parse_region_string(uint8_t*, const ASMLine*); -bool parse_size_code(uint8_t*, const ASMLine*); +bool parse_rom_size(uint32_t*, const ASMLine*, const char*); +bool parse_region_string(uint8_t*, const ASMLine*, const char*); +bool parse_size_code(uint8_t*, const ASMLine*, const char*); diff --git a/src/assembler/preprocessor.c b/src/assembler/preprocessor.c index 6ee2d88..2eb35a6 100644 --- a/src/assembler/preprocessor.c +++ b/src/assembler/preprocessor.c @@ -29,7 +29,7 @@ parse_##arg_type((arg_type*) &arg, line, directive) #define CALL_SPECIFIC_PARSER_(arg_type, parser) \ - parse_##parser((arg_type*) &arg, line) + parse_##parser((arg_type*) &arg, line, directive) #define DISPATCH_(first, second, target, ...) target @@ -57,7 +57,7 @@ else if (first_ctr++, IS_DIRECTIVE(line, d)) { \ directive = d; \ FAIL_ON_COND_(!DIRECTIVE_HAS_ARG(line, directive), ED_PP_NO_ARG) \ - arg_type arg; \ + arg_type arg = 0; \ arg_type* dest = &(dest_loc); \ if (DIRECTIVE_IS_AUTO(line, directive)) { \ arg = auto_val; \ @@ -360,7 +360,10 @@ ErrorInfo* preprocess(AssemblerState *state, const LineBuffer *source) END_DIRECTIVE BEGIN_DIRECTIVE(DIR_ROM_SIZE, size_t, state->rom_size, 0) - USE_PARSER(uint32_t, rom_size) + PARSER_BRANCH(uint32_t, {}, { + USE_PARSER(uint32_t, rom_size) + }) + VALIDATE(size_bytes_to_code) END_DIRECTIVE BEGIN_DIRECTIVE(DIR_ROM_HEADER, size_t, state->header.offset, DEFAULT_HEADER_OFFSET)