diff --git a/src/assembler.c b/src/assembler.c index 31a1cdf..44c1045 100644 --- a/src/assembler.c +++ b/src/assembler.c @@ -23,8 +23,20 @@ static ErrorInfo* tokenize(AssemblerState *state) // verify no instructions clash with header offset // if rom size is set, verify nothing overflows + // otherwise, check nothing overflows max rom size (1 MB) (void) state; + +#ifdef DEBUG_MODE + DEBUG("Dumping ASMLines:") + const ASMLine *temp = state->lines; + while (temp) { + DEBUG("- %-40.*s [%s:%02zu]", (int) temp->length, temp->data, + temp->filename, temp->original->lineno) + temp = temp->next; + } +#endif + return NULL; } @@ -39,13 +51,13 @@ static ErrorInfo* resolve_defaults(AssemblerState *state) // TODO // if (!state.rom_size) - // set to max possible >= 32 KB, or error if too many instructions - // if (state.header.rom_size) - // check reported rom size is <= actual rom size + // set to max possible >= 32 KB (max of instructions, offset, and state.header.rom_size) // if (!state.header.rom_size) // set to actual rom size using util's size_bytes_to_code() + state->rom_size = 8; + (void) state; return NULL; } diff --git a/src/assembler/errors.c b/src/assembler/errors.c index e2a39f9..fe89515 100644 --- a/src/assembler/errors.c +++ b/src/assembler/errors.c @@ -76,7 +76,7 @@ ErrorInfo* error_info_create( einfo->type = err_type; einfo->desc = err_desc; - einfo->line = create_error_line(line); + einfo->line = line ? create_error_line(line) : NULL; return einfo; } diff --git a/src/assembler/errors.h b/src/assembler/errors.h index c7299f7..1045df6 100644 --- a/src/assembler/errors.h +++ b/src/assembler/errors.h @@ -23,7 +23,9 @@ typedef enum { ED_PP_DUPLICATE, ED_PP_NO_ARG, ED_PP_BAD_ARG, - ED_PP_ARG_RANGE + ED_PP_ARG_RANGE, + ED_PP_HEADER_RANGE, + ED_PP_DECLARE_RANGE } ASMErrorDesc; /* Strings */ @@ -42,7 +44,9 @@ static const char *asm_error_descs[] = { "multiple values for directive", "missing argument for directive", "invalid argument for directive", - "directive argument out of range" + "directive argument out of range", + "header offset exceeds given ROM size", + "declared ROM size in header exceeds actual size" }; /* Structs */ diff --git a/src/assembler/preprocessor.c b/src/assembler/preprocessor.c index 2eb35a6..bf41671 100644 --- a/src/assembler/preprocessor.c +++ b/src/assembler/preprocessor.c @@ -15,6 +15,7 @@ #include "io.h" #include "parse_util.h" #include "../logging.h" +#include "../rom.h" #include "../util.h" /* Helper macros for preprocess() */ @@ -49,6 +50,9 @@ #define PARSER_BRANCH(arg_type, true_part, false_part) \ if (CALL_PARSER_(arg_type)) {true_part} else {false_part} +#define SAVE_LINE(target) \ + target = line; + #define BEGIN_DIRECTIVE_BLOCK \ ssize_t first_ctr = -1; \ if (0) {} @@ -233,6 +237,7 @@ static ErrorInfo* build_asm_lines( const LineBuffer *root, const LineBuffer *source, ASMLine **head, ASMLine **tail, ASMInclude **includes) { + ErrorInfo *ei; ASMLine dummy = {.next = NULL}; ASMLine *line, *prev = &dummy; const Line *orig, *next_orig = source->lines; @@ -249,21 +254,16 @@ static ErrorInfo* build_asm_lines( line->next = NULL; if (IS_DIRECTIVE(line, DIR_INCLUDE)) { - ErrorInfo *ei; char *path = read_include_path(line); if (!path) { ei = error_info_create(line, ET_INCLUDE, ED_INC_BAD_ARG); - asm_lines_free(line); - asm_lines_free(dummy.next); - return ei; + goto error; } if (path_has_been_loaded(path, root, *includes)) { - ei = error_info_create(line, ET_INCLUDE, ED_INC_RECURSION); - asm_lines_free(line); - asm_lines_free(dummy.next); free(path); - return ei; + ei = error_info_create(line, ET_INCLUDE, ED_INC_RECURSION); + goto error; } DEBUG("- reading included file: %s", path) @@ -271,9 +271,7 @@ static ErrorInfo* build_asm_lines( free(path); if (!incbuffer) { ei = error_info_create(line, ET_INCLUDE, ED_INC_FILE_READ); - asm_lines_free(line); - asm_lines_free(dummy.next); - return ei; + goto error; } ASMInclude *include = malloc(sizeof(ASMInclude)); @@ -288,9 +286,7 @@ static ErrorInfo* build_asm_lines( if ((ei = build_asm_lines(root, incbuffer, &inchead, &inctail, includes))) { error_info_append(ei, line); - asm_lines_free(line); - asm_lines_free(dummy.next); - return ei; + goto error; } prev->next = inchead; @@ -307,6 +303,11 @@ static ErrorInfo* build_asm_lines( if (tail) *tail = prev; return NULL; + + error: + asm_lines_free(line); + asm_lines_free(dummy.next); + return ei; } /* @@ -342,6 +343,7 @@ ErrorInfo* preprocess(AssemblerState *state, const LineBuffer *source) ASMLine dummy = {.next = state->lines}; ASMLine *prev, *line = &dummy, *next = state->lines, *condemned = NULL; + const ASMLine *rom_size_line = NULL, *rom_declsize_line = NULL; const char *directive; while ((prev = line, line = next)) { @@ -364,6 +366,7 @@ ErrorInfo* preprocess(AssemblerState *state, const LineBuffer *source) USE_PARSER(uint32_t, rom_size) }) VALIDATE(size_bytes_to_code) + SAVE_LINE(rom_size_line) END_DIRECTIVE BEGIN_DIRECTIVE(DIR_ROM_HEADER, size_t, state->header.offset, DEFAULT_HEADER_OFFSET) @@ -401,6 +404,7 @@ ErrorInfo* preprocess(AssemblerState *state, const LineBuffer *source) }, { USE_PARSER(uint8_t, size_code) }) + SAVE_LINE(rom_declsize_line) END_DIRECTIVE END_DIRECTIVE_BLOCK @@ -412,24 +416,20 @@ ErrorInfo* preprocess(AssemblerState *state, const LineBuffer *source) line = prev; } - // TODO: if giving rom size, check header offset is in rom size range - // TODO: if giving reported and actual rom size, check reported is <= actual + if (state->rom_size && state->header.offset + HEADER_SIZE > state->rom_size) { + ei = error_info_create(rom_size_line, ET_PREPROC, ED_PP_HEADER_RANGE); + goto cleanup; + } - state->rom_size = 8; // TODO + if (state->rom_size && state->header.rom_size && + size_code_to_bytes(state->header.rom_size) > state->rom_size) { + ei = error_info_create(rom_size_line, ET_PREPROC, ED_PP_DECLARE_RANGE); + error_info_append(ei, rom_declsize_line); + goto cleanup; + } cleanup: asm_lines_free(condemned); state->lines = dummy.next; // Fix list head if first line was a directive - -#ifdef DEBUG_MODE - DEBUG("Dumping ASMLines:") - const ASMLine *temp = state->lines; - while (temp) { - DEBUG("- %-40.*s [%s:%02zu]", (int) temp->length, temp->data, - temp->filename, temp->original->lineno) - temp = temp->next; - } -#endif - return ei; } diff --git a/src/rom.c b/src/rom.c index 4fa0e5b..de3e07f 100644 --- a/src/rom.c +++ b/src/rom.c @@ -15,7 +15,6 @@ #define NUM_LOCATIONS 3 #define MAGIC_LEN 8 -#define HEADER_SIZE 16 #define SIZE_CODE_BUF 8 static size_t header_locations[NUM_LOCATIONS] = {0x7FF0, 0x3FF0, 0x1FF0}; diff --git a/src/rom.h b/src/rom.h index 557eae1..8dde1e4 100644 --- a/src/rom.h +++ b/src/rom.h @@ -6,6 +6,8 @@ #include #include +#define HEADER_SIZE 16 + /* Error strings */ static const char* rom_err_isdir = "Is a directory";