diff --git a/capsules/BLOCK_MAP.md b/capsules/BLOCK_MAP.md index b8a46f22..322cbb52 100644 --- a/capsules/BLOCK_MAP.md +++ b/capsules/BLOCK_MAP.md @@ -1,5 +1,5 @@ # Capsule Block Manifest — Auto-generated - + diff --git a/capsules/v4/nucleus-64.f18 b/capsules/v4/nucleus-64.f18 index 1f73d1a1..c156aa3c 100644 Binary files a/capsules/v4/nucleus-64.f18 and b/capsules/v4/nucleus-64.f18 differ diff --git a/v4/Makefile b/v4/Makefile index 328ca604..55260251 100644 --- a/v4/Makefile +++ b/v4/Makefile @@ -200,6 +200,8 @@ hosted-check: $(foreach i,$(HOSTED_ISAS),$(BINDIR)/boot-$(i).txt) $(BINDIR)/star @grep -q "^ok> UNKNOWN WORD: 'T{'$$" $(BINDIR)/after-post-amd64.txt || { echo "hosted-check: POST's harness is on the node"; exit 1; } @printf '5 7 PORT!\n1 2 + .\n' | $(BINDIR)/starforth4-amd64 > $(BINDIR)/noone-amd64.txt 2>&1; true @grep -q '^ok> No one on that port$$' $(BINDIR)/noone-amd64.txt && grep -q '^ok> 3 ok$$' $(BINDIR)/noone-amd64.txt || { echo "hosted-check: a write to a port with no one on it was not an error the node came back from"; cat $(BINDIR)/noone-amd64.txt | tail -4; exit 1; } + @printf '5 AWAIT\n1 2 + .\n7 8 * .\n' | $(BINDIR)/starforth4-amd64 > $(BINDIR)/await-amd64.txt 2>&1; true + @grep -q '^ok> Interrupted$$' $(BINDIR)/await-amd64.txt && grep -q '^ok> 3 ok$$' $(BINDIR)/await-amd64.txt && grep -q '^ok> 56 ok$$' $(BINDIR)/await-amd64.txt || { echo "hosted-check: a line typed while the node waited did not break the wait and then run"; tail -6 $(BINDIR)/await-amd64.txt; exit 1; } @$(BINDIR)/starforth4-postfail < /dev/null > $(BINDIR)/postfail.txt; test $$? -ne 0 || { echo "hosted-check: a boot with a failing case did not fail"; exit 1; } @grep -q '^POST FAIL: fail.wrong out<5 5 $$' $(BINDIR)/postfail.txt || { echo "hosted-check: the failing case was not named"; cat $(BINDIR)/postfail.txt; exit 1; } @grep -q '^POST FAIL: fail.many outes, b->h); @@ -150,6 +151,7 @@ static int run_line(const v4_boot *b, const char *text, unsigned len, char *keep continue; } if (n->read_port != CONSOLE_PORT && n->read_port != KERNEL_PORT && v4_node_port_gone(n, V4_ERROR_NO_ONE)) continue; /* reading one port, with no one on it */ + if (n->read_port == V4_PORT_ANY) return V4_BOOT_LINE_WAITING; /* waiting for an answer: only the console can end that */ return V4_BOOT_LINE_STOPPED; /* waiting for what will not come */ } if (v4_image_waiting(n, b->im)) { /* the text is reading the keyboard */ diff --git a/v4/tests/test_host_mesh.c b/v4/tests/test_host_mesh.c index 810d0aef..871e2b96 100644 --- a/v4/tests/test_host_mesh.c +++ b/v4/tests/test_host_mesh.c @@ -317,6 +317,17 @@ int main(void) CHECK(is_empty(tell(11, ": P12 S\" 1 DROP\" 12 SEND ; P12")) && pool[1].n.mem[REFUSED] == refused + 1, "having forgotten the way to 12, what node 11 sends there goes toward its centre, which has no way either, and is refused"); CHECK(is_empty(tell(10, "12 2 ROUTE")) && is_empty(tell(11, "12 3 ROUTE")) && strcmp(tell(12, "7 8 * ."), "56 ") == 0, "told the way again, they reach 12 as before"); } + /* a line from the console breaks a wait (MESH.md 7b.6) */ + CHECK(is_empty(tell(10, "12 AWAIT .")) && ended == 0 && pool[0].n.mem[AWAIT_FROM] == 12 && waiting(hera), "node 10 waits for an answer from 12, which is not going to send one"); + CHECK(is_empty(tell(11, "20 22 + .")) && ended == 0 && pool[0].n.mem[AWAIT_FROM] == 12, "text from the console for node 11 comes to node 10 on its way: node 10 keeps it, and goes on waiting"); + { + const char *r = tell(10, "65 EMIT"); + CHECK(strstr(r, "Interrupted\n") != NULL && pool[0].n.mem[AWAIT_FROM] == 0, "text from the console for node 10 itself ends its wait, with an error that says so: \"%s\"", r); + CHECK(strstr(r, "A") != NULL && strstr(r, "42 ") != NULL && ended == 3, "the line is then done as usual, and so is what was kept for node 11: \"%s\", %d ended", r, ended); + CHECK(strstr(r, "Interrupted\n") < strstr(r, "A"), "the wait ends before the line that ended it is done"); + } + CHECK(strcmp(tell(10, "1 2 + ."), "3 ") == 0 && waiting(hera) && waiting(mid) && waiting(far), "and all three go on as before"); + CHECK(strstr(tell(10, "5 NO-ROUTE"), "ERROR") == NULL && strcmp(tell(11, "20 22 + ."), "42 ") == 0, "forgetting the way to a node there was no way to changes nothing"); printf(" %d checks, %d failures\n", checks, failures); diff --git a/v4/tools/hosted.c b/v4/tools/hosted.c index 5f6acce5..5c809ed9 100644 --- a/v4/tools/hosted.c +++ b/v4/tools/hosted.c @@ -75,6 +75,21 @@ int main(void) len = strlen(line); if (len && line[len - 1] == '\n') len--; how = v4_boot_line(&boot, line, (unsigned)len); + /* The line is waiting for an answer no one here can send. The next + * line typed breaks the wait: the line that was waiting ends in an + * error, and then the line just typed is done (boot.h). */ + while (how == V4_BOOT_LINE_WAITING) { + fflush(stdout); + if (!fgets(line, sizeof line, stdin)) { putchar('\n'); return 0; } + len = strlen(line); + if (len && line[len - 1] == '\n') len--; + how = v4_boot_line(&boot, line, (unsigned)len); + if (how == V4_BOOT_LINE_TOO_LONG) { fputs("Line too long\n ERROR\n", stdout); how = V4_BOOT_LINE_WAITING; continue; } + if (how == V4_TEXT_ERROR) fputs(" ERROR\nok> ", stdout); + else if (how == V4_TEXT_COMPLETED) fputs(" ok\nok> ", stdout); + else break; + how = v4_boot_line(&boot, 0, 0); + } if (how == V4_TEXT_COMPLETED) fputs(" ok\n", stdout); if (leaving) { fflush(stdout); return 0; } else if (how == V4_TEXT_ERROR) fputs(" ERROR\n", stdout);