diff options
Diffstat (limited to 'appl/spree/other/tst.b')
| -rw-r--r-- | appl/spree/other/tst.b | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/appl/spree/other/tst.b b/appl/spree/other/tst.b new file mode 100644 index 00000000..3b35fefa --- /dev/null +++ b/appl/spree/other/tst.b @@ -0,0 +1,151 @@ +implement Tst; +include "sys.m"; + sys: Sys; +include "draw.m"; + draw: Draw; + Point, Rect: import draw; +include "bufio.m"; + bufio: Bufio; + Iobuf: import bufio; + +Tst: module +{ + init: fn(ctxt: ref Draw->Context, argv: list of string); +}; + +File: adt { + name: string; + fd: ref Sys->FD; + pid: int; +}; + +files: list of ref File; + +stderr: ref Sys->FD; +outputch: chan of chan of string; +init(ctxt: ref Draw->Context, argv: list of string) +{ + sys = load Sys Sys->PATH; + stderr = sys->fildes(2); + bufio = load Bufio Bufio->PATH; + sys->print(":cardtst\n"); + stdin := bufio->fopen(sys->fildes(0), Sys->OREAD); + line := ""; + currfd: ref Sys->FD; + outputch = chan of chan of string; + spawn outputproc(); + while ((s := stdin.gets('\n')) != nil) { + if (len s > 1 && s[len s - 2] == '\\') + line += s[0:len s - 2] + "\n"; + else { + s = line + s; + line = nil; + if (s[0] == ':') { + (nil, toks) := sys->tokenize(s, " \n"); + case hd toks { + ":open" => + if (tl toks == nil) { + sys->fprint(stderr, "usage: open file\n"); + continue; + } + f := open(hd tl toks); + if (f != nil) { + currfd = f.fd; + sys->print("current file is now %s\n", f.name); + } + ":close" => + if (tl toks == nil) { + sys->fprint(stderr, "usage: close file\n"); + continue; + } + fl := files; + f: ref File; + for (files = nil; fl != nil; fl = tl fl) { + if ((hd fl).name == hd tl toks) + f = hd fl; + else + files = hd fl :: files; + } + if (f == nil) { + sys->fprint(stderr, "unknown file '%s'\n", hd tl toks); + continue; + } + sys->fprint(f.fd, ""); + f = nil; + ":files" => + for (fl := files; fl != nil; fl = tl fl) { + if ((hd fl).fd == currfd) + sys->print(":%s <--- current\n", (hd fl).name); + else + sys->print(":%s\n", (hd fl).name); + } + * => + for (fl := files; fl != nil; fl = tl fl) + if ((hd fl).name == (hd toks)[1:]) + break; + if (fl == nil) { + sys->fprint(stderr, "unknown file '%s'\n", (hd toks)[1:]); + continue; + } + currfd = (hd fl).fd; + } + } else if (currfd == nil) + sys->fprint(stderr, "no current file\n"); + else if (len s > 1 && sys->fprint(currfd, "%s", s[0:len s - 1]) == -1) + sys->fprint(stderr, "command failed: %r\n"); + } + } + for (fl := files; fl != nil; fl = tl fl) + kill((hd fl).pid); + outputch <-= nil; +} + +open(f: string): ref File +{ + fd := sys->open("/n/remote/" + f, Sys->ORDWR); + if (fd == nil) { + sys->fprint(stderr, "cannot open %s: %r\n", f); + return nil; + } + sync := chan of int; + spawn updateproc(f, fd, sync); + files = ref File(f, fd, <-sync) :: files; + sys->print("opened %s\n", f); + return hd files; +} + +updateproc(name: string, fd: ref Sys->FD, sync: chan of int) +{ + sync <-= sys->pctl(0, nil); + c := chan of string; + buf := array[Sys->ATOMICIO] of byte; + while ((n := sys->read(fd, buf, len buf)) > 0) { + (nt, toks) := sys->tokenize(string buf[0:n], "\n"); + outputch <-= c; + c <-= "++ " + name + ":\n"; + for (; toks != nil; toks = tl toks) + c <-= sys->sprint("+%s\n", hd toks); + c <-= nil; + } + if (n < 0) + sys->fprint(stderr, "cards: error reading %s: %r\n", name); + sys->fprint(stderr, "cards: updateproc (%s) exiting\n", name); +} + +outputproc() +{ + for (;;) { + c := <-outputch; + if (c == nil) + exit; + while ((s := <-c) != nil) + sys->print("%s", s); + } +} + +kill(pid: int) +{ + if ((fd := sys->open("/prog/"+string pid+"/ctl", Sys->OWRITE)) != nil) + sys->write(fd, array of byte "kill", 4); +} + |
