summaryrefslogtreecommitdiffstats
path: root/asm.c
diff options
context:
space:
mode:
authorLouis Burda <quent.burda@gmail.com>2023-07-25 05:56:08 +0200
committerLouis Burda <quent.burda@gmail.com>2023-07-25 05:56:08 +0200
commit7d73b738a5703d5263a84dcbe3564e2267af6804 (patch)
treee386ecb7813d86577b9fc5ef5153785de60d6f51 /asm.c
parent41760436d528552d64122bb0c837f4d8274a0bdd (diff)
downloadtis100-7d73b738a5703d5263a84dcbe3564e2267af6804.tar.gz
tis100-7d73b738a5703d5263a84dcbe3564e2267af6804.zip
Improve parsing, make stdin / stdout port optional
Diffstat (limited to 'asm.c')
-rw-r--r--asm.c110
1 files changed, 60 insertions, 50 deletions
diff --git a/asm.c b/asm.c
index 7d02652..4c7e626 100644
--- a/asm.c
+++ b/asm.c
@@ -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);