about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-01-24 20:30:25 -0800
committerKartik K. Agaram <vc@akkartik.com>2015-01-24 20:34:15 -0800
commitcbb2018f9c79a8601823a3daca378a206c0aab67 (patch)
tree0dea74e693f6a4c0c212506854d0b8415636080a
parent12971dd65cf00a76c36b7fb78bb0d6b622ed516b (diff)
downloadmu-cbb2018f9c79a8601823a3daca378a206c0aab67.tar.gz
604 - new function to buffer stdin
Still surprisingly hard to debug. We might be barking up the wrong tree.
Or we might just need to lump it. System software is hard.
-rw-r--r--mu.arc62
-rw-r--r--mu.arc.t72
2 files changed, 129 insertions, 5 deletions
diff --git a/mu.arc b/mu.arc
index 29188a4e..705bbfe5 100644
--- a/mu.arc
+++ b/mu.arc
@@ -315,7 +315,7 @@
     (when rep.routine*!limit
       ; start the clock if it wasn't already running
       (or= rep.routine*!running-since curr-cycle*))
-    (trace "schedule" top.routine*!fn-name)
+    (trace "schedule" label.routine*)
     (routine-mark
       (run-for-time-slice scheduling-interval*))
     (update-scheduler-state)
@@ -393,6 +393,7 @@
     (until (empty running-routines*)
       (push (deq running-routines*) completed-routines*))
     (each (routine _) sleeping-routines*
+;?       (prn " " label.routine) ;? 0
       (wipe sleeping-routines*.routine)
       (push routine completed-routines*)))
   (detect-deadlock)
@@ -1954,10 +1955,18 @@
     (break-unless x:keyboard-address)
     (idx:integer-address <- get-address x:keyboard-address/deref index:offset)
     (buf:string-address <- get x:keyboard-address/deref data:offset)
