summary refs log tree commit diff
path: root/input.e
diff options
context:
space:
mode:
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 ;