ref: 249dc0489c7b24371e1f829e9c849fa7464f6c0c
dir: /appl/spree/other/tst.b/
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); }