MESH.md step 3. The ports are the transport; the message is what is transported: to, from, type, heat and TTL, ACL tag, sequence, length, then text four characters to a word. - quit.v4: a node with nothing to do is blocked reading "any port"; text for it is interpreted; (FINISH) sends what it printed and then how the text ended, and it waits again - core.v4: EMIT keeps what is printed, (FLUSH-OUT) and (HDR) send it to the sender on the port the message came on. EMIT still needs one free data cell and no more; it works on the return stack and in A and B - message.h/.c: the same format for whatever is on a port and is not a node - boot.c: the boot is the node's console on port 1 and its kernel on port 0 - the prompt tests are a console that speaks messages - gone: v4_line_begin, v4_line_done, v4_line_status; writing a node's input buffer and setting its P from outside; any use of CONSOLE-TX Verified: make -C v4 test (test_host_quit.c 1283 checks, the full-stack figures unchanged) and make -C v4 sanitize pass; hosted-check passes on three ISAs with POST 550 of 550; clean qemu with STARFORTH_V4=1 passes POST and answers lines typed at each prompt on amd64, aarch64 and riscv64 (logs/20261006-110551, -111621, -111341). -110837 is an aarch64 run ended by the test wrapper's limit while still in UEFI firmware; it shows nothing about v4. Not done: KEY, EXPECT and QUERY still read the console's input registers; a message not for this node is let go (step 4). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
45 lines
1.4 KiB
C
45 lines
1.4 KiB
C
/* message.c -- a message, as it is written to a port and read from one.
|
|
* See message.h. Nothing here uses the C library.
|
|
*/
|
|
#include "v4/message.h"
|
|
|
|
unsigned v4_message_text(v4_message *m, v4_cell to, v4_cell from, v4_cell type, const char *chars, unsigned len)
|
|
{
|
|
unsigned i, words;
|
|
|
|
if (len > V4_MSG_MAX_CHARS) return 0;
|
|
words = (len + 3u) / 4u;
|
|
m->word[0] = to;
|
|
m->word[1] = from;
|
|
m->word[2] = type;
|
|
m->word[3] = 0;
|
|
m->word[4] = 0;
|
|
m->word[5] = 0;
|
|
m->word[6] = (v4_cell)len;
|
|
for (i = 0; i < words; i++) m->word[V4_MSG_HEADER + i] = 0;
|
|
for (i = 0; i < len; i++)
|
|
m->word[V4_MSG_HEADER + i / 4u] = (v4_cell)((v4_ucell)m->word[V4_MSG_HEADER + i / 4u]
|
|
| ((v4_ucell)(unsigned char)chars[i] << (8u * (i % 4u))));
|
|
m->count = V4_MSG_HEADER + words;
|
|
return m->count;
|
|
}
|
|
|
|
unsigned v4_message_length(const v4_message *m)
|
|
{
|
|
v4_cell len = m->word[6];
|
|
return (len < 0 || len > (v4_cell)V4_MSG_MAX_CHARS) ? 0u : (unsigned)len;
|
|
}
|
|
|
|
char v4_message_char(const v4_message *m, unsigned i)
|
|
{
|
|
return (char)(((v4_ucell)m->word[V4_MSG_HEADER + i / 4u] >> (8u * (i % 4u))) & 0xFFu);
|
|
}
|
|
|
|
int v4_message_word(v4_message *m, v4_cell word)
|
|
{
|
|
if (m->count < V4_MSG_MAX_WORDS) m->word[m->count] = word;
|
|
m->count++;
|
|
if (m->count < V4_MSG_HEADER) return 0;
|
|
return m->count >= V4_MSG_HEADER + (v4_message_length(m) + 3u) / 4u;
|
|
}
|