Oberon || Library || Module Index || Search Engine || Definition || Module
TYPE Filter = PROCEDURE (in, out: Streams.Stream); TYPE CrPipe = POINTER TO CrPipeRec; TYPE CrPipeRec = RECORD (Streams.StreamRec) END; PROCEDURE Open(VAR out, in: Streams.Stream; bufmode: Streams.BufMode); PROCEDURE Spawn(filter: Filter; in, out: Streams.Stream);
Open creates a pipeline with two streams (similar to pipe(2)). Both streams remain unconnected until they are connected to filters by Spawn. Input/output operations to unconnected pipeline streams are illegal. Transfer of control mainly depends on the buffering mode of the inner streams:
Spawn passes in and out to filter and starts the procedure as coroutine. At least one of the two streams should be a pipeline stream. Pipeline streams which are passed to Spawn are connected to filter. Pipeline constructions must be linear: cycles would cause deadlocks.
The pipeline starts working either by reading from the end or by writing to the start of the pipeline. A filter has three ways of returning/closing:
PROCEDURE UpperToLower(in, out: Streams.Stream);
CONST diff = ORD("a") - ORD("A");
VAR ch: CHAR;
BEGIN
WHILE Streams.ReadByte(in, ch) DO
IF (ch >= "A") & (ch <= "Z") THEN
ch := CHR(ORD(ch) - diff);
END;
IF ~Streams.WriteByte(out, ch) THEN
RETURN
END;
END;
END UpperToLower;
PROCEDURE Setup;
VAR
out, in: Streams.Stream;
oldstdout: Streams.Stream;
BEGIN
CrPipes.Open(out, in, Streams.linebuf);
oldstdout := Streams.stdout;
Streams.stdout := out;
CrPipes.Spawn(UpperToLower, in, oldstdout);
END Setup;
Oberon || Library || Module Index || Search Engine || Definition || Module