diff --git a/src/assembler.c b/src/assembler.c index 03a8006..e6cb86f 100644 --- a/src/assembler.c +++ b/src/assembler.c @@ -33,9 +33,9 @@ static ErrorInfo* parse_instruction( /* Tokenize ASMLines into ASMInstructions. - On success, state->instructions is modified and NULL is returned. On error, - an ErrorInfo object is returned and state->instructions is not modified. - state->symtable may or may not be modified regardless of success. + NULL is returned on success and an ErrorInfo object is returned on failure. + state->instructions, state->data, and state->symtable may or may not be + modified regardless of success. */ static ErrorInfo* tokenize(AssemblerState *state) { @@ -53,32 +53,33 @@ static ErrorInfo* tokenize(AssemblerState *state) while (line) { if (IS_LOCAL_DIRECTIVE(line)) { - if (!IS_DIRECTIVE(line, DIR_ORIGIN)) { + if (IS_DIRECTIVE(line, DIR_ORIGIN)) { + if (!DIRECTIVE_HAS_ARG(line, DIR_ORIGIN)) { + ei = error_info_create(line, ET_PREPROC, ED_PP_NO_ARG); + goto cleanup; + } + + uint32_t arg; + if (!parse_uint32_t(&arg, line, DIR_ORIGIN)) { + ei = error_info_create(line, ET_PREPROC, ED_PP_BAD_ARG); + goto cleanup; + } + + offset = arg; + origin = line; + } + else { // TODO ei = error_info_create(line, ET_PREPROC, ED_PP_UNKNOWN); - goto error; - } - - if (!DIRECTIVE_HAS_ARG(line, DIR_ORIGIN)) { - ei = error_info_create(line, ET_PREPROC, ED_PP_NO_ARG); - goto error; + goto cleanup; } - - uint32_t arg; - if (!parse_uint32_t(&arg, line, DIR_ORIGIN)) { - ei = error_info_create(line, ET_PREPROC, ED_PP_BAD_ARG); - goto error; - } - - offset = arg; - origin = line; } else if (IS_LABEL(line)) { // TODO: add to symbol table } else { if ((ei = parse_instruction(line, &inst, offset))) - goto error; + goto cleanup; // TODO: bounded check on range [offset, offset + inst->length) against overlap table // if clash, use error with current line, @@ -92,13 +93,8 @@ static ErrorInfo* tokenize(AssemblerState *state) line = line->next; } - state->instructions = dummy.next; - goto cleanup; - - error: - asm_instructions_free(dummy.next); - cleanup: + state->instructions = dummy.next; free(overlap_table); return ei; } @@ -144,7 +140,7 @@ static ErrorInfo* resolve_symbols(AssemblerState *state) } /* - Convert finalized ASMInstructions into a binary data block. + Convert finalized ASMInstructions and ASMData into a binary data block. This function should never fail. */ @@ -208,10 +204,7 @@ size_t assemble(const LineBuffer *source, uint8_t **binary_ptr, ErrorInfo **ei_p *ei_ptr = error_info; cleanup: - asm_lines_free(state.lines); - asm_includes_free(state.includes); - asm_instructions_free(state.instructions); - asm_symtable_free(state.symtable); + state_free(&state); return retval; } diff --git a/src/assembler/directives.h b/src/assembler/directives.h index 10948f3..2d974d0 100644 --- a/src/assembler/directives.h +++ b/src/assembler/directives.h @@ -6,7 +6,7 @@ #include #define DIRECTIVE_MARKER '.' -#define NUM_DIRECTIVES 15 +#define NUM_DIRECTIVES 14 #define DIR_INCLUDE ".include" @@ -20,7 +20,6 @@ #define DIR_ROM_DECLSIZE ".rom_declsize" #define DIR_ORIGIN ".org" -#define DIR_ALIGN ".align" #define DIR_BYTE ".byte" #define DIR_ASCII ".ascii" #define DIR_ASCIZ ".asciz" @@ -34,9 +33,9 @@ (!DIRECTIVE_HAS_ARG(line, d) || (line)->data[strlen(d)] == ' ')) #define IS_LOCAL_DIRECTIVE(line) \ - (IS_DIRECTIVE(line, DIR_ORIGIN) || IS_DIRECTIVE(line, DIR_ALIGN) || \ - IS_DIRECTIVE(line, DIR_BYTE) || IS_DIRECTIVE(line, DIR_ASCII) || \ - IS_DIRECTIVE(line, DIR_ASCIZ) || IS_DIRECTIVE(line, DIR_ASCIIZ)) + (IS_DIRECTIVE(line, DIR_ORIGIN) || IS_DIRECTIVE(line, DIR_BYTE) || \ + IS_DIRECTIVE(line, DIR_ASCII) || IS_DIRECTIVE(line, DIR_ASCIZ) || \ + IS_DIRECTIVE(line, DIR_ASCIIZ)) #define DIRECTIVE_OFFSET(line, d) \ (DIRECTIVE_HAS_ARG(line, d) ? strlen(d) : 0) diff --git a/src/assembler/state.c b/src/assembler/state.c index 3ddf27e..77a8eb4 100644 --- a/src/assembler/state.c +++ b/src/assembler/state.c @@ -24,10 +24,23 @@ void state_init(AssemblerState *state) state->lines = NULL; state->includes = NULL; state->instructions = NULL; + state->data = NULL; state->symtable = NULL; } /* + Deallocate the contents of an AssemblerState object. +*/ +void state_free(AssemblerState *state) +{ + asm_lines_free(state->lines); + asm_includes_free(state->includes); + asm_instructions_free(state->instructions); + asm_data_free(state->data); + asm_symtable_free(state->symtable); +} + +/* Initialize an ASMSymbolTable and place it in *symtable_ptr. */ void asm_symtable_init(ASMSymbolTable **symtable_ptr) @@ -83,6 +96,19 @@ void asm_instructions_free(ASMInstruction *inst) } /* + Deallocate an ASMData list. +*/ +void asm_data_free(ASMData *data) +{ + while (data) { + ASMData *temp = data->next; + free(data->data); + free(data); + data = temp; + } +} + +/* Deallocate an ASMSymbolTable. */ void asm_symtable_free(ASMSymbolTable *symtable) diff --git a/src/assembler/state.h b/src/assembler/state.h index 1b4edaf..b922059 100644 --- a/src/assembler/state.h +++ b/src/assembler/state.h @@ -42,6 +42,14 @@ struct ASMInstruction { }; typedef struct ASMInstruction ASMInstruction; +struct ASMData { + size_t offset; + size_t length; + uint8_t *data; + struct ASMData *next; +}; +typedef struct ASMData ASMData; + struct ASMSymbol { size_t offset; char *symbol; @@ -69,16 +77,19 @@ typedef struct { ASMLine *lines; ASMInclude *includes; ASMInstruction *instructions; + ASMData *data; ASMSymbolTable *symtable; } AssemblerState; /* Functions */ void state_init(AssemblerState*); +void state_free(AssemblerState*); void asm_symtable_init(ASMSymbolTable**); void asm_lines_free(ASMLine*); void asm_includes_free(ASMInclude*); void asm_instructions_free(ASMInstruction*); +void asm_data_free(ASMData*); void asm_symtable_free(ASMSymbolTable*); #ifdef DEBUG_MODE