summaryrefslogtreecommitdiff
path: root/appl/alphabet/main/filter.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/alphabet/main/filter.b')
-rw-r--r--appl/alphabet/main/filter.b114
1 files changed, 114 insertions, 0 deletions
diff --git a/appl/alphabet/main/filter.b b/appl/alphabet/main/filter.b
new file mode 100644
index 00000000..f532f529
--- /dev/null
+++ b/appl/alphabet/main/filter.b
@@ -0,0 +1,114 @@
+implement Filter, Mainmodule;
+include "sys.m";
+ sys: Sys;
+include "draw.m";
+include "sh.m";
+ sh: Sh;
+ Context: import sh;
+include "bufio.m";
+ bufio: Bufio;
+ Iobuf: import bufio;
+include "alphabet/reports.m";
+ reports: Reports;
+ Report, report: import reports;
+include "alphabet.m";
+ alphabet: Alphabet;
+ Value: import alphabet;
+
+Filter: module {};
+
+typesig(): string
+{
+ return "ffcs*"; # XXX option to suppress stderr?
+}
+
+init()
+{
+ sys = load Sys Sys->PATH;
+ alphabet = load Alphabet Alphabet->PATH;
+ reports = load Reports Reports->PATH;
+ bufio = load Bufio Bufio->PATH;
+ sh = load Sh Sh->PATH;
+ sh->initialise();
+}
+
+quit()
+{
+}
+
+run(drawctxt: ref Draw->Context, report: ref Reports->Report, nil: chan of string,
+ nil: list of (int, list of ref Value),
+ args: list of ref Value): ref Value
+{
+ f := chan of ref Sys->FD;
+ a: list of ref Sh->Listnode;
+ for(al := tl tl args; al != nil; al = tl al)
+ a = ref Sh->Listnode(nil, (hd al).s().i) :: a;
+ spawn filterproc(drawctxt, (hd args).f().i, f, (hd tl args).c().i, rev(a), report.start("filter"));
+ return ref Value.Vf(f);
+}
+
+filterproc(drawctxt: ref Draw->Context,
+ f0,
+ f1: chan of ref Sys->FD,
+ c: ref Sh->Cmd,
+ args: list of ref Sh->Listnode,
+ errorc: chan of string)
+{
+ (fd0, fd1) := startfilter(f0, f1, errorc);
+ sys->pipe(p := array[2] of ref Sys->FD);
+ spawn stderrproc(p[0], errorc);
+ p[0] = nil;
+
+ # i hate this stuff.
+ sys->pctl(Sys->FORKFD, nil);
+ sys->dup(fd0.fd, 0);
+ sys->dup(fd1.fd, 1);
+ sys->dup(p[1].fd, 2);
+ fd0 = fd1 = nil;
+ p = nil;
+ sys->pctl(Sys->NEWFD, 0::1::2::nil);
+ Context.new(drawctxt).run(ref Sh->Listnode(c, nil)::args, 0);
+ sys->fprint(sys->fildes(2), "");
+}
+
+# read side (when it's an argument):
+# read proposed new fd
+# write actual fd for them to write to (creating pipe in necessary)
+#
+# write side (when you're returning it):
+# write a proposed new fd (or nil if no suggestion)
+# read actual fd for writing
+startfilter(f0, f1: chan of ref Sys->FD, errorc: chan of string): (ref Sys->FD, ref Sys->FD)
+{
+ f1 <-= nil;
+ if((fd1 := <-f1) == nil){
+ <-f0;
+ f0 <-= nil;
+ reports->quit(errorc);
+ }
+ if((fd0 := <-f0) == nil){
+ sys->pipe(p := array[2] of ref Sys->FD);
+ f0 <-= p[1];
+ fd0 = p[0];
+ }else
+ f0 <-= nil;
+ return (fd0, fd1);
+}
+
+stderrproc(fd: ref Sys->FD, errorc: chan of string)
+{
+ iob := bufio->fopen(fd, Sys->OREAD);
+ while((s := iob.gets('\n')) != nil)
+ if(len s > 1)
+ errorc <-= s[0:len s - 1];
+ errorc <-= nil;
+}
+
+rev[T](l: list of T): list of T
+{
+ r: list of T;
+ for(; l != nil; l = tl l)
+ r = hd l :: r;
+ return r;
+} \ No newline at end of file