@@ -17,6 +17,37 @@ | |||||
#define IS_LABEL(line) (line->data[line->length - 1] == ':') | #define IS_LABEL(line) (line->data[line->length - 1] == ':') | ||||
/* | /* | ||||
Add a given line, representing a label, to the symbol table. | |||||
Return NULL on success and an ErrorInfo object on failure (in the case of | |||||
duplicate labels). | |||||
*/ | |||||
static ErrorInfo* add_label_to_table( | |||||
ASMSymbolTable *symtable, const ASMLine *line, size_t offset) | |||||
{ | |||||
char *symbol = strndup(line->data, line->length - 1); | |||||
if (!symbol) | |||||
OUT_OF_MEMORY() | |||||
const ASMSymbol *current = asm_symtable_find(symtable, symbol); | |||||
if (current) { | |||||
ErrorInfo *ei = error_info_create(line, ET_LAYOUT, ED_LYT_DUPE_LABELS); | |||||
error_info_append(ei, current->line); | |||||
return ei; | |||||
} | |||||
ASMSymbol *label = malloc(sizeof(ASMSymbol)); | |||||
if (!label) | |||||
OUT_OF_MEMORY() | |||||
label->offset = offset; | |||||
label->symbol = symbol; | |||||
label->line = line; | |||||
asm_symtable_insert(symtable, label); | |||||
return NULL; | |||||
} | |||||
/* | |||||
Parse an instruction encoded in line into an ASMInstruction object. | Parse an instruction encoded in line into an ASMInstruction object. | ||||
On success, return NULL and store the instruction in *inst_ptr. On failure, | On success, return NULL and store the instruction in *inst_ptr. On failure, | ||||
@@ -44,7 +75,9 @@ static ErrorInfo* tokenize(AssemblerState *state) | |||||
if (!overlap_table) | if (!overlap_table) | ||||
OUT_OF_MEMORY() | OUT_OF_MEMORY() | ||||
// TODO: fill overlap table for header with pointers to a dummy object | |||||
ASMLine header_indicator; | |||||
for (size_t i = 0; i < HEADER_SIZE; i++) | |||||
overlap_table[state->header.offset + i] = &header_indicator; | |||||
ErrorInfo *ei = NULL; | ErrorInfo *ei = NULL; | ||||
ASMInstruction dummy = {.next = NULL}, *inst, *prev = &dummy; | ASMInstruction dummy = {.next = NULL}, *inst, *prev = &dummy; | ||||
@@ -77,7 +110,8 @@ static ErrorInfo* tokenize(AssemblerState *state) | |||||
} | } | ||||
} | } | ||||
else if (IS_LABEL(line)) { | else if (IS_LABEL(line)) { | ||||
// TODO: add to symbol table | |||||
if ((ei = add_label_to_table(state->symtable, line, offset))) | |||||
goto cleanup; | |||||
} | } | ||||
else { | else { | ||||
if ((ei = parse_instruction(line, &inst, offset))) | if ((ei = parse_instruction(line, &inst, offset))) | ||||
@@ -33,6 +33,7 @@ static const char *asm_error_descs[] = { | |||||
"header offset exceeds given ROM size", // ED_LYT_HEADER_RANGE | "header offset exceeds given ROM size", // ED_LYT_HEADER_RANGE | ||||
"declared ROM size in header exceeds actual size", // ED_LYT_DECLARE_RANGE | "declared ROM size in header exceeds actual size", // ED_LYT_DECLARE_RANGE | ||||
"duplicate definitions for label", // ED_LYT_DUPE_LABELS | |||||
"location overlaps with ROM header", // ED_LYT_HEAD_OVERLAP | "location overlaps with ROM header", // ED_LYT_HEAD_OVERLAP | ||||
"location overlaps with previous instruction", // ED_LYT_INST_OVERLAP | "location overlaps with previous instruction", // ED_LYT_INST_OVERLAP | ||||
"location overlaps with previous data", // ED_LYT_DATA_OVERLAP | "location overlaps with previous data", // ED_LYT_DATA_OVERLAP | ||||
@@ -29,6 +29,7 @@ typedef enum { | |||||
ED_LYT_HEADER_RANGE, | ED_LYT_HEADER_RANGE, | ||||
ED_LYT_DECLARE_RANGE, | ED_LYT_DECLARE_RANGE, | ||||
ED_LYT_DUPE_LABELS, | |||||
ED_LYT_HEAD_OVERLAP, | ED_LYT_HEAD_OVERLAP, | ||||
ED_LYT_INST_OVERLAP, | ED_LYT_INST_OVERLAP, | ||||
ED_LYT_DATA_OVERLAP, | ED_LYT_DATA_OVERLAP, | ||||
@@ -128,6 +128,40 @@ void asm_symtable_free(ASMSymbolTable *symtable) | |||||
free(symtable); | free(symtable); | ||||
} | } | ||||
/* | |||||
... | |||||
*/ | |||||
static inline size_t hash_key(const char *key) | |||||
{ | |||||
return 0; | |||||
} | |||||
/* | |||||
Search for a key in the symbol table. | |||||
Return the key on success and NULL on failure. | |||||
*/ | |||||
const ASMSymbol* asm_symtable_find(const ASMSymbolTable *tab, const char *key) | |||||
{ | |||||
ASMSymbol *symbol = tab->buckets[hash_key(key)]; | |||||
while (symbol) { | |||||
if (!strcmp(key, symbol->symbol)) | |||||
return symbol; | |||||
symbol = symbol->next; | |||||
} | |||||
return NULL; | |||||
} | |||||
/* | |||||
Insert a symbol into the table. | |||||
*/ | |||||
void asm_symtable_insert(ASMSymbolTable *tab, ASMSymbol *symbol) | |||||
{ | |||||
size_t index = hash_key(symbol->symbol); | |||||
symbol->next = tab->buckets[index]; | |||||
tab->buckets[index] = symbol; | |||||
} | |||||
#ifdef DEBUG_MODE | #ifdef DEBUG_MODE | ||||
/* | /* | ||||
DEBUG FUNCTION: Print out an ASMLine list to stdout. | DEBUG FUNCTION: Print out an ASMLine list to stdout. | ||||
@@ -53,6 +53,7 @@ typedef struct ASMData ASMData; | |||||
struct ASMSymbol { | struct ASMSymbol { | ||||
size_t offset; | size_t offset; | ||||
char *symbol; | char *symbol; | ||||
const ASMLine *line; | |||||
struct ASMSymbol *next; | struct ASMSymbol *next; | ||||
}; | }; | ||||
typedef struct ASMSymbol ASMSymbol; | typedef struct ASMSymbol ASMSymbol; | ||||
@@ -92,6 +93,9 @@ void asm_instructions_free(ASMInstruction*); | |||||
void asm_data_free(ASMData*); | void asm_data_free(ASMData*); | ||||
void asm_symtable_free(ASMSymbolTable*); | void asm_symtable_free(ASMSymbolTable*); | ||||
const ASMSymbol* asm_symtable_find(const ASMSymbolTable*, const char*); | |||||
void asm_symtable_insert(ASMSymbolTable*, ASMSymbol*); | |||||
#ifdef DEBUG_MODE | #ifdef DEBUG_MODE | ||||
void asm_lines_print(const ASMLine*); | void asm_lines_print(const ASMLine*); | ||||
#endif | #endif |