commit 0f06ef7127b669207fd8f09b88ecb660b38eb971
parent 29465804bb9f3bc0eb0f538ec450e9177c0c4767
Author: Louis Burda <quent.burda@gmail.com>
Date: Wed, 26 Jul 2023 19:38:36 +0200
Fix more issues caused by negative literals
Diffstat:
10 files changed, 118 insertions(+), 94 deletions(-)
diff --git a/asm.c b/asm.c
@@ -71,18 +71,6 @@ static const char *tok_reprs[] = {
};
static bool
-is_lit(const char *str)
-{
- const char *c;
-
- c = str;
- if (*c == '-') c++;
- else if (*c == '+') c++;
- for (; *c && isdigit(*c); c++);
- return !*c;
-}
-
-static bool
is_int(const char *str)
{
char *end;
@@ -95,8 +83,20 @@ is_int(const char *str)
return true;
}
-static int
-str_to_lit(const char *str)
+bool
+asm_is_lit(const char *str)
+{
+ const char *c;
+
+ c = str;
+ if (*c == '-') c++;
+ else if (*c == '+') c++;
+ for (; *c && isdigit(*c); c++);
+ return !*c;
+}
+
+int
+asm_str_to_lit(const char *str)
{
int m, v, b, i, o;
@@ -147,7 +147,7 @@ tok_to_op(struct asm_tokenizer *tokenizer, enum asm_tok tok)
op.type = tok_to_optype(tok);
if (op.type == OP_LIT) {
- op.val.lit = str_to_lit(tokenizer->tokstr);
+ op.val.lit = asm_str_to_lit(tokenizer->tokstr);
} else if (op.type == OP_LABEL) {
op.val.label = strdup(tokenizer->tokstr);
if (!op.val.label) die("strdup:");
@@ -231,7 +231,7 @@ tok_next(struct asm_tokenizer *tok)
return (enum asm_tok) i;
}
- if (is_lit(s)) {
+ if (asm_is_lit(s)) {
return TOK_LIT;
} else if (*s == '#') {
tok->off += strlen(tok->linebuf + tok->off);
diff --git a/asm.h b/asm.h
@@ -4,5 +4,7 @@
#include <stdio.h>
+bool asm_is_lit(const char *str);
+int asm_str_to_lit(const char *str);
size_t asm_print_inst(char *buf, size_t n, struct tpu_inst *inst);
void tis_load(struct tis *tis, const char *filepath);
diff --git a/test/jro.in b/test/jro.in
@@ -1 +1,2 @@
-test
+123
+-123
diff --git a/test/jro.out b/test/jro.out
@@ -1 +1,2 @@
-test
+123
+-123
diff --git a/test/ports.in b/test/ports.in
@@ -1 +1,4 @@
-test
+1
+99
+-123
+1000
diff --git a/test/ports.out b/test/ports.out
@@ -1 +1,4 @@
-test
+1
+99
+-123
+1000
diff --git a/tis100-curses.c b/tis100-curses.c
@@ -213,14 +213,12 @@ tui_draw_tpu(struct tpu *tpu)
tui_draw_box(x, y, w, h, attr,
WACS_D_TTEE, WACS_D_URCORNER, WACS_D_LTEE, WACS_D_RTEE);
tui_draw_text(x + 2, y + 1, A_BOLD, "ACC");
- tui_draw_text(x + 1, y + 2, 0,
- tpu->acc >= 0 ? " %03i" : "-%03i", tpu->acc);
+ tui_draw_text(x + 1 + (tpu->acc >= 0), y + 2, 0, "%03i", tpu->acc);
tui_draw_box(x, (y += TPU_INFO_H - 1), w, h, attr,
WACS_D_LTEE, WACS_D_RTEE, WACS_D_LTEE, WACS_D_RTEE);
tui_draw_text(x + 2, y + 1, A_BOLD, "BAK");
- tui_draw_text(x + 1, y + 2, 0,
- tpu->bak >= 0 ? " %03i" : "-%03i", tpu->bak);
+ tui_draw_text(x + 1 + (tpu->bak >= 0), y + 2, 0, "%03i", tpu->bak);
tui_draw_box(x, (y += TPU_INFO_H - 1), w, h, attr,
WACS_D_LTEE, WACS_D_RTEE, WACS_D_LTEE, WACS_D_RTEE);
@@ -255,64 +253,64 @@ tui_draw_tpu(struct tpu *tpu)
if (tpu->ports[DIR_LEFT].attached) {
port = &tpu->ports[DIR_LEFT];
- if (port->in >= 0)
+ if (port->in_set)
tui_draw_text(sx - 3, sy + 6,
A_BOLD, "%03i", port->in);
if (port->type & PORT_IN)
tui_draw_wch(sx - 1, sy + 7,
- port->in >= 0 ? A_BOLD : 0, WACS_RARROW);
+ port->in_set ? A_BOLD : 0, WACS_RARROW);
if (port->type & PORT_OUT)
tui_draw_wch(sx - 1, sy + 8,
- port->out >= 0 ? A_BOLD : 0, WACS_LARROW);
- if (port->out >= 0)
+ port->out_set ? A_BOLD : 0, WACS_LARROW);
+ if (port->out_set)
tui_draw_text(sx - 3, sy + 10,
A_BOLD, "%03i", port->out);
}
if (tpu->ports[DIR_RIGHT].attached) {
port = &tpu->ports[DIR_RIGHT];
- if (port->out >= 0)
+ if (port->out_set)
tui_draw_text(sx + TPU_W + 1, sy + 5,
A_BOLD, "%03i", port->out);
if (port->type & PORT_OUT)
tui_draw_wch(sx + TPU_W + 1, sy + 7,
- port->out >= 0 ? A_BOLD : 0, WACS_RARROW);
+ port->out_set ? A_BOLD : 0, WACS_RARROW);
if (port->type & PORT_IN)
tui_draw_wch(sx + TPU_W + 1, sy + 8,
- port->in >= 0 ? A_BOLD : 0, WACS_LARROW);
- if (port->in >= 0)
+ port->in_set ? A_BOLD : 0, WACS_LARROW);
+ if (port->in_set)
tui_draw_text(sx + TPU_W + 1, sy + 9,
A_BOLD, "%03i", port->in);
}
if (tpu->ports[DIR_UP].attached) {
port = &tpu->ports[DIR_UP];
- if (port->out >= 0)
+ if (port->out_set)
tui_draw_text(sx + 9, sy - 1,
A_BOLD, "%03i", port->out);
if (port->type & PORT_OUT)
tui_draw_wch(sx + 13, sy - 1,
- port->out >= 0 ? A_BOLD : 0, WACS_UARROW);
+ port->out_set ? A_BOLD : 0, WACS_UARROW);
if (port->type & PORT_IN)
tui_draw_wch(sx + 15, sy - 1,
- port->in >= 0 ? A_BOLD : 0, WACS_DARROW);
- if (port->in >= 0)
+ port->in_set ? A_BOLD : 0, WACS_DARROW);
+ if (port->in_set)
tui_draw_text(sx + 17, sy - 1,
A_BOLD, "%03i", port->in);
}
if (tpu->ports[DIR_DOWN].attached) {
port = &tpu->ports[DIR_DOWN];
- if (port->in >= 0)
+ if (port->in_set)
tui_draw_text(sx + 9, sy + TPU_H,
A_BOLD, "%03i", port->in);
if (port->type & PORT_IN)
tui_draw_wch(sx + 13, sy + TPU_H,
- port->in >= 0 ? A_BOLD : 0, WACS_UARROW);
+ port->in_set ? A_BOLD : 0, WACS_UARROW);
if (port->type & PORT_OUT)
tui_draw_wch(sx + 15, sy + TPU_H,
- port->out >= 0 ? A_BOLD : 0, WACS_DARROW);
- if (port->out >= 0)
+ port->out_set ? A_BOLD : 0, WACS_DARROW);
+ if (port->out_set)
tui_draw_text(sx + 17, sy + TPU_H,
A_BOLD, "%03i", port->out);
}
@@ -388,7 +386,6 @@ static void
handlekey(int key)
{
enum tpu_port_dir dir;
- int c;
if (input_mode == MAIN) {
switch (key) {
@@ -408,18 +405,7 @@ handlekey(int key)
scrx += 4;
break;
case 's':
- if (tis_stdin && tis.stdin_port.attached
- && tis.stdin_port.out < 0) {
- c = getc(tis_stdin);
- if (c >= 0) tis.stdin_port.out = c;
- }
-
- if (tis.stdout_port.attached && tis.stdout_port.in >= 0) {
- if (tis_stdout)
- putc(tis.stdout_port.in, tis_stdout);
- tis.stdout_port.in = -1;
- }
-
+ tis_communicate(&tis, tis_stdin, tis_stdout);
tis_step(&tis);
break;
}
diff --git a/tis100.c b/tis100.c
@@ -21,7 +21,6 @@ int
main(int argc, const char **argv)
{
bool idle, prev_idle;
- int c;
if (argc < 2 || argc > 4) {
fprintf(stderr, "Usage: tis-as FILE [STDIN] [STDOUT]\n");
@@ -52,15 +51,7 @@ main(int argc, const char **argv)
idle = false;
while (!idle || !prev_idle || tis.stdin_port.attached
&& tis.stdin_port.reading && !feof(tis_stdin)) {
- if (tis.stdin_port.attached && tis.stdin_port.out < 0) {
- c = getc(tis_stdin);
- if (c >= 0) tis.stdin_port.out = c;
- }
-
- if (tis.stdout_port.attached && tis.stdout_port.in >= 0) {
- putc(tis.stdout_port.in, tis_stdout);
- tis.stdout_port.in = -1;
- }
+ tis_communicate(&tis, tis_stdin, tis_stdout);
prev_idle = idle;
idle = !tis_step(&tis);
diff --git a/tpu.c b/tpu.c
@@ -138,7 +138,9 @@ tpu_port_init(struct tpu_port *port)
port->clr_post_run = false;
port->reading = false;
port->writing = false;
+ port->in_set = false;
port->in = -1;
+ port->out_set = false;
port->out = -1;
}
@@ -246,20 +248,22 @@ tpu_update_ports(struct tpu *tpu)
for (i = 0; i < 4; i++) {
port = &tpu->ports[i];
if (!port->attached) continue;
- if (port->out >= 0 && port->dst_port->in < 0) {
- port->dst_port->reading = false;
+ if (port->out_set && !port->dst_port->in_set) {
port->dst_port->in = port->out;
+ port->dst_port->in_set = true;
+ port->dst_port->reading = false;
+ port->out_set = false;
port->writing = false;
- port->out = -1;
}
- if (port->dst_port->out >= 0 && port->in < 0) {
- port->reading = false;
+ if (port->dst_port->out_set && !port->in_set) {
port->in = port->dst_port->out;
+ port->in_set = true;
+ port->reading = false;
+ port->dst_port->out_set = false;
port->dst_port->writing = false;
- port->dst_port->out = -1;
}
if (tpu->status == STATUS_RUN && port->clr_post_run) {
- port->in = -1;
+ port->in_set = false;
port->clr_post_run = false;
}
}
@@ -323,18 +327,19 @@ tpu_add_inst(struct tpu *tpu, enum tpu_inst_type inst_type,
* (->dst_port->out) -- the read value (->in) is cleared at the end of
* an instruction step */
-static int
-tpu_port_read(struct tpu *tpu, enum tpu_port_dir dir)
+static bool
+tpu_port_read(struct tpu *tpu, enum tpu_port_dir dir, int *lit)
{
struct tpu_port *port;
port = &tpu->ports[dir];
port->clr_post_run = true;
- if (port->in < 0) {
+ if (!port->in_set) {
port->reading = true;
- return -1;
+ return false;
}
- return port->in;
+ *lit = port->in;
+ return true;
}
static bool
@@ -343,10 +348,11 @@ tpu_port_write(struct tpu *tpu, enum tpu_port_dir dir, int lit)
struct tpu_port *port;
port = &tpu->ports[dir];
- if (port->out >= 0) {
+ if (port->out_set) {
port->writing = true;
return false;
}
+ port->out_set = true;
port->out = lit;
return true;
}
@@ -359,31 +365,33 @@ tpu_jmp_label(struct tpu *tpu, const char *label)
}
int
-tpu_exec_get(struct tpu *tpu, struct tpu_inst_op *op)
+tpu_exec_get(struct tpu *tpu, struct tpu_inst_op *op, int *lit)
{
- int i, v;
+ int i;
switch (op->type) {
case OP_ACC:
- return tpu->acc;
+ *lit = tpu->acc;
+ return true;
case OP_NIL:
- return 0;
+ *lit = 0;
+ return true;
case OP_LEFT: case OP_RIGHT: case OP_UP: case OP_DOWN:
- return tpu_port_read(tpu, op_to_dir(op->type));
+ return tpu_port_read(tpu, op_to_dir(op->type), lit);
case OP_ANY:
for (i = 0; i < 4; i++) {
- v = tpu_port_read(tpu, (enum tpu_port_dir) i);
- if (v >= 0) {
+ if (tpu_port_read(tpu, (enum tpu_port_dir) i, lit)) {
tpu->last = i;
- return v;
+ return true;
}
}
- return -1;
+ return false;
case OP_LAST:
- if (tpu->last < 0) return 0;
- return tpu_port_read(tpu, (enum tpu_port_dir) tpu->last);
+ if (tpu->last < 0) return false;
+ return tpu_port_read(tpu, (enum tpu_port_dir) tpu->last, lit);
case OP_LIT:
- return op->val.lit;
+ *lit = op->val.lit;
+ return true;
case OP_LABEL:
abort();
}
@@ -426,8 +434,8 @@ tpu_exec_mov(struct tpu *tpu, struct tpu_inst *inst)
if (inst->type != INST_MOV) abort();
- lit = tpu_exec_get(tpu, &inst->ops[0]);
- if (lit < 0) return STATUS_READ;
+ if (!tpu_exec_get(tpu, &inst->ops[0], &lit))
+ return STATUS_READ;
if (!tpu_exec_put(tpu, &inst->ops[1], lit))
return STATUS_WRITE;
@@ -462,14 +470,14 @@ tpu_exec(struct tpu *tpu, struct tpu_inst *inst)
tpu->pc += 1;
return STATUS_RUN;
case INST_ADD:
- val = tpu_exec_get(tpu, &inst->ops[0]);
- if (val < 0) return STATUS_READ;
+ if (!tpu_exec_get(tpu, &inst->ops[0], &val))
+ return STATUS_READ;
tpu->acc = MIN(MAX(tpu->acc + val, -999), 999);
tpu->pc += 1;
return STATUS_RUN;
case INST_SUB:
- val = tpu_exec_get(tpu, &inst->ops[0]);
- if (val < 0) return STATUS_READ;
+ if (!tpu_exec_get(tpu, &inst->ops[0], &val))
+ return STATUS_READ;
tpu->acc = MIN(MAX(tpu->acc - val, -999), 999);
tpu->pc += 1;
return STATUS_RUN;
@@ -637,3 +645,29 @@ tis_step(struct tis *tis)
return running;
}
+
+void
+tis_communicate(struct tis *tis, FILE *tis_stdin, FILE *tis_stdout)
+{
+ char buf[16], *s;
+ int val;
+
+ if (tis_stdin && tis->stdin_port.attached && !tis->stdin_port.out_set) {
+ while ((s = fgets(buf, sizeof(buf), tis_stdin))) {
+ if ((s = strchr(buf, '\n'))) *s = '\0';
+ if (!*buf) continue;
+ val = (int) strtol(buf, &s, 10);
+ if (!s || *s != '\0')
+ die("communicate: invalid input '%s'", buf);
+ tis->stdin_port.out = val;
+ tis->stdin_port.out_set = true;
+ break;
+ }
+ }
+
+ if (tis->stdout_port.attached && tis->stdout_port.in_set) {
+ if (tis_stdout)
+ fprintf(tis_stdout, "%i\n", tis->stdout_port.in);
+ tis->stdout_port.in_set = false;
+ }
+}
diff --git a/tpu.h b/tpu.h
@@ -1,5 +1,6 @@
#pragma once
+#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
@@ -69,6 +70,7 @@ struct tpu_port {
bool clr_post_run;
bool reading, writing;
bool attached;
+ bool in_set, out_set;
int in, out;
};
@@ -137,6 +139,7 @@ struct tpu *tpu_map_get(struct tpu_map *map, int x, int y);
void tis_init(struct tis *tis);
void tis_deinit(struct tis *tis);
bool tis_step(struct tis *tis);
+void tis_communicate(struct tis *tis, FILE *tis_stdin, FILE *tis_stdout);
extern const char *dir_reprs[];
extern const char *status_reprs[];