summaryrefslogtreecommitdiff
path: root/appl/alphabet/reports.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/alphabet/reports.b')
-rw-r--r--appl/alphabet/reports.b189
1 files changed, 189 insertions, 0 deletions
diff --git a/appl/alphabet/reports.b b/appl/alphabet/reports.b
new file mode 100644
index 00000000..d9336d8b
--- /dev/null
+++ b/appl/alphabet/reports.b
@@ -0,0 +1,189 @@
+implement Reports;
+include "sys.m";
+ sys: Sys;
+include "draw.m";
+include "sh.m";
+include "alphabet/reports.m";
+
+Reporter: adt {
+ id: int;
+ name: string;
+ stopc: chan of int;
+};
+
+reportproc(errorc: chan of string, stopc: chan of int, reply: chan of ref Report)
+{
+ if(sys == nil)
+ sys = load Sys Sys->PATH;
+ r := ref Report(chan of (string, chan of string, chan of int), chan of int);
+ if(stopc == nil)
+ stopc = chan of int;
+ else
+ sys->pctl(Sys->NEWPGRP, nil);
+ reply <-= r;
+ reportproc0(stopc, errorc, r.startc, r.enablec);
+}
+
+Report.start(r: self ref Report, name: string): chan of string
+{
+ if(r == nil)
+ return nil;
+ errorc := chan of string;
+ r.startc <-= (name, errorc, nil);
+ return errorc;
+}
+
+Report.add(r: self ref Report, name: string, errorc: chan of string, stopc: chan of int)
+{
+ r.startc <-= (name, errorc, stopc);
+}
+
+Report.enable(r: self ref Report)
+{
+ r.enablec <-= 0;
+}
+
+reportproc0(
+ stopc: chan of int,
+ reportc: chan of string,
+ startc: chan of (string, chan of string, chan of int),
+ enablec: chan of int
+ )
+{
+ realc := array[2] of chan of string;
+ p := array[len realc] of Reporter;
+ a := array[0] of chan of string;
+ id := n := 0;
+ stopped := 0;
+out:
+ for(;;) alt{
+ <-stopc =>
+ stopped = 1;
+ break out;
+ (prefix, c, stop) := <-startc =>
+ if(n == len realc){
+ if(realc == a)
+ a = nil;
+ realc = (array[n * 2] of chan of string)[0:] = realc;
+ p = (array[n * 2] of Reporter)[0:] = p;
+ if(a == nil)
+ a = realc;
+ }
+ realc[n] = c;
+ p[n] = (id++, prefix, stop);
+ n++;
+ <-enablec =>
+ if(n == 0)
+ break out;
+ a = realc;
+ (x, msg) := <-a =>
+ if(msg == nil){
+ if(--n == 0)
+ break out;
+ if(n != x){
+ a[x] = a[n];
+ a[n] = nil;
+ p[x] = p[n];
+ p[n] = (-1, nil, nil);
+ }
+ }else{
+ if(reportc != nil){
+ alt{
+ reportc <-= sys->sprint("%d. %s: %s", p[x].id, p[x].name, msg) =>
+ ;
+ <-stopc =>
+ stopped = 1;
+ break out;
+ }
+ }
+ }
+ }
+ if(stopped == 0){
+ if(reportc != nil){
+ alt{
+ reportc <-= nil =>
+ ;
+ <-stopc =>
+ stopped = 1;
+ }
+ }
+ }
+ if(stopped){
+ for(i := 0; i < n; i++)
+ note(p[i].stopc);
+ note(stopc);
+ }
+}
+
+quit(errorc: chan of string)
+{
+ if(errorc != nil)
+ errorc <-= nil;
+ exit;
+}
+
+report(errorc: chan of string, err: string)
+{
+ if(errorc != nil)
+ errorc <-= err;
+}
+
+newpgrp(stopc: chan of int, flags: int): chan of int
+{
+ if(sys == nil)
+ sys = load Sys Sys->PATH;
+ if(flags&PROPAGATE){
+ if(stopc == nil)
+ stopc = chan[1] of int;
+ sys->pipe(p := array[2] of ref Sys->FD);
+ spawn deadman(p[1]);
+ sys->pctl(Sys->NEWPGRP, nil);
+ spawn watchproc(p[0], stopc);
+ }else
+ sys->pctl(Sys->NEWPGRP, nil);
+ spawn grpproc(stopc, newstopc := chan[1] of int, flags&KILL);
+ return newstopc;
+}
+
+grpproc(noteparent, noteself: chan of int, kill: int)
+{
+ if(noteparent == nil)
+ noteparent = chan of int;
+ alt{
+ <-noteparent =>
+ note(noteparent);
+ <-noteself =>
+ ;
+ }
+ note(noteself);
+ if(kill){
+ pid := sys->pctl(0, nil);
+ fd := sys->open("#p/"+string pid+"/ctl", Sys->OWRITE);
+ if(fd == nil)
+ fd = sys->open("/prog/"+string pid+"/ctl", Sys->OWRITE);
+ sys->fprint(fd, "killgrp");
+ }
+}
+
+note(c: chan of int)
+{
+ if(c != nil){
+ alt {
+ c <-= 1 =>
+ ;
+ * =>
+ ;
+ }
+ }
+}
+
+deadman(nil: ref Sys->FD)
+{
+ <-chan of int;
+}
+
+watchproc(fd: ref Sys->FD, stopc: chan of int)
+{
+ sys->read(fd, array[1] of byte, 1);
+ note(stopc);
+}