commit 33995e119a16fbf13c51cf3a72a6cc52d70a75a8
parent 0f06ef7127b669207fd8f09b88ecb660b38eb971
Author: Louis Burda <quent.burda@gmail.com>
Date: Wed, 26 Jul 2023 22:15:15 +0200
Add support for multiple input and output ports
Diffstat:
15 files changed, 270 insertions(+), 188 deletions(-)
diff --git a/asm.c b/asm.c
@@ -5,6 +5,7 @@
#include <ctype.h>
#include <stdarg.h>
#include <stdbool.h>
+#include <stdio.h>
#include <string.h>
#include <stdint.h>
@@ -15,7 +16,7 @@
enum asm_tok {
/* Global */
- TOK_STDIN, TOK_STDOUT, TOK_TPU, TOK_END,
+ TOK_IN, TOK_OUT, TOK_TPU, TOK_END,
/* Operands (order like OP_*) */
TOK_ACC, TOK_NIL, TOK_LEFT, TOK_RIGHT, TOK_UP, TOK_DOWN,
@@ -40,7 +41,7 @@ struct asm_tokenizer {
static const char *tok_strs[] = {
/* Global */
- "stdin", "stdout", "tpu", "end",
+ NULL, NULL, "tpu", "end",
/* Operands (order like OP_*) */
"acc", "nil", "left", "right", "up", "down",
@@ -56,15 +57,15 @@ static const char *tok_strs[] = {
static const char *tok_reprs[] = {
/* Global */
- "'STDIN'", "'STDOUT'", "'TPU'", "'END'",
+ "IN.<C>", "OUT.<C>", "TPU", "END",
/* Operands (order like OP_*) */
- "'ACC'", "'NIL'", "'LEFT'", "'RIGHT'", "'UP'", "'DOWN'",
- "'ANY'", "'LAST'", "<LIT>", "<NAME>",
+ "ACC", "NIL", "LEFT", "RIGHT", "UP", "DOWN",
+ "ANY", "LAST", "<LIT>", "<NAME>",
/* Instructions (order like INST_*) */
- "'NOP'", "'MOV'", "'SWP'", "'SAV'", "'ADD'", "'SUB'",
- "'NEG'", "'JMP'", "'JEZ'", "'JNZ'", "'JGZ'", "'JLZ'", "'JRO'",
+ "NOP", "MOV", "SWP", "SAV", "ADD", "SUB",
+ "NEG", "JMP", "JEZ", "JNZ", "JGZ", "JLZ", "JRO",
/* Misc */
"#<COMMENT>", "<LABEL>:", "X<INT>", "Y<INT>", "<NL>", "<EOF>"
@@ -83,7 +84,15 @@ is_int(const char *str)
return true;
}
-bool
+static int
+asm_port_char_to_index(char c)
+{
+ if (!isalpha(c))
+ die("invalid io port char '%c'", c);
+ return tolower(c) - 'a';
+}
+
+static bool
asm_is_lit(const char *str)
{
const char *c;
@@ -95,7 +104,7 @@ asm_is_lit(const char *str)
return !*c;
}
-int
+static int
asm_str_to_lit(const char *str)
{
int m, v, b, i, o;
@@ -159,11 +168,11 @@ tok_to_op(struct asm_tokenizer *tokenizer, enum asm_tok tok)
static size_t
strlcat_op_name(char *buf, struct tpu_inst_op *op, size_t n)
{
- char hhbuf[5];
+ char tmp[5];
if (op->type == OP_LIT) {
- snprintf(hhbuf, 5, "%i", op->val.lit);
- return strdcat(buf, hhbuf, n);
+ snprintf(tmp, 5, "%i", op->val.lit);
+ return strdcat(buf, tmp, n);
} else if (op->type == OP_LABEL) {
return strdcat(buf, op->val.label, n);
} else {
@@ -231,7 +240,11 @@ tok_next(struct asm_tokenizer *tok)
return (enum asm_tok) i;
}
- if (asm_is_lit(s)) {
+ if (!strncasecmp(s, "in.", 3) && len == 4) {
+ return TOK_IN;
+ } else if (!strncasecmp(s, "out.", 4) && len == 5) {
+ return TOK_OUT;
+ } else if (asm_is_lit(s)) {
return TOK_LIT;
} else if (*s == '#') {
tok->off += strlen(tok->linebuf + tok->off);
@@ -307,6 +320,7 @@ tpu_validate(struct tpu *tpu)
void
tis_load(struct tis *tis, const char *filepath)
{
+ struct tpu_io_port *io_port;
struct asm_tokenizer tokenizer;
struct tpu_inst_op op1, op2;
enum tpu_inst_type inst_type;
@@ -314,18 +328,16 @@ tis_load(struct tis *tis, const char *filepath)
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, optok;
char instbuf[TPU_MAX_INST_LEN+1];
- size_t i, len;
+ int io_x, io_y;
+ ssize_t i, k;
+ size_t len;
+ char c;
tis_deinit(tis);
tis_init(tis);
- stdin_set = stdout_set = false;
-
tokenizer.filepath = filepath;
tokenizer.file = fopen(filepath, "r");
if (!tokenizer.file) die("load: fopen '%s':", filepath);
@@ -336,23 +348,41 @@ tis_load(struct tis *tis, const char *filepath)
tokenizer.linebuf[tokenizer.off] = '\0';
while ((tok = tok_next(&tokenizer)) != TOK_EOF) {
switch (tok) {
- case TOK_STDIN:
- 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 || stdout_set) goto disallowed;
+ case TOK_IN:
+ case TOK_OUT:
+ if (tpu) goto disallowed;
+
+ io_port = malloc(sizeof(struct tpu_io_port));
+ if (!io_port) die("malloc:");
+
+ len = strlen(tokenizer.tokstr);
+ c = tokenizer.tokstr[len-1];
+ k = asm_port_char_to_index(c);
+
+ if (tok == TOK_IN) {
+ if (tis->in_ports[k])
+ die("load: line %lu, duplicate in.%c",
+ tokenizer.lineno, c);
+ tis->in_ports[k] = io_port;
+ } else {
+ if (tis->out_ports[k])
+ die("load: loute %lu, duplicate out.%c",
+ tokenizer.lineno, c);
+ tis->out_ports[k] = io_port;
+ }
+
tok_next_in(&tokenizer, TOK_XPOS, -1);
- stdout_x = atoi(tokenizer.tokstr + 1);
+ io_x = atoi(tokenizer.tokstr + 1);
tok_next_in(&tokenizer, TOK_YPOS, -1);
- stdout_y = atoi(tokenizer.tokstr + 1);
+ io_y = atoi(tokenizer.tokstr + 1);
tok_next_in(&tokenizer, TOK_NL, -1);
- stdout_set = true;
+
+ if (tok == TOK_IN)
+ tpu_io_port_init(io_port, c, DIR_UP,
+ PORT_IN, io_x, io_y);
+ else
+ tpu_io_port_init(io_port, c, DIR_DOWN,
+ PORT_OUT, io_x, io_y);
break;
case TOK_TPU:
if (tpu) goto disallowed;
@@ -445,41 +475,37 @@ tis_load(struct tis *tis, const char *filepath)
for (link = tis->tpu_map.buckets[i]; link; link = link->next) {
tpu_init_ports(link->tpu, &tis->tpu_map);
- 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");
+ for (k = -TIS_MAX_IO_PORTS; k < TIS_MAX_IO_PORTS; k++) {
+ io_port = k < 0 ? tis->in_ports[-k-1]
+ : tis->out_ports[k];
+ if (!io_port || io_port->port.attached) continue;
+ if (link->tpu->x != io_port->x) continue;
+ if (link->tpu->y != io_port->y) continue;
+ port = &link->tpu->ports[io_port->dir];
+ if (port->attached) {
+ die("load: io_port X%i Y%i (%s) busy",
+ io_port->x, io_port->y,
+ dir_reprs[io_port->dir]);
+ }
port->attached = true;
port->dst_tpu = NULL;
- port->dst_port = &tis->stdin_port;
- port->type = PORT_IN;
- tis->stdin_port.attached = true;
- tis->stdin_port.dst_tpu = link->tpu;
- tis->stdin_port.dst_port = port;
- }
-
- 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");
- port->attached = true;
- port->dst_tpu = NULL;
- port->dst_port = &tis->stdout_port;
- port->type = PORT_OUT;
- tis->stdout_port.attached = true;
- tis->stdout_port.dst_tpu = link->tpu;
- tis->stdout_port.dst_port = port;
+ port->dst_port = &io_port->port;
+ port->type = io_port->type;
+ io_port->port.attached = true;
+ io_port->port.dst_tpu = link->tpu;
+ io_port->port.dst_port = port;
}
}
}
- if (stdin_set && !tis->stdin_port.attached)
- die("load: stdin tpu (X%i Y%i) not found",
- stdin_x, stdin_y);
-
- if (stdout_set && !tis->stdout_port.attached)
- die("load: stdout tpu (X%i Y%i) not found",
- stdout_x, stdout_y);
+ for (i = -TIS_MAX_IO_PORTS; i < TIS_MAX_IO_PORTS; i++) {
+ io_port = i < 0 ? tis->in_ports[-i-1] : tis->out_ports[i];
+ if (io_port && !io_port->port.attached) {
+ die("load: io_port X%i Y%i (%s) not found",
+ io_port->x, io_port->y,
+ dir_reprs[io_port->dir]);
+ }
+ }
fclose(tokenizer.file);
@@ -494,3 +520,33 @@ disallowed:
tokenizer.lineno, tok_reprs[tok]);
}
}
+
+void
+tis_load_io(struct tis *tis, const char **argv)
+{
+ const char **arg;
+ int n, i;
+ char c;
+
+ for (arg = argv; *arg; arg++) {
+ if (sscanf(*arg, "--in.%c%n", &c, &n) == 1 && n == 6) {
+ i = asm_port_char_to_index(c);
+ if (!tis->in_ports[i])
+ die("in.%c io port not initialized", c);
+ tis->in_ports[i]->file = fopen(*++arg, "r");
+ if (!tis->in_ports[i]->file)
+ die("fopen '%s':", *arg);
+ setvbuf(tis->in_ports[i]->file, NULL, _IONBF, 0);
+ } else if (sscanf(*arg, "--out.%c%n", &c, &n) == 1 && n == 7) {
+ i = asm_port_char_to_index(c);
+ if (!tis->out_ports[i])
+ die("out.%c io port not initialized", c);
+ tis->out_ports[i]->file = fopen(*++arg, "w+");
+ if (!tis->out_ports[i]->file)
+ die("fopen '%s':", *arg);
+ setvbuf(tis->out_ports[i]->file, NULL, _IONBF, 0);
+ } else {
+ die("parse: unknown cmdline option '%s'", *arg);
+ }
+ }
+}
diff --git a/asm.h b/asm.h
@@ -4,7 +4,6 @@
#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);
+void tis_load_io(struct tis *tis, const char **argv);
diff --git a/test.sh b/test.sh
@@ -1,16 +1,30 @@
-#!/bin/sh
-
+#!/bin/bash
for f in test/*.asm; do
- in="$(echo "$f" | cut -d. -f1).in"
- out="$(echo "$f" | cut -d. -f1).out"
- tmp="/tmp/tis-test.out"
- ./tis100 "$f" "$in" "$tmp"
+ base=$(echo "$f" | cut -d. -f1)
+ args=""
+ for i in $base.in.*; do
+ c=$(echo "$i" | cut -d. -f3)
+ args="$args --in.$c $i"
+ done
+ for i in $base.out.*; do
+ c=$(echo "$i" | cut -d. -f3)
+ args="$args --out.$c /tmp/tis100-test.out.$c"
+ done
+ ./tis100 "$f" $args
if [ $? -ne 0 ]; then
echo "$f"
- elif ! diff "$out" "$tmp"; then
- cat "$tmp" | xxd 1>&2
- cat "$out" | xxd 1>&2
- echo "$f"
+ else
+ bad=0
+ for c in "abcdefghijklmnopqrstuvwyxz"; do
+ out="$base.in.$c"
+ tmp="/tmp/tis100-test.out.$c"
+ if [ -e "$out" -a -e "$tmp" ] && ! diff "$out" "$tmp"; then
+ cat "$tmp" | xxd 1>&2
+ cat "$out" | xxd 1>&2
+ bad=1
+ fi
+ done
+ [ $bad -ne 0 ] && echo "$f"
fi
done
diff --git a/test/jro.asm b/test/jro.asm
@@ -1,5 +1,5 @@
-stdin X1 Y1
-stdout X1 Y1
+in.a X1 Y1
+out.a X1 Y1
tpu X1 Y1
mov UP, ACC
diff --git a/test/jro.in b/test/jro.in.a
diff --git a/test/jro.out b/test/jro.out.a
diff --git a/test/ports.asm b/test/ports.asm
@@ -1,5 +1,5 @@
-stdin X1 Y1
-stdout X3 Y2
+in.a X1 Y1
+out.a X3 Y2
tpu X1 Y1
mov UP, RIGHT
diff --git a/test/ports.in b/test/ports.in
@@ -1,4 +0,0 @@
-1
-99
--123
-1000
diff --git a/test/jro.in b/test/ports.in.a
diff --git a/test/ports.out b/test/ports.out
@@ -1,4 +0,0 @@
-1
-99
--123
-1000
diff --git a/test/jro.in b/test/ports.out.a
diff --git a/tis100-curses.c b/tis100-curses.c
@@ -52,8 +52,6 @@ static int scrw = 80;
static int scrh = 40;
static struct tis tis;
-static FILE *tis_stdin = NULL;
-static FILE *tis_stdout = NULL;
static int show_reloaded = 0;
@@ -62,7 +60,7 @@ static enum input_mode input_mode = MAIN;
static struct tpu *tpu_sel = NULL;
int (*cleanup)(void) = endwin;
-const char *progname = "tis-curses";
+const char *progname = "tis100-curses";
static enum tpu_port_dir
key_to_dir(int key)
@@ -156,6 +154,16 @@ tui_draw_text(int x, int y, attr_t attr, const char *fmt, ...)
}
static void
+tui_draw_lit(int x, int y, attr_t attr, int lit)
+{
+ char buf[6];
+
+ snprintf(buf, 5, "%03i", lit);
+ if (buf[0] != '-') x += 1;
+ tui_draw_text(x, y, attr, "%.*s", 4, buf);
+}
+
+static void
tui_draw_wch(int x, int y, attr_t attr, const cchar_t *c)
{
attron(attr);
@@ -213,12 +221,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 + (tpu->acc >= 0), y + 2, 0, "%03i", tpu->acc);
+ tui_draw_lit(x + 1, y + 2, 0, 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 + (tpu->bak >= 0), y + 2, 0, "%03i", tpu->bak);
+ tui_draw_lit(x + 1, y + 2, 0, 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);
@@ -254,8 +262,7 @@ tui_draw_tpu(struct tpu *tpu)
if (tpu->ports[DIR_LEFT].attached) {
port = &tpu->ports[DIR_LEFT];
if (port->in_set)
- tui_draw_text(sx - 3, sy + 6,
- A_BOLD, "%03i", port->in);
+ tui_draw_lit(sx - 4, sy + 6, A_BOLD, port->in);
if (port->type & PORT_IN)
tui_draw_wch(sx - 1, sy + 7,
port->in_set ? A_BOLD : 0, WACS_RARROW);
@@ -263,15 +270,13 @@ tui_draw_tpu(struct tpu *tpu)
tui_draw_wch(sx - 1, sy + 8,
port->out_set ? A_BOLD : 0, WACS_LARROW);
if (port->out_set)
- tui_draw_text(sx - 3, sy + 10,
- A_BOLD, "%03i", port->out);
+ tui_draw_lit(sx - 4, sy + 10, A_BOLD, port->out);
}
if (tpu->ports[DIR_RIGHT].attached) {
port = &tpu->ports[DIR_RIGHT];
if (port->out_set)
- tui_draw_text(sx + TPU_W + 1, sy + 5,
- A_BOLD, "%03i", port->out);
+ tui_draw_lit(sx + TPU_W, sy + 5, A_BOLD, port->out);
if (port->type & PORT_OUT)
tui_draw_wch(sx + TPU_W + 1, sy + 7,
port->out_set ? A_BOLD : 0, WACS_RARROW);
@@ -279,15 +284,13 @@ tui_draw_tpu(struct tpu *tpu)
tui_draw_wch(sx + TPU_W + 1, sy + 8,
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);
+ tui_draw_lit(sx + TPU_W, sy + 9, A_BOLD, port->in);
}
if (tpu->ports[DIR_UP].attached) {
port = &tpu->ports[DIR_UP];
if (port->out_set)
- tui_draw_text(sx + 9, sy - 1,
- A_BOLD, "%03i", port->out);
+ tui_draw_lit(sx + 8, sy - 1, A_BOLD, port->out);
if (port->type & PORT_OUT)
tui_draw_wch(sx + 13, sy - 1,
port->out_set ? A_BOLD : 0, WACS_UARROW);
@@ -295,15 +298,13 @@ tui_draw_tpu(struct tpu *tpu)
tui_draw_wch(sx + 15, sy - 1,
port->in_set ? A_BOLD : 0, WACS_DARROW);
if (port->in_set)
- tui_draw_text(sx + 17, sy - 1,
- A_BOLD, "%03i", port->in);
+ tui_draw_lit(sx + 16, sy - 1, A_BOLD, port->in);
}
if (tpu->ports[DIR_DOWN].attached) {
port = &tpu->ports[DIR_DOWN];
if (port->in_set)
- tui_draw_text(sx + 9, sy + TPU_H,
- A_BOLD, "%03i", port->in);
+ tui_draw_lit(sx + 8, sy + TPU_H, A_BOLD, port->in);
if (port->type & PORT_IN)
tui_draw_wch(sx + 13, sy + TPU_H,
port->in_set ? A_BOLD : 0, WACS_UARROW);
@@ -311,8 +312,7 @@ tui_draw_tpu(struct tpu *tpu)
tui_draw_wch(sx + 15, sy + TPU_H,
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);
+ tui_draw_lit(sx + 16, sy + TPU_H, A_BOLD, port->out);
}
}
@@ -405,7 +405,7 @@ handlekey(int key)
scrx += 4;
break;
case 's':
- tis_communicate(&tis, tis_stdin, tis_stdout);
+ tis_communicate(&tis);
tis_step(&tis);
break;
}
@@ -441,37 +441,21 @@ first_tpu(void)
}
static void
-reset(int ifd, int argc, char **argv, bool watch)
+reset(int ifd, int argc, const char **argv, bool watch)
{
tis_load(&tis, argv[1]);
+ tis_load_io(&tis, argv + 2);
if (watch)
if (inotify_add_watch(ifd, argv[1], IN_MODIFY) < 0)
die("inotify_add_watch '%s':", argv[1]);
- if (argc >= 3) {
- if (tis_stdin) fclose(tis_stdin);
- tis_stdin = fopen(argv[2], "r");
- if (!tis_stdin) die("fopen '%s':", argv[2]);
- }
-
- if (argc >= 4) {
- if (tis_stdout) fclose(tis_stdout);
- tis_stdout = fopen(argv[3], "w+");
- if (!tis_stdout) die("fopen '%s':", argv[3]);
- }
-
- if (tis.stdin_port.attached) {
- tpu_sel = tis.stdin_port.dst_tpu;
- } else {
- tpu_sel = first_tpu();
- }
+ tpu_sel = first_tpu();
tui_seek(NULL, MID, MID);
-
}
int
-main(int argc, char **argv)
+main(int argc, const char **argv)
{
struct inotify_event event;
ssize_t len;
@@ -479,8 +463,8 @@ main(int argc, char **argv)
int key;
int ifd;
- if (argc < 2 || argc > 4) {
- fprintf(stderr, "Usage: tis-curses FILE [STDIN] [STDOUT]\n");
+ if (argc < 2) {
+ fprintf(stderr, "Usage: tis100-curses FILE [IO..]\n");
exit(1);
}
@@ -525,14 +509,6 @@ main(int argc, char **argv)
case 'h':
tui_seek(NULL, MID, MID);
break;
- case 'i':
- if (tis.stdin_port.attached)
- tui_seek(tis.stdin_port.dst_tpu, MID, MID);
- break;
- case 'o':
- if (tis.stdout_port.attached)
- tui_seek(tis.stdout_port.dst_tpu, MID, MID);
- break;
case 'r':
reset(ifd, argc, argv, false);
break;
@@ -549,8 +525,5 @@ main(int argc, char **argv)
close(ifd);
- if (tis_stdin) fclose(tis_stdin);
- if (tis_stdout) fclose(tis_stdout);
-
endwin();
}
diff --git a/tis100.c b/tis100.c
@@ -11,55 +11,48 @@
#include <stdlib.h>
static struct tis tis;
-static FILE *tis_stdin = NULL;
-static FILE *tis_stdout = NULL;
int (*cleanup)(void) = NULL;
-const char *progname = "tis-as";
+const char *progname = "tis100";
+
+static bool
+io_active(struct tis *tis)
+{
+ struct tpu_io_port *io_port;
+ int i;
+
+ for (i = 0; i < TIS_MAX_IO_PORTS; i++) {
+ io_port = tis->in_ports[i];
+ if (!io_port || !io_port->file) continue;
+ if (!feof(io_port->file) && io_port->port.attached
+ && io_port->port.dst_port->reading)
+ return true;
+ }
+ return false;
+}
int
main(int argc, const char **argv)
{
bool idle, prev_idle;
- if (argc < 2 || argc > 4) {
- fprintf(stderr, "Usage: tis-as FILE [STDIN] [STDOUT]\n");
+ if (argc < 2) {
+ fprintf(stderr, "Usage: tis100 FILE [IO..]\n");
exit(1);
}
- if (argc >= 3) {
- tis_stdin = fopen(argv[2], "r");
- if (!tis_stdin) die("fopen '%s':", argv[2]);
- } else {
- tis_stdin = stdin;
- }
- setvbuf(tis_stdin, NULL, _IONBF, 0);
-
- if (argc >= 4) {
- tis_stdout = fopen(argv[3], "w+");
- if (!tis_stdout) die("fopen '%s':", argv[3]);
- } else {
- tis_stdout = stdout;
- }
- setvbuf(tis_stdout, NULL, _IONBF, 0);
-
tis_init(&tis);
tis_load(&tis, argv[1]);
+ tis_load_io(&tis, argv + 2);
- tis.stdin_port.out = -1;
idle = false;
- while (!idle || !prev_idle || tis.stdin_port.attached
- && tis.stdin_port.reading && !feof(tis_stdin)) {
- tis_communicate(&tis, tis_stdin, tis_stdout);
-
+ while (!idle || !prev_idle || io_active(&tis)) {
+ tis_communicate(&tis);
prev_idle = idle;
idle = !tis_step(&tis);
}
- fclose(tis_stdin);
- fclose(tis_stdout);
-
tis_deinit(&tis);
}
diff --git a/tpu.c b/tpu.c
@@ -151,6 +151,26 @@ tpu_port_deinit(struct tpu_port *port)
}
void
+tpu_io_port_init(struct tpu_io_port *io_port, char c, enum tpu_port_dir dir,
+ enum tpu_port_type type, int x, int y)
+{
+ tpu_port_init(&io_port->port);
+ io_port->type = type;
+ io_port->file = NULL;
+ io_port->dir = dir;
+ io_port->c = c;
+ io_port->x = x;
+ io_port->y = y;
+}
+
+void
+tpu_io_port_deinit(struct tpu_io_port *io_port)
+{
+ tpu_port_deinit(&io_port->port);
+ if (io_port->file) fclose(io_port->file);
+}
+
+void
tpu_init(struct tpu *tpu)
{
size_t i;
@@ -611,16 +631,26 @@ void
tis_init(struct tis *tis)
{
tpu_map_init(&tis->tpu_map);
- tpu_port_init(&tis->stdin_port);
- tpu_port_init(&tis->stdout_port);
+ memset(&tis->in_ports, 0, TIS_MAX_IO_PORTS * sizeof(void *));
+ memset(&tis->out_ports, 0, TIS_MAX_IO_PORTS * sizeof(void *));
}
void
tis_deinit(struct tis *tis)
{
+ int i;
+
tpu_map_deinit(&tis->tpu_map);
- tpu_port_deinit(&tis->stdin_port);
- tpu_port_deinit(&tis->stdout_port);
+ for (i = 0; i < TIS_MAX_IO_PORTS; i++) {
+ if (tis->in_ports[i]) {
+ tpu_io_port_deinit(tis->in_ports[i]);
+ free(tis->in_ports[i]);
+ }
+ if (tis->out_ports[i]) {
+ tpu_io_port_deinit(tis->out_ports[i]);
+ free(tis->out_ports[i]);
+ }
+ }
}
bool
@@ -647,27 +677,37 @@ tis_step(struct tis *tis)
}
void
-tis_communicate(struct tis *tis, FILE *tis_stdin, FILE *tis_stdout)
+tis_communicate(struct tis *tis)
{
+ struct tpu_io_port *io_port;
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))) {
+ int val, i;
+
+ for (i = 0; i < TIS_MAX_IO_PORTS; i++) {
+ io_port = tis->in_ports[i];
+ if (!io_port) continue;
+ if (!io_port->port.attached || io_port->port.out_set)
+ continue;
+ if (!io_port->file) continue;
+ while ((s = fgets(buf, sizeof(buf), io_port->file))) {
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;
+ io_port->port.out = val;
+ io_port->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;
+ for (i = 0; i < TIS_MAX_IO_PORTS; i++) {
+ io_port = tis->out_ports[i];
+ if (!io_port) continue;
+ if (!io_port->port.attached || !io_port->port.in_set)
+ continue;
+ if (io_port->file)
+ fprintf(io_port->file, "%i\n", io_port->port.in);
+ io_port->port.in_set = false;
}
}
diff --git a/tpu.h b/tpu.h
@@ -9,6 +9,7 @@
#define LABEL_MAP_BUCKETS 64
#define TPU_MAX_INST_CNT 15
#define TPU_MAX_INST_LEN 18
+#define TIS_MAX_IO_PORTS 26
/* enum order is important ! */
@@ -103,10 +104,19 @@ struct tpu_map {
struct tpu_map_link *buckets[TPU_MAP_BUCKETS];
};
+struct tpu_io_port {
+ struct tpu_port port;
+ enum tpu_port_dir dir;
+ enum tpu_port_type type;
+ FILE *file;
+ int x, y;
+ char c;
+};
+
struct tis {
struct tpu_map tpu_map;
- struct tpu_port stdin_port;
- struct tpu_port stdout_port;
+ struct tpu_io_port *in_ports[26];
+ struct tpu_io_port *out_ports[26];
};
void label_map_init(struct label_map *map);
@@ -117,6 +127,11 @@ int label_map_get(struct label_map *map, const char *name);
void tpu_port_init(struct tpu_port *port);
void tpu_port_deinit(struct tpu_port *port);
+void tpu_io_port_init(struct tpu_io_port *io_port, char c,
+ enum tpu_port_dir dir, enum tpu_port_type type, int x, int y);
+void tpu_io_port_deinit(struct tpu_io_port *io_port);
+void tpu_io_port_attach(struct tpu_io_port *io_port, FILE *file);
+
void tpu_init(struct tpu *tpu);
void tpu_deinit(struct tpu *tpu);
struct tpu_inst *tpu_current_inst(struct tpu *tpu);
@@ -139,7 +154,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);
+void tis_communicate(struct tis *tis);
extern const char *dir_reprs[];
extern const char *status_reprs[];