+    (max:integer <- length buf:string-address/deref)
+    { begin
+      (done?:boolean <- greater-or-equal idx:integer-address/deref max:integer)
+      (break-unless done?:boolean)
+      (reply ((#\null literal)))
+    }
     (c:character <- index buf:string-address/deref idx:integer-address/deref)
     (idx:integer-address/deref <- add idx:integer-address/deref 1:literal)
     (reply c:character)
   }
+  ; real keyboard input is infrequent; avoid polling it too much
+  (sleep for-some-cycles:literal 1:literal)
   (c:character <- read-key-from-host)
   (reply c:character)
 )
@@ -1967,12 +1976,52 @@
   (k:keyboard-address <- next-input)
   (stdin:channel-address <- next-input)
   { begin
-    ; keyboard input is infrequent; sleep at the start of each iteration
-    (sleep for-some-cycles:literal 1:literal)
     (c:character <- read-key k:keyboard-address)
     (loop-unless c:character)
     (curr:tagged-value <- save-type c:character)
     (stdin:channel-address/deref <- write stdin:channel-address curr:tagged-value)
+    (eof?:boolean <- equal c:character ((#\null literal)))
+    (break-if eof?:boolean)
+    (loop)
+  }
+)
+
+(init-fn buffer-stdin
+  (default-space:space-address <- new space:literal 30:literal)
+  (stdin:channel-address <- next-input)
+  (buffered-stdin:channel-address <- next-input)
+  (line:buffer-address <- init-buffer 30:literal)
+  ; repeat forever
+  { begin
+    ; read characters from stdin until newline, copy into line
+    { begin
+      (x:tagged-value stdin:channel-address/deref <- read stdin:channel-address)
+      (c:character <- maybe-coerce x:tagged-value character:literal)
+      (assert c:character)
+      (line:buffer-address <- append line:buffer-address c:character)
+      (line-contents:string-address <- get line:buffer-address/deref data:offset)
+;?       (print-primitive-to-host c:character) ;? 0
+;?       (print-primitive-to-host (("\n" literal))) ;? 0
+      (line-done?:boolean <- equal c:character ((#\newline literal)))
+      (break-if line-done?:boolean)
+      (eof?:boolean <- equal c:character ((#\null literal)))
+      (break-if eof?:boolean)
+      (loop)
+    }
+    ; copy line into buffered-stdout
+    (break-if eof?:boolean)
+    (i:integer <- copy 0:literal)
+    (line-contents:string-address <- get line:buffer-address/deref data:offset)
+    (max:integer <- get line:buffer-address/deref length:offset)
+    { begin
+      (done?:boolean <- greater-or-equal i:integer max:integer)
+      (break-if done?:boolean)
+      (c:character <- index line-contents:string-address/deref i:integer)
+      (curr:tagged-value <- save-type c:character)
+      (buffered-stdin:channel-address/deref <- write buffered-stdin:channel-address curr:tagged-value)
+      (i:integer <- add i:integer 1:literal)
+      (loop)
+    }
     (loop)
   }
 )
@@ -2050,7 +2099,7 @@
     (idx:integer <- add t1:integer col:integer-address/deref)
     (buf:string-address <- get x:terminal-address/deref data:offset)
     (cursor:byte-address <- index-address buf:string-address/deref idx:integer)
-    (cursor:byte-address/deref <- copy c:character)
+    (cursor:byte-address/deref <- copy c:character)  ; todo: newline, etc.
     (col:integer-address/deref <- add col:integer-address/deref 1:literal)
     ; we don't rely on any auto-wrap functionality
     ; maybe die if we go out of screen bounds?
@@ -2213,11 +2262,14 @@
 
 (init-fn send-prints-to-stdout
   (default-space:space-address <- new space:literal 30:literal)
+  (screen:terminal-address <- next-input)
   (stdout:channel-address <- next-input)
   { begin
     (x:tagged-value stdout:channel-address/deref <- read stdout:channel-address)
     (c:character <- maybe-coerce x:tagged-value character:literal)
-    (print-character nil:literal/terminal c:character)
+    (done?:boolean <- equal c:character ((#\null literal)))
+    (break-if done?:boolean)
+    (print-character screen:terminal-address c:character)
     (loop)
   }
 )
diff --git a/mu.arc.t b/mu.arc.t
index 0e8d31a8..6ae86e96 100644
--- a/mu.arc.t
+++ b/mu.arc.t
@@ -4140,6 +4140,78 @@
 (when (~is memory*.1 #\o)
   (prn "F - 'read-key' advances cursor in provided string"))
 
+; to receive input line by line, run send-keys-buffered-to-stdin
+(reset)
+(new-trace "buffer-stdin-until-newline")
+(add-code
+  '((function main [
+      (default-space:space-address <- new space:literal 30:literal)
+      (s:string-address <- new "foo")
+      (k:keyboard-address <- init-keyboard s:string-address)
+      (stdin:channel-address <- init-channel 1:literal)
+      (fork send-keys-to-stdin:fn nil:literal/globals nil:literal/limit k:keyboard-address stdin:channel-address)
+      (buffered-stdin:channel-address <- init-channel 1:literal)
+      (r:integer/routine <- fork buffer-stdin:fn nil:literal/globals nil:literal/limit stdin:channel-address buffered-stdin:channel-address)
+      (screen:terminal-address <- init-fake-terminal 20:literal 10:literal)
+      (5:string-address/raw <- get screen:terminal-address/deref data:offset)
+      (fork-helper send-prints-to-stdout:fn nil:literal/globals nil:literal/limit screen:terminal-address buffered-stdin:channel-address)
+      (sleep until-routine-done:literal r:integer/routine)
+    ])))
+;? (set dump-trace*) ;? 3
+;? (= dump-trace* (obj whitelist '("schedule" "run"))) ;? 0
+(run 'main)
+;? (prn int-canon.memory*) ;? 0
+(each routine completed-routines*
+  (awhen rep.routine!error
+    (prn "error - " it)))
+(when (~memory-contains-array memory*.5
+          (+ "                    "
+             "                    "
+             "                    "
+             "                    "
+             "                    "
+             "                    "
+             "                    "
+             "                    "
+             "                    "
+             "                    "))
+  (prn "F - 'buffer-stdin' prints nothing until newline is encountered"))
+;? (quit) ;? 3
+
+(reset)
+(new-trace "print-buffered-contents-on-newline")
+(add-code
+  '((function main [
+      (default-space:space-address <- new space:literal 30:literal)
+      (s:string-address <- new "foo\nline2")
+      (k:keyboard-address <- init-keyboard s:string-address)
+      (stdin:channel-address <- init-channel 1:literal)
+      (fork send-keys-to-stdin:fn nil:literal/globals nil:literal/limit k:keyboard-address stdin:channel-address)
+      (buffered-stdin:channel-address <- init-channel 1:literal)
+      (r:integer/routine <- fork buffer-stdin:fn nil:literal/globals nil:literal/limit stdin:channel-address buffered-stdin:channel-address)
+      (screen:terminal-address <- init-fake-terminal 20:literal 10:literal)
+      (5:string-address/raw <- get screen:terminal-address/deref data:offset)
+      (fork-helper send-prints-to-stdout:fn nil:literal/globals nil:literal/limit screen:terminal-address buffered-stdin:channel-address)
+      (sleep until-routine-done:literal r:integer/routine)
+    ])))
+;? (= dump-trace* (obj whitelist '("schedule" "run"))) ;? 1
+(run 'main)
+(each routine completed-routines*
+  (awhen rep.routine!error
+    (prn "error - " it)))
+(when (~memory-contains-array memory*.5
+          (+ "foo\n                "
+             "                    "
+             "                    "
+             "                    "
+             "                    "
+             "                    "
+             "                    "
+             "                    "
+             "                    "
+             "                    "))
+  (prn "F - 'buffer-stdin' prints lines to screen"))
+
 )  ; section 100
 
 (reset)