summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrederick Yin <fkfd@fkfd.me>2022-08-16 16:42:47 +0800
committerFrederick Yin <fkfd@fkfd.me>2022-08-16 16:42:47 +0800
commit9e61b076a5766a1bf7eff78911f6788111fed60e (patch)
treefa57ca96275e71821fd702ce7bd198bd8d72de28
parentfbfa52da575e283def59c6487b51dd66eebc03b8 (diff)
hack-as: Dynamic memory allocation
-rw-r--r--projects/06/hack-as/hack-as.c17
1 files 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 <string.h>
#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);
}