summary refs log tree commit diff
path: root/input.e
diff options
context:
space:
mode:
authorIrene Knapp <ireneista@irenes.space>2026-05-26 19:41:59 -0700
committerIrene Knapp <ireneista@irenes.space>2026-05-28 03:22:11 -0700
commitd9a82e9f3c87aa318fb05819249656b43fde15e3 (patch)
tree136ac947f2cac5fb6ba2599ce4e0540f46cb5dcf /input.e
parent33fb92edc2a9958234b1bc2431a17fa4edbd83ea (diff)
add the ability to bind signal handlers
and a useful example one ;)

this also involved fixing the failure cases in input.e to handle EINTR correctly. it required a lot of tracing, but now the expected state of the stack is much better commented for next time.

many thanks to @cks@mastodon.social who found code in the Go compiler which had the details of what's required in regard to the restorer, which made the whole thing work, and to @snowfox@tech.lgbt who did some experimental testing around the exact requirements. both those contributions are reflected in the documentation added with this CL. additional thanks to everyone who chimed in on the fedi thread, your comments kept us going!

Force-Push: yes
Change-Id: I97fd89426bf807df5565e011d3665f7e904fa138
Diffstat (limited to 'input.e')
-rw-r--r--input.e31
1 files changed, 23 insertions, 8 deletions
diff --git a/input.e b/input.e
index 52fe717..dd5b7d3 100644
--- a/input.e
+++ b/input.e
@@ -226,16 +226,31 @@
 : refill-input-buffer-from-stdin
   dup normalize-buffer
   dup compute-next-buffer-free-block
+  ~ (metadata pointer, destination start, destination length)
   ~   Check whether the buffer is full. If not, do a read. If so, that's not
   ~ an error, just clean up and take no action.
-  dup { swap sys-read
-        dup 0 > {
-          dup -4 =
-          { drop recurse }
-          { drop drop s" Read error." emitstring 0 sys-exit } if-else }
-        { swap dup buffer-logical-length @ 3roll +
-          swap buffer-logical-length ! } if-else }
-      { drop drop } if-else ;
+  dup { swap
+        ~ (metadata pointer, destination length, destination start)
+        { 2dup sys-read
+          ~ (metadata pointer, destination length, destination start,
+          ~  read result)
+          dup 0 > {
+            dup -4 =
+            {
+              ~   This is the EINTR case, so we're supposed to try the same
+              ~ read again. To that end, this whole thing is running in a
+              ~ loop, and all the other paths exit.
+              drop
+              ~ (metadata pointer, destination length, destination start)
+            }
+            { drop drop drop drop
+              ." Read error." 0 sys-exit } if-else }
+          { 3unroll drop drop
+            ~ (metadata pointer, read result)
+            swap dup buffer-logical-length @ 3roll +
+            ~ (metadata pointer, adjusted logical length)
+            swap buffer-logical-length ! exit } if-else } forever }
+      { drop drop drop } if-else ;