DEFINITION MODULE Streams;
(*
  Module:	Stream Input/Output
  Author:	Ceriel J.H. Jacobs
  Version:	$Header$

 * This module provides sequential IO through streams.
 * A stream is either a text stream or a binary stream, and is either in
 * reading, writing or appending mode.
 * By default, there are three open text streams, connected to standard input,
 * standard output, and standard error respectively.
 * These are text streams.
 * When connected to a terminal, the standard output and standard error
 * streams are linebuffered.
 * The user can create more streams with the OpenStream call, and
 * delete streams with the CloseStream call.
 * Streams are automatically closed at program termination.
 *)

  FROM SYSTEM IMPORT BYTE;

  TYPE	StreamKind = (text, binary, none);
	StreamMode = (reading, writing, appending);
	StreamResult = (succeeded, illegaloperation,
			nomemory, openfailed, nostream, endoffile);
	StreamBuffering = (unbuffered, linebuffered, blockbuffered);
  TYPE	Stream;

  VAR	InputStream, OutputStream, ErrorStream: Stream;

  PROCEDURE OpenStream(VAR stream: Stream;
		       filename: ARRAY OF CHAR; 
		       kind: StreamKind;
		       mode: StreamMode;
		       VAR result: StreamResult);
  (* Associates a stream with the file named filename.
     If kind = none, result is set to illegaloperation.
     mode has one of the follwing values:
       reading:		the file is opened for reading
       writing:		the file is truncated or created for writing
       appending:	the file is opened for writing at end of file,
			or created for writing.
     On failure, result is set to openfailed.
     On success, result is set to succeeded.
  *)

  PROCEDURE SetStreamBuffering( stream: Stream;
				b: StreamBuffering;
				VAR result: StreamResult);
  (* This procedure is only allowed for output streams.
     The three types of buffering available are unbuffered, linebuffered,
     and blockbuffered. When an output stream is unbuffered, the output
     appears as soon as written; when it is blockbuffered, output is saved
     up and written as a block; When it is linebufferded (only possible for
     text output streams), output is saved up until a newline is encountered
     or input is read from standard input.
  *)

  PROCEDURE CloseStream(VAR stream: Stream; VAR result: StreamResult);
  (* Closes the stream.
     result is set to nostream if "stream" was not associated with a stream.
  *)

  PROCEDURE FlushStream(stream: Stream; VAR result: StreamResult);
  (* Flushes the stream.
     result is set to nostream if "stream" was not associated with a stream.
     It is set to illegaloperation if "stream" is not an output or
     appending stream.
  *)

  PROCEDURE EndOfStream(stream: Stream; VAR result: StreamResult): BOOLEAN;
  (* Returns true if the stream is an input stream, and the end of the file
     has been reached.
     result is set to nostream if "stream" was not associated with a stream.
     It is set to illegaloperation if the stream is not an input stream.
  *)

  PROCEDURE Read(stream: Stream; VAR ch: CHAR; VAR result: StreamResult);
  (* reads a character from the stream. Certain character translations may
     occur, such as the mapping of the end-of-line sequence to the
     character 12C.
     result is set to nostream if "stream" was not associated with a stream.
     It is set to endoffile if EndOfStream would have returned TRUE before the
     call to Read. In this case, "ch" is set to 0C.
     It is set to illegaloperation if the stream is not a text input stream.
  *)

  PROCEDURE ReadByte(stream: Stream; VAR byte: BYTE; VAR result: StreamResult);
  (* reads a byte from the stream. No character translations occur.
     result is set to nostream if "stream" was not associated with a stream.
     It is set to endoffile if EndOfStream would have returned TRUE before the
     call to ReadByte. In this case, "byte" is set to 0C.
     It is set to illegaloperation if the stream is not a binary input stream.
  *)

  PROCEDURE ReadBytes(stream: Stream;
		      VAR bytes: ARRAY OF BYTE;
		      VAR result: StreamResult);
  (* reads bytes from the stream. No character translations occur.
     The number of bytes is determined by the size of the parameter.
     result is set to nostream if "stream" was not associated with a stream.
     It is set to endoffile if there are not enough bytes left on the stream.
     In this case, the rest of the bytes are set to 0C.
     It is set to illegaloperation if the stream is not a binary input stream.
  *)

  PROCEDURE Write(stream: Stream; ch: CHAR; VAR result: StreamResult);
  (* writes a character to the stream. Certain character translations may
     occur, such as the mapping of a line-feed or carriage return (12C or 15C)
     to the end-of-line sequence of the system.
     result is set to nostream if "stream" was not associated with a stream.
     It is set to illegaloperation if the stream is not a text output stream.
  *)

  PROCEDURE WriteByte(stream: Stream; byte: BYTE; VAR result: StreamResult);
  (* writes a byte to the stream. No character translations occur.
     result is set to nostream if "stream" was not associated with a stream.
     It is set to illegaloperation if the stream is not a binary output stream.
  *)

  PROCEDURE WriteBytes(stream: Stream;
		       bytes: ARRAY OF BYTE;
		       VAR result: StreamResult);
  (* writes bytes to the stream. No character translations occur.
     The number of bytes written is equal to the size of the parameter.
     result is set to nostream if "stream" was not associated with a stream.
     It is set to illegaloperation if the stream is not a binary output stream.
  *)

  PROCEDURE GetPosition(stream: Stream;
			VAR position: LONGINT;
			VAR result: StreamResult);
  (* gives the actual read/write position in "position".
     "result" is set to illegaloperation if "stream" is not a stream.
  *)

  PROCEDURE SetPosition(stream: Stream;
			position: LONGINT;
			VAR result: StreamResult);
  (* sets the actual read/write position to "position".
     "result" is set to nostream if "stream" is not a stream.
     It is set to illegaloperation if the stream was opened for appending and
     the position is in front of the current position, or it failed for some
     other reason (f.i. when the stream is connected to a terminal).
  *)

  PROCEDURE isatty(stream: Stream; VAR result: StreamResult): BOOLEAN;
  (* return TRUE if the stream is connected to a terminal.
     "result" is set to nostream if "stream" is not a stream, and
     set to illegaloperation if the operation failed for some other reason.
  *)

END Streams.
