# RRE Listener and Extensions In this file I am implementing the interactive listener that RRE will run when started with `-i`, `-i,c`, or `-i,fs`. The basic image has a space allocated for input at the end of the kernel. This is at address 1024 (the kernel space is fixed at addresses 0 to 1023). ~~~ #1024 'TIB const ~~~ ~~~ :image:save (s-) #1000 io:scan-for io:invoke ; ~~~ ## Console Input The RRE interface provides a keyboard device. This exposes it via `c:get`. ~~~ {{ 'Keyboard var :identify @Keyboard n:zero? [ #1 io:scan-for dup n:negative? [ drop 'IO_DEVICE_TYPE_0001_NOT_FOUND s:put nl ] [ !Keyboard ] choose ] if ; ---reveal--- :c:get (-c) identify @Keyboard io:invoke ; }} ~~~ Now that I can read characters, it's time to support reading strings. I do this via two words. The first is `parse-until`. This will setup a temporary string as an input buffer, then read input, passing each character ot a provided quote. When the quote returns `TRUE`, it ends and returns the string. When not `TRUE` it will add the character to the buffer. ~~~ {{ :gather (c-) dup [ ASCII:BS eq? ] [ ASCII:DEL eq? ] bi or &drop &buffer:add choose ; :cycle (q-qc) repeat c:get dup-pair swap call not 0; drop gather again ; ---reveal--- :parse-until (q-s) [ s:empty buffer:set cycle drop-pair buffer:start ] buffer:preserve ; }} ~~~ Using this, a simple `s:get` can be implemented very easily as a quote which looks for an end of line character. ~~~ :s:get (-s) [ [ ASCII:LF eq? ] [ ASCII:CR eq? ] bi or ] parse-until ; :s:get-word (-s) &c:whitespace? parse-until ; ~~~ ## Scripting: Command Line Arguments RRE also provides access to the command line arguments passed to a script. The next few words map the scripting device to words we can use. ~~~ {{ 'Scripting var :identify @Scripting n:zero? [ #9 io:scan-for dup n:negative? [ drop 'IO_DEVICE_TYPE_0009_NOT_FOUND s:put nl ] [ !Scripting ] choose ] if ; ---reveal--- :sys:argc (-n) identify #0 @Scripting io:invoke ; :sys:argv (n-s) s:empty swap identify #1 @Scripting io:invoke ; :include (s-) identify #2 @Scripting io:invoke ; :sys:name (-s) s:empty identify #3 @Scripting io:invoke ; :sys:current-file (-s) s:empty identify #4 @Scripting io:invoke ; :sys:current-line (-n) identify #5 @Scripting io:invoke ; :sys:ignore-to-eol (-) identify #6 @Scripting io:invoke ; :sys:abort-include (-) identify #7 @Scripting io:invoke ; }} ~~~ ~~~ :clear ASCII:ESC c:put '[2J s:put ASCII:ESC c:put '[0;0H s:put ; ~~~ Hide the support words. # Standard Interactive Listener The main part of this file is the *listener*, an interactive read-eval-print loop. RRE's C part will access a couple parts of this, based on the startup flags passed. ~~~ 'NoEcho var :bye #0 unix:exit ; {{ 'EOT var FALSE 'Ignoring var-n (-f) :ignoring? @Ignoring ; (-nn) :version @Version #100 /mod ; (c-f) :done? dup !EOT [ ASCII:CR eq? ] [ ASCII:LF eq? ] [ ASCII:SPACE eq? ] tri or or ; (c-f) :eol? @EOT [ ASCII:CR eq? ] [ ASCII:LF eq? ] bi or ; (s-sf) :valid? dup s:length n:strictly-positive? ; (c-c) :check-eof dup [ #-1 eq? ] [ ASCII:EOT eq? ] bi or &bye if ; :bs buffer:get buffer:get drop-pair ; (c-c) :check-bs dup [ ASCII:BS eq? ] [ ASCII:DEL eq? ] bi or &bs if ; (c-c) :check check-eof check-bs ; (-c) :character c:get dup buffer:add ; (q-) :buffer [ TIB buffer:set call buffer:start ] buffer:preserve ; (-s) :read-token [ [ character check done? ] until ] buffer s:chop ; (-sf) :input read-token valid? ; (sf-) :process ignoring? [ drop-pair eol? [ &Ignoring v:off ] if ] if; &interpret &drop choose ; ---reveal--- :// sys:ignore-to-eol &Ignoring v:on ; immediate :banner version 'RETRO_12_(%n.%n)\n s:format s:put EOM here - here EOM '%n_Max,_%n_Used,_%n_Free\n s:format s:put ; :listen @NoEcho [ banner ] -if repeat input process again ; }} &listen #1 store ~~~