diff options
Diffstat (limited to 'asm.c')
| -rw-r--r-- | asm.c | 70 |
1 files changed, 51 insertions, 19 deletions
@@ -16,6 +16,9 @@ #define WHITESPACE " \t\v\r\n," enum asm_tok { + /* Missing */ + TOK_NONE = -1, + /* Global */ TOK_IN, TOK_OUT, TOK_TPU, TOK_END, @@ -28,13 +31,13 @@ enum asm_tok { TOK_NEG, TOK_JMP, TOK_JEZ, TOK_JNZ, TOK_JGZ, TOK_JLZ, TOK_JRO, /* Misc */ - TOK_COMMENT, TOK_LABEL, TOK_XPOS, TOK_YPOS, TOK_NL, TOK_EOF + TOK_COMMENT, TOK_LABEL, TOK_XPOS, TOK_YPOS, TOK_NL, TOK_EOF, }; struct asm_tokenizer { const char *filepath; FILE *file; - enum asm_tok tok; + enum asm_tok next; char *tokstr; size_t lineno, off; char linebuf[256]; @@ -204,10 +207,17 @@ asm_print_inst(char *buf, size_t n, struct tpu_inst *inst) static enum asm_tok tok_next(struct asm_tokenizer *tok) { + enum asm_tok v; size_t len; char *s; int i; + if (tok->next != TOK_NONE) { + v = tok->next; + tok->next = TOK_NONE; + return v; + } + if (!tok->linebuf[tok->off]) { if (feof(tok->file)) return TOK_EOF; s = fgets(tok->linebuf, sizeof(tok->linebuf), tok->file); @@ -333,7 +343,8 @@ tis_load_asm(struct tis *tis, const char *filepath) struct tpu_map_link *link; struct tpu_port *port; enum asm_tok tok, optok; - char instbuf[TPU_MAX_INST_LEN+1]; + char rowbuf[TPU_MAX_COLS+1]; + size_t colsused; int io_x, io_y; ssize_t i, k; size_t len; @@ -345,10 +356,13 @@ tis_load_asm(struct tis *tis, const char *filepath) tokenizer.file = fopen(filepath, "r"); if (!tokenizer.file) die("load: fopen '%s':", filepath); + tokenizer.next = TOK_NONE; tokenizer.lineno = 0; tokenizer.off = 0; tokenizer.tokstr = NULL; tokenizer.linebuf[tokenizer.off] = '\0'; + + colsused = 0; while ((tok = tok_next(&tokenizer)) != TOK_EOF) { switch (tok) { case TOK_IN: @@ -380,12 +394,15 @@ tis_load_asm(struct tis *tis, const char *filepath) io_y = atoi(tokenizer.tokstr + 1); tok_next_in(&tokenizer, TOK_NL, -1); - if (tok == TOK_IN) + if (tok == TOK_IN) { tpu_io_port_init(io_port, c, DIR_UP, PORT_IN, io_x, io_y); - else + } else { tpu_io_port_init(io_port, c, DIR_DOWN, PORT_OUT, io_x, io_y); + } + + colsused = 0; break; case TOK_TPU: if (tpu) goto disallowed; @@ -400,12 +417,14 @@ tis_load_asm(struct tis *tis, const char *filepath) if (!tpu_map_add(&tis->tpu_map, tpu)) die("load: duplicate tpu location X%i Y%i", tpu->x, tpu->y); + colsused = 0; break; case TOK_END: if (!tpu) goto disallowed; tpu_validate(tpu); tpu = NULL; tok_next_in(&tokenizer, TOK_NL, -1); + colsused = 0; break; case TOK_NOP: case TOK_MOV: case TOK_SWP: case TOK_SAV: case TOK_ADD: case TOK_SUB: case TOK_NEG: case TOK_JMP: @@ -442,14 +461,17 @@ tis_load_asm(struct tis *tis, const char *filepath) if (!inst) die("load: line %lu, invalid instruction", tokenizer.lineno-1); - len = asm_print_inst(instbuf, sizeof(instbuf), inst); - if (len >= sizeof(instbuf)) - die("load: line %lu, inst too long", + tpu->rows += 1; + if (tpu->inst_cnt > TPU_MAX_INST_CNT || tpu->rows > TPU_MAX_ROWS) + die("load: line %lu, tpu has too many rows", tokenizer.lineno-1); - if (tpu->inst_cnt + tpu->label_cnt > TPU_MAX_INST_CNT) - die("load: line %lu, line does not fit", + len = asm_print_inst(rowbuf, sizeof(rowbuf), inst); + if (colsused + len > TPU_MAX_COLS) + die("load: line %lu, tpu row is too long", tokenizer.lineno-1); + + colsused = 0; break; case TOK_COMMENT: if (tpu && !strcmp(tokenizer.tokstr, "DISABLED")) @@ -457,19 +479,29 @@ tis_load_asm(struct tis *tis, const char *filepath) tok_next_in(&tokenizer, TOK_NL, -1); break; case TOK_LABEL: - if (strlen(tokenizer.tokstr) > TPU_MAX_INST_LEN - 1) + len = strlen(tokenizer.tokstr); + strncpy(rowbuf, tokenizer.tokstr, TPU_MAX_COLS); + optok = tok_next(&tokenizer); + if (!label_map_add(&tpu->label_map, rowbuf, + (int) tpu->inst_cnt, optok != TOK_NL)) + die("load: line %lu, duplicate label %s (pos)", + tokenizer.lineno, rowbuf); + if (optok == TOK_NL) { + tpu->rows += 1; + if (tpu->rows > TPU_MAX_ROWS) + die("load: line %lu, line does not fit", + tokenizer.lineno); + colsused = 0; + } else { + tokenizer.next = optok; + colsused = len + 1; + } + if (len + 1 > TPU_MAX_COLS) die("load: line %lu, label too long", tokenizer.lineno); - if (!label_map_add(&tpu->label_map, - tokenizer.tokstr, (int) tpu->inst_cnt)) - die("load: line %lu, duplicate label (pos)", - tokenizer.lineno); - tpu->label_cnt += 1; - if (tpu->inst_cnt + tpu->label_cnt > TPU_MAX_INST_CNT) - die("load: line %lu, line does not fit", - tokenizer.lineno); break; case TOK_NL: + colsused = 0; break; default: goto disallowed; |
