Page Numbers: Yes First Page: 74 X: 527 Y: 10.5"
Margins: Binding: 13
Odd Heading: Not-on-first-page
Alto/Mesa Streams
Even Heading:
Alto/Mesa Streams
Alto/Mesa Streams
October 1980
Streams provide a standard interface between programs and their sources of sequential input and their sinks for sequential output. A set of standard operations defined for all types of streams is sufficient for all ordinary input-output requirements. In addition, most streams have special (device dependent) operations defined for them; programs which use such operations thereby forfeit complete compatibility.
Streams transmit information in atomic units called items. Usually an item is a CHARACTER or a WORD, and this is the case for most of the streams supplied with Mesa. Of course, a stream supplied to a program must have the same ideas about the kind of item it handles as the program does; otherwise confusion will result. Normally, streams which transmit text use CHARACTER items, and those which transmit binary information use WORDs.
Streams are passed about using StreamHandles, variants of which are produced by the (device dependent) procedures that create streams. A StreamHandle is a pointer to a variant record of type StreamObject, which is defined (in StreamDefs) as follows:
StreamHandle: TYPE = POINTER TO StreamObject;
KeyboardHandle: TYPE = POINTER TO Keyboard StreamObject;
DisplayHandle: TYPE = POINTER TO Display StreamObject;
DiskHandle: TYPE = POINTER TO Disk StreamObject;
StreamObject: TYPE = RECORD [
reset:
PROCEDURE [StreamHandle],
get:
PROCEDURE [StreamHandle] RETURNS [UNSPECIFIED],
putback:
PROCEDURE [StreamHandle, UNSPECIFIED],
put:
PROCEDURE [StreamHandle, UNSPECIFIED],
endof:
PROCEDURE [StreamHandle] RETURNS [BOOLEAN],
destroy:
PROCEDURE [StreamHandle],
link: StreamHandle,
body:
SELECT type: * FROM
Keyboard => . . .
Display => . . .
Disk => . . .
Other => [type:
UNSPECIFIED, data: POINTER],
ENDCASE];
The procedures which create streams return discriminated pointers (a DiskHandle, for example), which can be assigned to variables of type StreamHandle without any loopholes. Most stream procedures (and all of the standard operations) expect StreamHandles (which can be matched by any discriminated pointer); they check at runtime for the appropriate stream type.
Error conditions are reported in a fashion independent of the particular stream type, using the following definitions (not all error codes are applicable to all stream types):
StreamError: SIGNAL [stream: StreamHandle, error: StreamErrorCode];
StreamErrorCode: TYPE = {
StreamType, StreamAccess, StreamOperation,
StreamPosition, StreamEnd, StreamBug};
As the definition implies, each stream object contains procedures that implement the standard stream operations, as described below (s is a StreamHandle, i is an item of the appropriate type, and "code error" means that SIGNAL StreamError[s, code] is raised). For each StreamType, there is a create procedure which returns a StreamHandle. Then, for example, to invoke get for a StreamHandle s, simply say s.get[s].
reset[s]
Restores the stream to some initial state, generally as close as possible to the state it is in just after it is created.
get[s]
Returns the next item; StreamAccess error if s cannot be read or if endof[s] is true before the call.
putback[s, i]
Modifies the stream so that the next get[s] will return i and leave s in the state it was in before the putback.
put[s, i]
Writes i into the stream as the next item; StreamAccess error if the stream cannot be written; StreamEnd error if there is no more space in the stream.
endof[s]
TRUE if there are no more items to be gotten from s. For output streams, endof is device-dependent.
destroy[s]
Destroys s in an orderly way, freeing the space it occupies. Note that this has nothing to do with deleting any underlying data structures or processes associated with the stream (like a disk file, for example, or the keyboard process).
Each of these operations is defined more precisely in the descriptions of the individual stream types which appear in separate sections. All of the stream routines produce the StreamType error when the variant of the StreamObject they are passed is not what they are expecting. See the Disk Streams, Display, and Keyboard sections for details of specific stream types.
The Other variant of a StreamObject is provided so that clients can easily provide other types of streams using the same standard set of operations. The data field of an Other StreamObject should point to any additional data required by the particular stream. Clients with more than one type of Other stream should include a type code in the type field.