diff options
| author | Louis Burda <quent.burda@gmail.com> | 2023-07-25 05:56:08 +0200 |
|---|---|---|
| committer | Louis Burda <quent.burda@gmail.com> | 2023-07-25 05:56:08 +0200 |
| commit | 7d73b738a5703d5263a84dcbe3564e2267af6804 (patch) | |
| tree | e386ecb7813d86577b9fc5ef5153785de60d6f51 /asm.c | |
| parent | 41760436d528552d64122bb0c837f4d8274a0bdd (diff) | |
| download | tis100-7d73b738a5703d5263a84dcbe3564e2267af6804.tar.gz tis100-7d73b738a5703d5263a84dcbe3564e2267af6804.zip | |
Improve parsing, make stdin / stdout port optional
Diffstat (limited to 'asm.c')
| -rw-r--r-- | asm.c | 110 |
1 files changed, 60 insertions, 50 deletions
@@ -3,6 +3,7 @@ #include "tpu.h" #include <stdarg.h> +#include <stdbool.h> #include <string.h> #include <stdint.h> @@ -80,6 +81,19 @@ is_lit(const char *str) return v < 256; } +static bool +is_int(const char *str) +{ + char *end; + long v; + + v = strtol(str, &end, 10); + if (!end || *end) return false; + if (v < INT32_MIN || v > INT32_MAX) return false; + + return true; +} + static uint8_t str_to_lit(const char *str) { @@ -100,6 +114,22 @@ tok_to_optype(enum asm_tok tok) return tok - TOK_ACC + OP_ACC; } +struct tpu_inst_op +tok_to_op(struct asm_tokenizer *tokenizer, enum asm_tok tok) +{ + struct tpu_inst_op op; + + op.type = tok_to_optype(tok); + if (op.type == OP_LIT) { + op.val.lit = str_to_lit(tokenizer->tokstr); + } else if (op.type == OP_LABEL) { + op.val.label = strdup(tokenizer->tokstr); + if (!op.val.label) die("strdup:"); + } + + return op; +} + static size_t strlcat_op_name(char *buf, struct tpu_inst_op *op, size_t n) { @@ -184,9 +214,9 @@ tok_next(struct asm_tokenizer *tok) && strspn(s, NAMEALPH) == len-1 && s[len-1] == ':') { s[len-1] = '\0'; return TOK_LABEL; - } else if (*s == 'X' && atoi(s+1) > 0) { + } else if (*s == 'X' && is_int(s+1)) { return TOK_XPOS; - } else if (*s == 'Y' && atoi(s+1) > 0) { + } else if (*s == 'Y' && is_int(s+1)) { return TOK_YPOS; } else if (strchr(TEXTALPH, *s) && strspn(s, NAMEALPH) == strlen(s)) { @@ -242,7 +272,7 @@ tpu_validate(struct tpu *tpu) dst = label_map_get(&tpu->label_map, tpu->insts[i].ops[0].val.label); if (dst == TPU_MAX_INST) - die("load: tpu X%lu Y%lu, label '%s' not defined", + die("load: tpu X%i Y%i, label '%s' not defined", tpu->x, tpu->y, tpu->insts[i].ops[0].val.label); } @@ -253,23 +283,21 @@ void tis_load(struct tis *tis, const char *filepath) { struct asm_tokenizer tokenizer; - int op1, op2; - enum asm_tok op1_tok, op2_tok; - union tpu_inst_op_val op1v, op2v; + struct tpu_inst_op op1, op2; enum tpu_inst_type inst; struct tpu *tpu = NULL; struct tpu_map_link *link; struct tpu_port *port; + bool stdin_set, stdout_set; int stdin_x, stdin_y; int stdout_x, stdout_y; - enum asm_tok tok; + enum asm_tok tok, optok; size_t i; tis_deinit(tis); tis_init(tis); - stdin_x = stdin_y = 0; - stdout_x = stdout_y = 0; + stdin_set = stdout_set = false; tokenizer.filepath = filepath; tokenizer.file = fopen(filepath, "r"); @@ -282,20 +310,22 @@ tis_load(struct tis *tis, const char *filepath) while ((tok = tok_next(&tokenizer)) != TOK_EOF) { switch (tok) { case TOK_STDIN: - if (tpu) goto disallowed; + if (tpu || stdin_set) goto disallowed; tok_next_in(&tokenizer, TOK_XPOS, -1); stdin_x = atoi(tokenizer.tokstr + 1); tok_next_in(&tokenizer, TOK_YPOS, -1); stdin_y = atoi(tokenizer.tokstr + 1); tok_next_in(&tokenizer, TOK_NL, -1); + stdin_set = true; break; case TOK_STDOUT: - if (tpu) goto disallowed; + if (tpu || stdout_set) goto disallowed; tok_next_in(&tokenizer, TOK_XPOS, -1); stdout_x = atoi(tokenizer.tokstr + 1); tok_next_in(&tokenizer, TOK_YPOS, -1); stdout_y = atoi(tokenizer.tokstr + 1); tok_next_in(&tokenizer, TOK_NL, -1); + stdout_set = true; break; case TOK_TPU: if (tpu) goto disallowed; @@ -303,9 +333,9 @@ tis_load(struct tis *tis, const char *filepath) if (!tpu) die("malloc:"); tpu_init(tpu); tok_next_in(&tokenizer, TOK_XPOS, -1); - tpu->x = (size_t) atoi(tokenizer.tokstr + 1); + tpu->x = atoi(tokenizer.tokstr + 1); tok_next_in(&tokenizer, TOK_YPOS, -1); - tpu->y = (size_t) atoi(tokenizer.tokstr + 1); + tpu->y = atoi(tokenizer.tokstr + 1); tok_next_in(&tokenizer, TOK_NL, -1); tpu_map_add(&tis->tpu_map, tpu); break; @@ -322,46 +352,32 @@ tis_load(struct tis *tis, const char *filepath) if (!tpu) goto disallowed; inst = tok_to_inst(tok); - op1_tok = tok_next_in(&tokenizer, TOK_ACC, TOK_BAK, + optok = tok_next_in(&tokenizer, TOK_ACC, TOK_BAK, TOK_NIL, TOK_LEFT, TOK_RIGHT, TOK_UP, TOK_DOWN, TOK_ANY, TOK_LAST, TOK_LIT, TOK_NAME, TOK_NL, -1); - if (op1_tok == TOK_NL) { - if (!tpu_add_inst(tpu, inst, -1, op1v, -1, op2v)) + if (optok == TOK_NL) { + if (!tpu_add_inst(tpu, inst, 0, op1, op2)) die("load: line %lu, invalid instruction", - tokenizer.lineno); + tokenizer.lineno-1); break; } + op1 = tok_to_op(&tokenizer, optok); - op1 = (int) tok_to_optype(op1_tok); - if (op1 == OP_LIT) - op1v.lit = str_to_lit(tokenizer.tokstr); - else if (op1 == OP_LABEL) { - op1v.label = strdup(tokenizer.tokstr); - if (!op1v.label) die("strdup:"); - } - - op2_tok = tok_next_in(&tokenizer, TOK_ACC, TOK_BAK, + optok = tok_next_in(&tokenizer, TOK_ACC, TOK_BAK, TOK_NIL, TOK_LEFT, TOK_RIGHT, TOK_UP, TOK_DOWN, TOK_ANY, TOK_LAST, TOK_LIT, TOK_NAME, TOK_NL, -1); - if (op2_tok == TOK_NL) { - if (!tpu_add_inst(tpu, inst, op1, op1v, -1, op2v)) + if (optok == TOK_NL) { + if (!tpu_add_inst(tpu, inst, 1, op1, op2)) die("load: line %lu, invalid instruction", - tokenizer.lineno); + tokenizer.lineno-1); break; } + op2 = tok_to_op(&tokenizer, optok); - op2 = (int) tok_to_optype(op2_tok); - if (op2 == OP_LIT) - op2v.lit = str_to_lit(tokenizer.tokstr); - else if (op2 == OP_LABEL) { - op2v.label = strdup(tokenizer.tokstr); - if (!op2v.label) die("strdup:"); - } - - if (!tpu_add_inst(tpu, inst, op1, op1v, op2, op2v)) - die("load: line %lu, invalid instruction", - tokenizer.lineno); tok_next_in(&tokenizer, TOK_NL, -1); + if (!tpu_add_inst(tpu, inst, 2, op1, op2)) + die("load: line %lu, invalid instruction", + tokenizer.lineno-1); break; case TOK_COMMENT: tok_next_in(&tokenizer, TOK_NL, -1); @@ -379,17 +395,11 @@ tis_load(struct tis *tis, const char *filepath) } } - if (stdin_x == 0 || stdin_y == 0) - die("load: stdin tpu not set"); - - if (stdout_x == 0 || stdout_y == 0) - die("load: stdout tpu not set"); - for (i = 0; i < TPU_MAP_BUCKETS; i++) { for (link = tis->tpu_map.buckets[i]; link; link = link->next) { tpu_init_ports(link->tpu, &tis->tpu_map); - if (link->x == stdin_x && link->y == stdin_y) { + if (stdin_set && link->x == stdin_x && link->y == stdin_y) { port = &link->tpu->ports[DIR_UP]; if (port->attached) die("load: stdin port in use"); @@ -402,7 +412,7 @@ tis_load(struct tis *tis, const char *filepath) tis->stdin_port.dst_port = port; } - if (link->x == stdout_x && link->y == stdout_y) { + if (stdout_set && link->x == stdout_x && link->y == stdout_y) { port = &link->tpu->ports[DIR_DOWN]; if (port->attached) die("load: stdout port in use"); @@ -417,11 +427,11 @@ tis_load(struct tis *tis, const char *filepath) } } - if (!tis->stdin_port.attached) + if (stdin_set && !tis->stdin_port.attached) die("load: stdin tpu (X%i Y%i) not found", stdin_x, stdin_y); - if (!tis->stdout_port.attached) + if (stdout_set && !tis->stdout_port.attached) die("load: stdout tpu (X%i Y%i) not found", stdout_x, stdout_y); |
