From 9e61b076a5766a1bf7eff78911f6788111fed60e Mon Sep 17 00:00:00 2001 From: Frederick Yin Date: Tue, 16 Aug 2022 16:42:47 +0800 Subject: hack-as: Dynamic memory allocation --- projects/06/hack-as/hack-as.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/projects/06/hack-as/hack-as.c b/projects/06/hack-as/hack-as.c index 6dde75d..b152fb8 100644 --- a/projects/06/hack-as/hack-as.c +++ b/projects/06/hack-as/hack-as.c @@ -5,6 +5,7 @@ #include #define MAX_ASM_LINE_LEN 64 +#define INST_CHUNK_LEN 64 #define MAX_INST_LEN 32768 #define MAX_ADDR 32767 @@ -195,7 +196,7 @@ size_t assembler(char *input_fn, bool verbose) { // resulting in lines of what looks like instructions in assembly but is not necessarily correct // labels in parentheses are assigned corresponding addresses in ROM, then collected in `symbols` // the strings are scattered in the heap but asm_lines collects pointers to them - char *asm_lines[MAX_INST_LEN] = {NULL}; + char **asm_lines = calloc(INST_CHUNK_LEN, sizeof(char*)); int asm_line_cnt = 0; // no. of lines (metaphorically) written into asm_lines char *asm_line = malloc(MAX_ASM_LINE_LEN + 1); // one line of (probably) assembly int asm_char_cnt = 0; // no. of chars written into asm_line @@ -230,13 +231,17 @@ size_t assembler(char *input_fn, bool verbose) { symbols[predef_symbol_cnt + user_symbol_cnt] = (struct symbol) {label, asm_line_cnt}; user_symbol_cnt++; } else { - // this line may be an instruction; assemble it + // this line may be an instruction + // if we used up a chunk, realloc asm_lines + if (asm_line_cnt > 0 && asm_line_cnt % INST_CHUNK_LEN == 0) { + asm_lines = realloc(asm_lines, (asm_line_cnt + INST_CHUNK_LEN) * sizeof(char*)); + } asm_lines[asm_line_cnt] = asm_line; asm_line_cnt++; } // allocate memory for next line asm_char_cnt = 0; - asm_line = malloc(MAX_ASM_LINE_LEN); + asm_line = malloc(MAX_ASM_LINE_LEN + 1); break; case '/': if (i + 1 < file_size && file_content[i + 1] == '/') { @@ -282,7 +287,10 @@ size_t assembler(char *input_fn, bool verbose) { is_symbol = true; } } - if (!is_symbol) continue; // address is decimal constant + if (!is_symbol) { + free(addr_str); + continue; // address is decimal constant + } char illegal_char = find_illegal_symbol_char(addr_str); if (illegal_char != -1) { fprintf(stderr, "Illegal character: %c\n", illegal_char); @@ -327,6 +335,7 @@ size_t assembler(char *input_fn, bool verbose) { } for (char **line = asm_lines; *line != NULL; line++) free(*line); + free(asm_lines); for (int s = predef_symbol_cnt; s < predef_symbol_cnt + user_symbol_cnt; s++) { free(symbols[s].label); } -- cgit v1.2.3