DEFINITION extPipes; (*Procedures for executing commands and reading their output or writing their input*) TYPE Stream = POINTER TO RECORD eof: BOOLEAN END; PROCEDURE OpenRead(command: ARRAY OF CHAR; VAR stream: Stream); (*OpenRead(c, s) executes the command specified by c and creates a pipeline between the calling program and the executed command. If opening the stream was successful, s is set to the the standard output stream of the command. If opening the stream failed, s is set to NIL.*) PROCEDURE OpenWrite(command: ARRAY OF CHAR; VAR stream: Stream); (*OpenWrite(c, s) executes the command specified by c and creates a pipeline between the calling program and the executed command. If opening the stream was successful, s is set to the the standard input stream of the command. If opening the stream failed, s is set to NIL.*) PROCEDURE Read(stream: Stream; VAR ch: CHAR); (*Read(s, ch) reads the next character from s and returns it in ch. The field s.eof is set to TRUE if an attempt was made to read beyond the end of the file.*) PROCEDURE Write(ch: CHAR; stream: Stream); (*Write(ch, s) writes ch to s. The field s.eof is set to TRUE if the operation was not successful.*) PROCEDURE Close(stream: Stream; VAR exitCode: INTEGER); (*Close(s, c) closes the stream s that was opened by OpenRead or OpenWrite. Output parameter c is assigned the exit code of the command language interpreter which executed the command, or -1 if closing the stream failed.*) (*Example: MODULE listfiles; IMPORT Err := extErr, Out, Pipes := extPipes; VAR stream: Pipes.Stream; ch: CHAR; exitCode: INTEGER; BEGIN Pipes.OpenRead("ls", stream); IF stream # NIL THEN Pipes.Read(stream, ch); WHILE ~stream.eof DO Out.Char(ch); Pipes.Read(stream, ch) END; Pipes.Close(stream, exitCode); IF exitCode > 0 THEN Err.String("command 'ls' failed"); Err.Ln; ASSERT(FALSE) END ELSE Err.String("opening a pipe failed"); Err.Ln; ASSERT(FALSE) END END listfiles. *) END extPipes.