# Input/Output

The input/output library defined in this chapter provides facilities for reading and writing of data streams over one or more channels. Channels are connected to sources of input data, or to destinations of output data, known as devices or device instances. There is a separation between modules that are concerned with device-independent operations, such as reading and writing, and modules concerned with device-dependent operations, such as making connections to named files. This separation allows the library to be extended to work with new devices. The module structure of the library is depicted in the following figure.

The figure will be available in the final release

Channels already open to standard sources and destinations can be identified using procedures provided by the module `StdChans`. This module also provides for the identification and selection of channels used by default for input and output operations.

The modules `TextIO`, `WholeIO`, `RealIO`, and `LongIO`, provide facilities that allow the reading and writing of high-level units of data, using text operations on channels specified explicitly by a parameter. These high-level units include characters, strings, and whole numbers and real numbers in decimal notation. The module `RawIO` provides facilities for reading and writing of arbitrary data types, using raw (binary) operations on explicitly specified channels.

Text operations produce or consume data streams as sequences of characters and line marks. Raw operations produce or consume data streams as sequences of storage locations (i.e. as arrays whose component type is `SYSTEM.LOC`).

The library allows devices to support both text and raw operations on a single channel, although this behaviour is not required.

The module `IOResult` provides the facility for a program to determine whether the last operation to read data from a specified input channel found data in the required format.

Corresponding to the `TextIO` group of modules is a group of modules `STextIO`, `SWholeIO`, `SRealIO`, `SLongIO`, `SRawIO` and `SIOResult`. The prefix `"S"` serves as an abbreviation for `"Simple"`. The procedures exported from this group do not take parameters identifying a channel. They operate on the default input and output channels, as identified by the module `StdChans`.

The module `IOConsts` defines types and constants used by `IOResult` and `SIOResult`.

The device modules `StreamFile`, `SeqFile`, `RndFile`, and `TermFile` provide facilities that allow a channel to be opened to a named stream, to a rewindable sequential file, to a random access file, or to a terminal device respectively. The device module `ProgramArgs` provides an open channel from which program arguments may be read. Device specific operations, such as positioning within a random access file, are also defined by the appropriate device module.

The module `ChanConsts` defines the constants and types used in those device module procedures that open channels.

The primitive device-independent operations on channels are provided by the module `IOChan`.

The module `IOChan` defines general input/output library exception values that may be raised when using any device through a channel. Device errors, such as a hardware read/write error, are reported by raising one of the general exception values, and providing an implementation-defined error number. Exception values associated with device- specific operations are defined by the appropriate device module.

The module `IOLink` provides facilities that allow a user to provide further specialized device modules for use with channels, following the pattern of the rest of the library.

NOTE:

Partial implementations of the input/output library may provide modules selected exclusively from the group `STextIO`, `SWholeIO`, `SRealIO`, and `SLongIO`, normally with `SIOResult` and `IOConsts`. If any other module is provided, the module `IOChan` must also be provided, in accordance with the import dependencies between the definition modules of the library.

- Standard and Default Channels
- Reading and Writing of Data
- Device-Independent Channel Operations
- Obtaining Channels from Device Modules
- Interface to Channels for New Device Modules

## Standard and Default Channels

Standard channels do not have to be opened by a client program since they are already open and ready for use. Under some operating systems they may be connected to sources and destinations specified before the program is run, while on a stand-alone system they may be connected to a console terminal.

No method is provided for closing a standard channel, and the values used to identify standard channels are constant throughout the execution of the program.

Default channels are channels whose identities have been stored as those to be used by default for input and output operations. Initially these correspond to the standard channels, but their values may be varied to obtain the effect of redirection.

- Module StdChans

### Module StdChans

The module `StdChans` defines functions that identify channels already open to implementation-defined sources and destinations of standard input, standard output, and standard error output. Access to a `null device' is provided to allow unwanted output to be suppressed. The null device throws away all data written to it, and gives an immediate end of input indication on reading.

The module `StdChans` provides procedures for identification and selection of the channels used by default for input and output operations.

- ChanID - Channel identity
- StdInChan - Get standard input channel id
- StdOutChan - Get standard output channel id
- StdErrChan - Get standard error channel id
- NullChan - Get null device channel id
- InChan - Get current default input channel id
- OutChan - Get current default output channel id
- ErrChan - Get current default error channel id
- SetInChan - Set current default input channel
- SetOutChan - Set current default output channel
- SetErrChan - Set current default output channel

#### ChanID - Channel identity

    TYPE
      ChanId = IOChan.ChanId;

Module `StdChans`

The type `IOChan.ChanId` which is used to identify channels is reexported.

#### StdInChan - Get standard input channel id

    PROCEDURE StdInChan (): ChanId;

Module `StdChans`

The function procedure `StdInChan` returns a value identifying a channel open to the implementation-defined standard source for program input.

#### StdOutChan - Get standard output channel id

    PROCEDURE StdOutChan (): ChanId;

Module `StdChans`

The function procedure `StdOutChan` returns a value identifying a channel open to the implementation-defined standard destination for program output.

#### StdErrChan - Get standard error channel id

    PROCEDURE StdErrChan (): ChanId;

Module `StdChans`

The function procedure `StdErrChan` returns a value identifying a channel open to the implementation-defined standard destination for program error messages.

#### NullChan - Get null device channel id

    PROCEDURE NullChan (): ChanId;

Module `StdChans`

The function procedure `NullChan` returns a value identifying a channel open to the null device.

NOTE:

The null device supports all operations by discarding all data written to it, or by giving an immediate end of input indication on reading.

#### InChan - Get current default input channel id

    PROCEDURE InChan (): ChanId;

Module `StdChans`

The function procedure `InChan` returns the identity of the current default input channel. This is the channel used by input procedures that do not take a channel parameter. Initially this is the value returned by `StdInChan`.

#### OutChan - Get current default output channel id

    PROCEDURE OutChan (): ChanId;

Module `StdChans`

The function procedure `OutChan` returns the identity of the current default output channel. This is the channel used by output procedures that do not take a channel parameter. Initially this is the value returned by `StdOutChan`.

#### ErrChan - Get current default error channel id

    PROCEDURE ErrChan (): ChanId;

Module `StdChans`

The function procedure `ErrChan` returns the identity of the current default output channel for program error messages. Initially this is the value returned by `StdErrChan`.

#### SetInChan - Set current default input channel

    PROCEDURE SetInChan (cid: ChanId);

Module `StdChans`

The procedure `SetInChan` sets the current default input channel to that identified by `cid`.

#### SetOutChan - Set current default output channel

    PROCEDURE SetOutChan (cid: ChanId);

Module `StdChans`

The procedure `SetOutChan` sets the current default output channel to that identified by `cid`.

#### SetErrChan - Set current default output channel

    PROCEDURE SetErrChan (cid: ChanId);

Module `StdChans`

The procedure `SetErrChan` sets the current default output channel for error messages to that identified by `cid`.

## Reading and Writing of Data

The module `TextIO` provides facilities for input and output of characters, character strings, and line marks, using text operations.

The module `WholeIO` provides facilities for input and output of whole numbers in decimal text form.

The modules `RealIO` and `LongIO` provide facilities for input and output of real numbers in decimal text form.

The module `RawIO` provides facilities for direct input and output of data, using raw operations (i.e. without any interpretation).

The input procedures of the modules `TextIO`, `WholeIO`, `RealIO`, `LongIO`, and `RawIO` are sufficient for use where the format of the input data is known. Since, in practice, their use may be inconsistent with the format of the input data, they have the effect of setting a `read result' for the used channel. The module `IOResult` provides the facility for obtaining the read result applicable to the most recent input operation on a given channel.

In all cases, channels are selected explicitly by passing an actual parameter of the type `ChanId` to the procedures of these modules.

The modules `STextIO`, `SWholeIO`, `SRealIO`, `SLongIO`, `SRawIO`, and `SIOResult` provide the set of similar procedures set that operate over default input and output channels, and so do not take a parameter identifying a channel.

- Modules TextIO and STextIO
- Modules WholeIO and SWholeIO
- Modules RealIO, SRealIO, LongIO, and SLongIO
- Modules RawIO and SRawIO
- Module IOConsts
- Modules IOResult and SIOResult

### Modules TextIO and STextIO

The module `TextIO` provides facilities for input and output of characters, character strings, and line marks, using text operations.

The procedures of the module `STextIO` behave as the corresponding procedures of the module `TextIO`, except that input is taken from the default input channel, and output is sent to the default output channel.

- ReadChar - Read a character
- ReadRestLine - Read rest of line
- ReadString - Read a string
- ReadToken - Read a space-delimited token
- SkipLine - Skip rest of input line
- WriteChar - Write a character
- WriteLn - Write a line mark
- WriteString - Write a string

#### ReadChar - Read a character

    PROCEDURE ReadChar (cid: IOChan.ChanId; VAR ch: CHAR);
    PROCEDURE ReadChar (VAR ch: CHAR);

Modules: `TextIO`, `STextIO`

If there is a character next in the input stream identified by `cid`, the procedure `ReadChar` removes it from the stream and assigns its value to `ch`; otherwise the value of `ch` is not defined. The read result for the channel is set to the value

`allRight`
  if a character is read;
`endOfLine`
  if no character is read, the next item being a line mark;
`endOfInput`
  if no character is read, the input stream having ended.

#### ReadRestLine - Read rest of line

    PROCEDURE ReadRestLine (cid: IOChan.ChanId;
                            VAR s: ARRAY OF CHAR);
    PROCEDURE ReadRestLine (VAR s: ARRAY OF CHAR);

Modules: `TextIO`, `STextIO`

If there is a character next in the input stream identified by `cid`, the procedure `ReadRestLine` reads a string of characters; reading continues as long as there are still characters before the next line mark or the end of the stream. As much of the string as can be accommodated is copied to `s` as a string value. The read result for the channel is set to the value

`allRight`
  if `s` is not empty and accomodates all of the string that has been read;
`outOfRange`
  if `s` is not empty but does not accommodate all of the string;
`endOfLine`
  if `s` is empty, the next item being a line mark;
`endOfInput`
  if `s` is empty, the input stream having ended.

#### ReadString - Read a string

    PROCEDURE ReadString (cid: IOChan.ChanId;
                          VAR s: ARRAY OF CHAR);
    PROCEDURE ReadString (VAR s: ARRAY OF CHAR);

Modules: `TextIO`, `STextIO`

If there is a character next in the input stream identified by `cid`, the procedure `ReadString` reads a string of characters; reading continues as long as there are still characters before the next line mark or the end of the stream and the capacity of `s` has not been exhausted. The string is copied to `s` as a string value. The read result for the channel is set to the value

`allRight`
  if `s` is not empty;
`endOfLine`
  if `s` is empty, the next item being a line mark;
`endOfInput`
  if `s` is empty, the input stream having ended.

#### ReadToken - Read a space-delimited token

    PROCEDURE ReadToken (cid: IOChan.ChanId;
                         VAR s: ARRAY OF CHAR);
    PROCEDURE ReadToken (VAR s: ARRAY OF CHAR);

Modules: `TextIO`, `STextIO`

The procedure `ReadToken` first skips any leading spaces in the input stream identified by `cid`. If the next item is a character, a string of characters is read; reading continues as long as there are still non-space characters before the next line mark or the end of the stream. As much of the string as can be accommodated is copied to `s` as a string value. The read result for the channel is set to the value

`allRight`
  if `s` is not empty and accomodates all of the string that has been read;
`outOfRange`
  if `s` is not empty but does not accommodate all of the string;
`endOfLine`
  if `s` is empty, the next item being a line mark;
`endOfInput`
  if `s` is empty, the input stream having ended.

#### SkipLine - Skip rest of input line

    PROCEDURE SkipLine (cid: IOChan.ChanId);
    PROCEDURE SkipLine ();

Modules: `TextIO`, `STextIO`

The procedure `SkipLine` reads successive items from the input stream identified by `cid` up to and including the next line mark, or until the end of the stream is reached.

The read result for the channel is set to the value

`allRight`
  if a line mark is read;
`endOfInput`
  if no line mark is read, the input stream having ended.

#### WriteChar - Write a character

    PROCEDURE WriteChar (cid: IOChan.ChanId; ch: CHAR);
    PROCEDURE WriteChar (ch: CHAR);

The procedure `WriteChar` writes the character `ch` to the output stream identified by `cid`.

#### WriteLn - Write a line mark

    PROCEDURE WriteLn (cid: IOChan.ChanId);
    PROCEDURE WriteLn ();

Modules: `TextIO`, `STextIO`

The procedure `WriteLn` writes a line mark to the output stream identified by `cid`.

#### WriteString - Write a string

    PROCEDURE WriteString (cid: IOChan.ChanId;
                           s: ARRAY OF CHAR);
    PROCEDURE WriteString (s: ARRAY OF CHAR);

Modules: `TextIO`, `STextIO`

The procedure `WriteString` writes the string value in `s` to the output stream identified by `cid`.

### Modules WholeIO and SWholeIO

The module `WholeIO` provides facilities for input and output of whole numbers in decimal text form.

The text form of a signed whole number is

    ["+" | "-"], decimal digit, {decimal digit}

The text form of an unsigned whole number is

    decimal digit, {decimal digit}

The procedures of the module `SWholeIO` behave as the corresponding procedures of the module `WholeIO`, except that input is taken from the default input channel, and output is sent to the default output channel.

- ReadInt - Read an INTEGER value
- WriteInt - Write an INTEGER value
- ReadCard - Read a CARDINAL value
- WriteCard - Write a CARDINAL value

#### ReadInt - Read an INTEGER value

    PROCEDURE ReadInt (cid: IOChan.ChanId;
                       VAR int: INTEGER);
    PROCEDURE ReadInt (VAR int: INTEGER);

Modules: `WholeIO`, `SWholeIO`

The procedure `ReadInt` skips any leading spaces from the input stream identified by `cid`, and then reads characters that form a signed whole number. The read result for the channel is set to the value

`allRight`
  if a signed whole number is read, and its value is in the range of the type `INTEGER`; the value of this number is assigned to `int`;
`outOfRange`
  if a signed whole number is read, but its value is out of range of the type `INTEGER`; the value `MAX(INTEGER)` or `MIN(INTEGER)` is assigned to `int` according to the sign of the number;

`wrongFormat`
  if there are characters read or to be read, but these are not in the format of a signed whole number; the value of `int` is not defined;

`endOfLine`
  if no characters are read, the next item being a line mark; the value of `int` is not defined;

`endOfInput`
  if no characters are read, the input having ended; the value of `int` is not defined.

#### WriteInt - Write an INTEGER value

    PROCEDURE WriteInt (cid: IOChan.ChanId;
                        int: INTEGER;
                        width: CARDINAL);
    PROCEDURE WriteInt (int: INTEGER;
                        width: CARDINAL);

Modules: `WholeIO`, `SWholeIO`

The procedure `WriteInt` writes the value of `int` to the output stream identified by `cid` in text form, with leading spaces as required to make the number of characters written at least that given by `width`. A sign is written only for negative values. In the special case of a value of zero for `width`, exactly one leading space is written.

#### ReadCard - Read a CARDINAL value

    PROCEDURE ReadCard (cid: IOChan.ChanId;
                        VAR card: CARDINAL);
    PROCEDURE ReadCard (VAR card: CARDINAL);

Modules: `WholeIO`, `SWholeIO`

The procedure `ReadCard` skips any leading spaces from the input stream identified by `cid`, and then reads characters that form an unsigned whole number. The read result for the channel is set to the value

`allRight`
  if an unsigned whole number is read, and its value is in the range of the type `CARDINAL`; the value of the number is assigned to `card`;

`outOfRange`
  if a signed whole number is read, but its value is out of range of the values of the type `CARDINAL`; the value `MAX(CARDINAL)` is assigned to `card`;

`wrongFormat`
  if there are characters read or to be read, but these are not in the format of an unsigned whole number; the value of `card` is not defined;

`endOfLine`
  if no characters are read, the next item being a line mark; the value of `card` is not defined;

`endOfInput`
  if no characters are read, the input having ended; the value of `card` is not defined.

#### WriteCard - Write a CARDINAL value

    PROCEDURE WriteCard (cid: IOChan.ChanId;
                         card: CARDINAL;
                         width: CARDINAL);
    PROCEDURE WriteCard (card: CARDINAL;
                         width: CARDINAL);

Modules: `WholeIO`, `SWholeIO`

The procedure `WriteCard` writes the value of `card` to the output stream identified by `cid` in text form, with leading spaces as required to make the number of characters written at least that given by `width`. In the special case of a value of zero for `width`, exactly one leading space is written.

### Modules RealIO, SRealIO, LongIO, and SLongIO

The modules `RealIO` and `LongIO` provide facilities for input and output of real numbers in decimal text form.

In the case of `RealIO`, real number parameters are of the type `REAL`. In the case of `LongIO`, real number parameters are of the type `LONGREAL`.

The semantics of the two modules are the same, except that when module `RealIO` refers to real number values, these values are of the type `REAL`, and when module `LongIO` refers to real number values, these values are of the type `LONGREAL`.

NOTE:

The above statement is merely to avoid needless repetition of the semantics for the two modules.

The text form of a signed fixed-point real number is

    ["+" | "-"], decimal digit, {decimal digit},
    [".", {decimal digit}]

The text form of a signed floating-point real number is

    signed fixed-point real number,
    "E"|"e", ["+" | "-"], decimal digit, {decimal digit}

The procedures of the module `SRealIO` behave as the corresponding procedures of the module `RealIO`, except that input is taken from the default input channel, and output is sent to the default output channel.

The procedures of the module `SLongIO` behave as the corresponding procedures of the module `LongIO`, except that input is taken from the default input channel, and output is sent to the default output channel.

- ReadReal - Read a real value
- WriteFloat - Write a real value in floating-point format
- WriteEng - Write a real value in engineering format
- WriteFixed - Write a real value in fixed-point format
- WriteReal - Write a real value

#### ReadReal - Read a real value

    PROCEDURE ReadReal (cid: IOChan.ChanId;
                        VAR real: REAL);
    PROCEDURE ReadReal (cid: IOChan.ChanId;
                        VAR real: LONGREAL);
    PROCEDURE ReadReal (VAR real: REAL);
    PROCEDURE ReadReal (VAR real: LONGREAL);

Modules: `RealIO`, `SRealIO`, `LongIO`, `SLongIO`

The procedure `ReadReal` skips any leading spaces from the input stream identified by `cid`, and then reads characters that form a signed fixed or floating point number. The read result for the channel is set to the value

`allRight`
  if a signed real number is read, and its value is in the range of the type of `real`; the value of this number is assigned to `real`;

`outOfRange`
  if a signed real number is read, but its value is out of range of the type of `real`; the maximum or minimum value of the type of `real` is assigned to `real` according to the sign of the number;

`wrongFormat`
  if there are characters read or to be read, but these characters are not in the format of a signed real number; the value of `real` is not defined;

`endOfLine`
  if no characters are read, the next item being a line mark; the value of `real` is not defined;

`endOfInput`
  if no characters are read, the input having ended; the value of `real` is not defined.

#### WriteFloat - Write a real value in floating-point format

    PROCEDURE WriteFloat (cid: IOChan.ChanId;
                          real: REAL;
                          sigFigs: CARDINAL;
                          width: CARDINAL);
    PROCEDURE WriteFloat (cid: IOChan.ChanId;
                          real: LONGREAL;
                          sigFigs: CARDINAL;
                          width: CARDINAL);
    PROCEDURE WriteFloat (real: REAL;
                          sigFigs: CARDINAL;
                          width: CARDINAL);
    PROCEDURE WriteFloat (real: LONGREAL;
                          sigFigs: CARDINAL;
                          width: CARDINAL);

Modules: `RealIO`, `SRealIO`, `LongIO`, `SLongIO`

The procedure `WriteFloat` writes the value of `real` to the output stream identified by `cid` in floating-point text form, with leading spaces as required to make the number of characters written at least that given by `width`. A sign is written only for negative values. In the special case of a value of zero for `width`, exactly one leading space is written.

One significant digit is included in the whole number part. The signed exponent part is included only if the exponent value is not zero. If the value of `sigFigs` is greater than zero, that number of significant digits is included, otherwise an implementation-defined number of significant digits is included. The decimal point is not included if there are no significant digits in the fractional part.

The following table gives examples of output by `WriteFloat`:

``

sigFigs | `3923009` | `39.23009` | `0.0003923009`
`1` | `4E+6` | `4E+1` | `4E-4`
`2` | `3.9E+6` | `3.9E+1` | `3.9E-4`
`5` | `3.9230E+6` | `3.9230E+1` | `3.9230E-4`

#### WriteEng - Write a real value in engineering format

    PROCEDURE WriteEng (cid: IOChan.ChanId;
                        real: REAL;
                        sigFigs: CARDINAL;
                        width: CARDINAL);
    PROCEDURE WriteEng (cid: IOChan.ChanId;
                        real: LONGREAL;
                        sigFigs: CARDINAL;
                        width: CARDINAL);
    PROCEDURE WriteEng (real: REAL;
                        sigFigs: CARDINAL;
                        width: CARDINAL);
    PROCEDURE WriteEng (real: LONGREAL;
                        sigFigs: CARDINAL;
                        width: CARDINAL);

Modules: `RealIO`, `SRealIO`, `LongIO`, `SLongIO`

The procedure `WriteEng` behaves as the procedure `WriteFloat` except that the number is scaled with one to three digits in the whole number part, and with an exponent that is a multiple of three.

The following table gives examples of output by `WriteEng`:

``

sigFigs | `3923009` | `39.23009` | `0.0003923009`
`1` | `4E+6` | `40` | `400E-6`
`2` | `3.9E+6` | `39` | `390E-6`
`5` | `3.9230E+6` | `39.230` | `392.30E-6`

#### WriteFixed - Write a real value in fixed-point format

    PROCEDURE WriteFixed (cid: IOChan.ChanId;
                          real: REAL;
                          place: INTEGER;
                          width: CARDINAL);
    PROCEDURE WriteFixed (cid: IOChan.ChanId;
                          real: LONGREAL;
                          place: INTEGER;
                          width: CARDINAL);
    PROCEDURE WriteFixed (real: REAL;
                          place: INTEGER;
                          width: CARDINAL);
    PROCEDURE WriteFixed (real: LONGREAL;
                          place: INTEGER;
                          width: CARDINAL);

Modules: `RealIO`, `SRealIO`, `LongIO`, `SLongIO`

The procedure `WriteFixed` writes the value of `real` to the output stream identified by `cid` in fixed-point text form with leading spaces as required to make the number of characters written at least that given by `width`. A sign is written only for negative values. In the special case of a value of zero for `width`, exactly one leading space is written.

At least one digit is included in the whole number part. The value is rounded to the given value of `place` relative to the decimal point. The decimal point is suppressed if `place` is less than zero.

The following table gives examples of output by `WriteFixed`:

``

places | `3923009` | `39.23009` | `0.0003923009`
`-5` | `3920000` | `0` | `0`
`-2` | `3923010` | `40` | `0`
`-1` | `3923009` | `39` | `0`
`0` | `3923009.` | `39.` | `0.`
`1` | `3923009.0` | `39.2` | `0.0`
`4` | `3923009.0000` | `39.2301` | `0.0004`

#### WriteReal - Write a real value

    PROCEDURE WriteReal (cid: IOChan.ChanId;
                         real: REAL;
                         width: CARDINAL);
    PROCEDURE WriteReal (cid: IOChan.ChanId;
                         real: LONGREAL;
                         width: CARDINAL);
    PROCEDURE WriteReal (real: REAL;
                         width: CARDINAL);
    PROCEDURE WriteReal (real: LONGREAL;
                         width: CARDINAL);

Modules: `RealIO`, `SRealIO`, `LongIO`, `SLongIO`

If the sign and magnitude of real can be expressed in a field given by `width`, the procedure `WriteReal` behaves as the procedure `WriteFixed`, with a value of `place` chosen to fill exactly the remaining field. Otherwise it behaves as the procedure `WriteFloat`, with a value of `sigFigs` of at least one, limited to those that can be included together with the sign and exponent part in the given `width`.

In the special case of a `width` of zero, the effect is as for the procedure `WriteFloat` with a value of `sigFigs` equal to zero.

### Modules RawIO and SRawIO

The module `RawIO` provides facilities for direct input and output of data using raw operations (i.e. without any interpretation).

The procedures of the module `SRawIO` behave as the corresponding procedures of the module `RawIO`, except that input is taken from the default input channel, and output is sent to the default output channel.

- Read - Read storage units
- Write - Write storage units

#### Read - Read storage units

    PROCEDURE Read (cid: IOChan.ChanId;
                    VAR to: ARRAY OF SYSTEM.LOC);
    PROCEDURE Read (VAR to: ARRAY OF SYSTEM.LOC);

Modules: `RawIO`, `SRawIO`

While the stream identified by `cid` is not exhausted, the procedure `Read` reads successive storage units from that channel, and assign them without interpretation to successive components of `to`. The read result for the channel is set to the value

`allRight`
  if items are read for all components;

`wrongFormat`
  if some items are read, but not for all components;

`endOfInput`
  if no items are read, the input having ended.

#### Write - Write storage units

    PROCEDURE Write (cid: IOChan.ChanId;
                     from: ARRAY OF SYSTEM.LOC);
    PROCEDURE Write (from: ARRAY OF SYSTEM.LOC);

Modules: `RawIO`, `SRawIO`

The procedure `Write` writes successive components of `from` to the channel identified by `cid`, as storage units without interpretation.

### Module IOConsts

The module `IOConsts` defines the enumeration type `ReadResults` used to express read results. Programs do not normally need to import from `IOConsts` directly, since client modules define identifiers that correspond to those defined by this module.

- ReadResults - Read result identities

#### ReadResults - Read result identities

    TYPE
      ReadResults =  (* This type is used to classify the result
                        of an input operation *)
      (
        notKnown,    (* no read result is set *)
        allRight,    (* data is as expected or as required *)
        outOfRange,  (* data cannot be represented *)
        wrongFormat, (* data not in expected format *)
        endOfLine,   (* end of line seen before expected data *)
        endOfInput   (* end of input seen before expected data *)
      );

Module `IOConsts`

### Modules IOResult and SIOResult

The module `IOResult` provides the facility for a program to determine whether the last operation to read data from a specified input channel found data in the required format.

The procedure of the module `SIOResult` behaves as the corresponding procedure of the module `IOResult`, except that the read result for the default input channel is returned.

NOTE:

The existence of the module `IOConsts` allows the definition module `SIOResult` to be independent of the modules `IOResult` and `IOChan`.

- ReadResults - Read result identities
- ReadResult - Get read result for channel

#### ReadResults - Read result identities

    TYPE
      ReadResults = IOConsts.ReadResults;

Modules: `IOResult`, `SIOResult`

The type `IOConsts.ReadResults` is re-exported.

#### ReadResult - Get read result for channel

    PROCEDURE ReadResult (cid: IOChan.ChanId): ReadResults;
    PROCEDURE ReadResult (): ReadResults;

Modules: `IOResult`, `SIOResult`

The function procedure `ReadResult` returns the stored read result for the channel identified by `cid`.

## Device-Independent Channel Operations

The module `IOChan` provides access to channel operations that are provided in a device-independent manner for all channels.

Device-dependent operations (which include operations for opening new channels and subsequently closing them) are defined in the definition module for each device.

- Module IOChan
- Module IOChan - Text Operations
- Module IOChan - Raw Operations
- Module IOChan - Common Operations
- Module IOChan - Access to Read Results
- Module IOChan - Channel Enquiries
- Module IOChan - Exceptions and Device Errors

### Module IOChan

The module `IOChan` defines the hidden type `ChanId` that is used to identify channels throughout the input/output library, and provides facilities for device-independent access to operations supported by the device to which a channel is connected.

- ChanId - Channel identity
- InvalidChan - Get an invalid channel id

#### ChanId - Channel identity

    TYPE
      ChanId;

Module `IOChan`

Values of this type are used to identify channels throughout the input/output library.

#### InvalidChan - Get an invalid channel id

    PROCEDURE InvalidChan (): ChanId;

Module `IOChan`

The function procedure `InvalidChan` returns the identity of the invalid channel.

NOTE:

The invalid channel is a channel on which no data transfer operations are available; enquiries on the invalid channel indicate that this is the case. The identity of the invalid channel can be used to initialize variables of the type `ChanId`.

### Module IOChan - Text Operations

Each of the following procedures invokes a corresponding operation for the device associated with the given channel. If the associated device supports the operation on the channel, the behaviour of the procedure conforms with the given description. The full behaviour is defined separately for each device.

These device operations produce a text stream. A text stream is a sequence of items, each of which corresponds either to a character or a line mark. The sequence may be empty.

The text operations provided by a device module perform any necessary translation between the internal representation (as a sequence of characters and line marks) and the external representation used by the source or destination. This may involve, for example, translation to and from escape sequences used in a coded character set, mapping between the external and internal representation of lines, or the interpretation of format effectors.

The interpretation of control characters is implementation-defined. The exception `textParseError` occurs (but need not be raised) if input data does not correspond to a character or line mark.

If the device does not support the operation on the channel, it raises the exception `notAvailable`.

- Look - Invoke Look operation
- Skip - Invoke Skip operation
- SkipLook - Invoke SkipLook operation
- WriteLn - Invoke WriteLn operation
- TextRead - Invoke TextRead operation
- TextWrite - Invoke TextWrite operation

#### Look - Invoke Look operation

    PROCEDURE Look (cid: ChanId;
                    VAR ch: CHAR;
                    VAR res: IOConsts.ReadResults);

Module `IOChan`

The procedure `Look` invokes the `Look` operation for the device that is associated with the channel identified by `cid`.

NOTE:

If supported on the channel, the device `Look` operation attempts to examine the next item in the input stream for the channel identified by `cid`, without removing it. If the next item is a character, its value is assigned to `ch`; otherwise, the value of `ch` is not defined. `res` is set to the same value as the stored read result for the channel `cid`, this being:

`allRight`
  if a character is seen next;
`endOfLine`
  if no character is seen, the next item being a line mark;
`endOfInput`
  if no character is seen, the input having ended.

#### Skip - Invoke Skip operation

    PROCEDURE Skip (cid: ChanId);

Module `IOChan`

The procedure `Skip` invokes the `Skip` operation for the device that is associated with the channel identified by `cid`.

NOTE:

If supported on the channel, the device `Skip` operation attempts to remove the next item in the input stream for the channel identified by `cid`. If there is no next item, the end of the input stream having been reached, the exception `skipAtEnd` is raised; otherwise the next character or line mark in the stream is removed, and the stored read result for the channel `cid` is set to the value `allRight`.

#### SkipLook - Invoke SkipLook operation

    PROCEDURE SkipLook (cid: ChanId;
                        VAR ch: CHAR;
                        VAR res: IOConsts.ReadResults);

Module `IOChan`

The procedure `SkipLook` invokes the `SkipLook` operation for the device that is associated with the channel identified by `cid`.

NOTE:

If supported on the channel, the device `SkipLook` operation attempts to remove the next item in the input stream for the channel identified by `cid` and then to examine the following item without removing it. If there is no next item, the end of the input stream having been reached, the exception `skipAtEnd` is raised; otherwise the next character or line mark in the stream is removed. If this is followed by a character as the next item in the stream, its value is assigned to `ch`, without removing the character from the stream; otherwise, the value of `ch` is not defined. `res` is set to the same value as the stored read result for the channel `cid`, this being:

`allRight`
  if a character is seen next;
`endOfLine`
  if no character is seen, the next item being a line mark;
`endOfInput`
  if no character is seen, the input having ended.

#### WriteLn - Invoke WriteLn operation

    PROCEDURE WriteLn (cid: ChanId);

Module `IOChan`

The procedure `WriteLn` invokes the `WriteLn` operation for the device that is associated with the channel identified by `cid`.

NOTE: If supported on the channel, the device `WriteLn` operation writes a line mark to the output stream identified by `cid`.

#### TextRead - Invoke TextRead operation

    PROCEDURE TextRead (cid: ChanId;
                        to: SYSTEM.ADDRESS;
                        maxChars: CARDINAL;
                        VAR charsRead: CARDINAL);

Module `IOChan`

The procedure `TextRead` invokes the `TextRead` operation for the device that is associated with the channel identified by `cid`.

NOTES:

- If supported on the channel, the device `TextRead` operation reads at most `maxChars` characters from the current line on the input stream for the channel identified by `cid`, and assigns their values to successive components of an array variable of the character type for which the address of the first component is `to`. The number of characters read is assigned to `charsRead`. The read result for the channel `cid` is set to the value

  `allRight`
    if ``maxChars = charsRead = 0' or (`maxChars > 0' and `charsRead > 0')`;

  `endOfLine`
    if ``maxChars > 0' and `charsRead = 0'` , the next item being a line mark;

  `endOfInput`
    if ``maxChars > 0' and `charsRead = 0'`, the input having ended.
- The intention is to allow `sub-arrays' to be selected, by passing the address of a starting component within a larger array. An exception occurs, but need not be raised, if the call leads to an attempt to access a non-existent component of the larger array.

#### TextWrite - Invoke TextWrite operation

    PROCEDURE TextWrite (cid: ChanId;
                         from: SYSTEM.ADDRESS;
                         charsToWrite: CARDINAL);

Module `IOChan`

The procedure `TextWrite` invokes the `TextWrite` operation for the device that is associated with the channel identified by `cid`.

NOTES:

- If supported on the channel, the device `TextWrite` operation copies `charsToWrite` characters, from successive components of an array variable of the character type, for which the address of the first component is `from`, to the output stream for the channel identified by `cid`. Copying starts from the index given by `offset`.
- The intention is to allow `sub-arrays' to be selected, by passing the address of a starting component within a larger array. An exception occurs, but need not be raised, if the call leads to an attempt to access a non-existent component of the larger array.

### Module IOChan - Raw Operations

Each of the following procedures invokes a corresponding operation for the device associated with the given channel. If the associated device supports the operation on the channel, the behaviour of the procedure conforms with the given description. The full behaviour is defined for each device module.

The raw operations provided by a device module transfer data location by location with no translation or interpretation.

If the device does not support the operation on the channel, it raises the exception `notAvailable`.

- RawRead - Invoke RawRead operation
- RawWrite - Invoke RawWrite operation

#### RawRead - Invoke RawRead operation

    PROCEDURE RawRead (cid: ChanId;
                       to: SYSTEM.ADDRESS;
                       maxLocs: CARDINAL;
                       VAR locsRead: CARDINAL);

Module `IOChan`

The procedure `RawRead` invokes the `RawRead` operation for the device that is associated with the channel identified by `cid`.

NOTES

- If supported on the channel, the device `RawRead` operation reads at most `maxLocs` items from the input stream for the channel identified by `cid`, and assigns their values to successive components of an array variable of the location type for which the address of the first component is `to`. The number of items read is assigned to `locsRead`. The read result for the channel cid is set to the value

  `allRight`
    if `(`maxLocs = locsRead = 0') or (`maxLocs > 0 and `locsRead > 0')`

  `endOfInput`
    if ``maxLocs > 0' and `locsRead = 0'`

- The intention is to allow `sub-arrays' to be selected, by passing the address of a starting component within a larger array. An exception occurs, but need not be raised, if the call leads to an attempt to access a non-existent component of the larger array.

#### RawWrite - Invoke RawWrite operation

    PROCEDURE RawWrite (cid: ChanId;
                        from: SYSTEM.ADDRESS;
                        locsToWrite: CARDINAL);

Module `IOChan`

The procedure `RawWrite` invokes the `RawWrite` operation for the device that is associated with the channel identified by `cid`.

NOTES:

- If supported on the channel, the device `RawWrite` operation copies `locsToWrite` items, from successive components of an array variable of the character type, for which the address of the first component is `from`, to the output stream for the channel identified by `cid`. Copying starts from the index given by `offset`.
- The intention is to allow `sub-arrays' to be selected, by passing the address of a starting component within a larger array. An exception occurs, but need not be raised, if the call leads to an attempt to access a non-existent component of the larger array.

### Module IOChan - Common Operations

Each of the following procedures invokes a corresponding operation for the device associated with the given channel. The behaviour of the procedure conforms with the given description. The full behaviour is defined for each device module.

- GetName - Invoke GetName operation
- Reset - Invoke Reset operation
- Flush - Invoke Flush operation

#### GetName - Invoke GetName operation

    PROCEDURE GetName (cid: ChanId;
                       VAR s: ARRAY OF CHAR);

Module `IOChan`

The procedure `GetName` invokes the `GetName` operation for the device that is associated with the channel identified by `cid`.

NOTES:

- The device `GetName` operation copies to `s` (as a string value) a name associated with the channel identified by `cid`.
- The name is truncated if the capacity of `s` is inadequate.

#### Reset - Invoke Reset operation

    PROCEDURE Reset (cid: ChanId);

Module `IOChan`

The procedure `Reset` invokes the Reset operation for the device that is associated with the channel identified by `cid`.

NOTE:

The device `Reset` operation resets the device associated with the channel identified by `cid` to a state defined by the device module.

#### Flush - Invoke Flush operation

    PROCEDURE Flush (cid: ChanId);

Module `IOChan`

The procedure `Flush` invokes the `Flush` operation for the device that is associated with the channel identified by `cid`.

NOTE:

The device `Flush` operation flushes any data buffered by the device module out to the destination associated with `cid`.

### Module IOChan - Access to Read Results

Higher-level data input procedures, for units such as strings and numerals, may alter the read result for a channel to indicate success or a particular kind of failure of interpretation. The result can be recovered, if necessary, by the caller of the data input procedure.

- SetReadResult - Set read result for channel
- ReadResult - Get read result for channel

#### SetReadResult - Set read result for channel

    PROCEDURE SetReadResult (cid: ChanId;
                             res: IOConsts.ReadResults);

Module `IOChan`

The procedure `SetReadResult` sets the read result for the channel identified by `cid` to the value given by `res`.

#### ReadResult - Get read result for channel

    PROCEDURE ReadResult (cid: ChanId): IOConsts.ReadResults;

Module `IOChan`

The function procedure `ReadResult` returns the stored read result for the channel identified by `cid`.

### Module IOChan - Channel Enquiries

- CurrentFlags - Get current flags for channel

#### CurrentFlags - Get current flags for channel

    PROCEDURE CurrentFlags (cid: ChanId): ChanConsts.FlagSet;

Module `IOChan`

The function procedure `CurrentFlags` returns the set of flags that currently apply to the channel identified by `cid`, as defined for the associated device.

### Module IOChan - Exceptions and Device Errors

The device-independent exceptions raised by the input/output library are identified by the values of the enumeration type `ChanExceptions`:

- ChanExceptions - Channel exceptions identities
- IsChanException - Query exceptional state
- ChanException - Query exception id
- DeviceErrNum - Device error number
- DeviceError - Get device error number

#### ChanExceptions - Channel exceptions identities

    TYPE
      ChanExceptions =
        (wrongDevice,
           (* device specific operation on wrong device *)
         notAvailable,
           (* operation attempted is not available on the channel *)
         skipAtEnd,
           (* attempt to skip data from a stream that has ended *)
         softDeviceError,
           (* device specific recoverable error *)
         hardDeviceError,
           (* device specific non-recoverable error *)
         textParseError,
           (* input data does not correspond to a character
              or line mark - optional detection *)
         notAChannel
           (* given value does not identify a channel -
              optional detection *)
       );

Module `IOChan`

NOTE:

The detection of the exceptions `textParseError` and `notAChannel` is implementation-defined.

#### IsChanException - Query exceptional state

    PROCEDURE IsChanException (): BOOLEAN;

Module `IOChan`

If the calling coroutine is in the state of exceptional execution because of the raising of an exception from `ChanExceptions`, the function procedure `IsChanException` returns `TRUE`; otherwise it returns `FALSE`.

#### ChanException - Query exception id

    PROCEDURE ChanException (): ChanExceptions;

Module `IOChan`

If the calling coroutine is in the state of exceptional execution because of the raising of an exception from `ChanExceptions`, the function procedure `ChanException` returns the value that identifies the raised exception; otherwise the language exception `exException` is raised.

#### DeviceErrNum - Device error number

    TYPE
      DeviceErrNum = INTEGER;

Module `IOChan`

Values of the type `DeviceErrNum` are used to identufy the implementation-defined error number for a chennel in the device exception handler.

See `DeviceError` procedure.

#### DeviceError - Get device error number

    PROCEDURE DeviceError (cid: ChanId): DeviceErrNum;

Module `IOChan`

The function procedure `DeviceError` returns the error number stored by the device module for the channel identified by `cid`, provided that a device error exception has been raised during an operation on that channel; otherwise the value of the call is not defined.

NOTE:

When a device procedure detects a device error, it raises the exception `softDeviceError` or `hardDeviceError`. If these exceptions are handled, the procedure `DeviceError` may be used to discover the implementation-defined error number stored by the device module for the channel that was in use when the device error occurred.

## Obtaining Channels from Device Modules

Separate device modules are defined that provide a program with the facility to obtain a new channel, connected either to a sequential stream, a rewindable sequential file, a random access file, or a terminal device.

A request to obtain a channel is made by calling an appropriate `open procedure', in general supplying a name that identifies the source or destination to which the connection is to be made.

The required input/output operations are specified using combinations of flags that are defined in terms of constants imported from the module `ChanConsts`.

An open procedure returns a parameter of an enumeration type (exported from the module `ChanConsts`) that indicates the success, or otherwise, of the request.

Each of these device modules defines a predicate allowing a check to be made that a given channel was opened by that module, as well as a `close procedure' that allows a program to break the connection and release the channel.

Procedures are also provided for device-dependent operations, such as setting the read/write position on a random access file.

A further device module is defined to allow access to the program arguments over a pre-opened channel.

- Module ChanConsts
- Module StreamFile
- Module SeqFile
- Module RndFile
- Module TermFile
- Module ProgramArgs

### Module ChanConsts

The module `ChanConsts` defines common types and values for use with open procedures. Programs do not normally need to import from `ChanConsts` directly, since device modules define identifiers that correspond to those defined by this module.

- ChanFlags - Channel open flags
- FlagSet - Channel open flags set
- OpenResults - Results of an open request
- The Use of ChanConsts

#### ChanFlags - Channel open flags

    TYPE
      ChanFlags =
      ( readFlag,
          (* input operations are requested/available *)
        writeFlag,
          (* output operations are requested/available *)
        oldFlag,
          (* a file may/must/did exist
             before the channel is opened *)
        textFlag,
          (* text operations are requested/available *)
        rawFlag,
          (* raw operations are requested/available *)
        interactiveFlag,
          (* interactive use is requested/applies *)
        echoFlag
          (* echoing by interactive device on removal of characters
             from input stream requested/applies *)
      );

Module `ChanConsts`

The elements of the enumeration type `ChanFlags` identify channel flags that are specified when a channel is opened and can be obtained for an open channel.

NOTE:

The type `FlagSet` is used in actual calls.

#### FlagSet - Channel open flags set

      FlagSet = SET OF ChanFlags;

    CONST
      read = FlagSet{readFlag};
        (* input operations are requested/available *)
      write = FlagSet{writeFlag};
        (* output operations are requested/available *)
      old = FlagSet{oldFlag};
        (* a file may/must/did exist
           before the channel is opened *)
      text = FlagSet{textFlag};
        (* text operations are requested/available *)
      raw = FlagSet{rawFlag};
        (* raw operations are requested/available *)
      interactive = FlagSet{interactiveFlag};
        (* interactive use is requested/applies *)
      echo = FlagSet{echoFlag};
        (* echoing by interactive device on removal of characters
           from input stream requested/applies *)

Module `ChanConsts`

Values of the type `FlagSet` are used in the calls to channel open procedures. Singleton values of `FlagSet` are provided for convinience. For example, `read + write` can be used instead of `FlagSet{read,write}`.

#### OpenResults - Results of an open request

    TYPE
      OpenResults =
      ( opened,
          (* the open succeeded as requested *)
        wrongNameFormat,
          (* given name is in the wrong format
             for the implementation *)
        wrongFlags,
          (* given flags include a value
             that does not apply to the device *)
        tooManyOpen,
          (* this device cannot support any more open channels *)
        outOfChans,
          (* no more channels can be allocated *)
        wrongPermissions,
          (* file or directory permissions do not allow request *)
        noRoomOnDevice,
          (* storage limits on the device prevent the open *)
        noSuchFile,
          (* a needed file does not exist *)
        fileExists,
          (* a file of the given name already exists
             when a new one is required *)
        wrongFileType,
          (* the file is of the wrong type to support
             the required operations *)
        noTextOperations,
          (* text operations have been requested,
             but are not supported *)
        noRawOperations,
          (* raw operations have been requested,
             but are not supported *)
        noMixedOperations,
          (* text and raw operations have been requested, but they
             are not supported in combination *)
        alreadyOpen,
          (* the source/destination is already open
             for operations not supported in combination
             with the requested operations *)
        otherProblem
          (* open failed for some other reason *)
      );

Module `ChanConsts`

The elements of the enumeration type `OpenResults` identify possible results of an open request.

#### The Use of ChanConsts

To save repetition in the natural language definition of the device modules, the meaning given to some values of `FlagSet` and `OpenResults` is defined here. The meaning of the other flags is given for the open operations to which they apply.

In a call of a device module open procedure that has a request parameter of the type `FlagSet` and a result parameter of the type `OpenResults`:

If the result is `opened`, the following operations are provided for the opened channel for the combinations of request flags shown:

| `read` | `write` |
`text` | text input | text output | as defined for the device
`raw` | raw input | raw output | as defined for the device

NOTE:

The supplied flags specify the minimal functionality that must be available for the open operation to succeed. Implementations are free to allow operations in addition to those specified in the request flags provided that these are reflected in the enquiry flags returned for the channel.

If the result is other than `opened`, the channel parameter is assigned the value identifying the invalid channel, on which no input/output operations are provided. The result is chosen according to the following table:

`wrongNameFormat` | if the given name is not in the format defined for the implementation
`wrongFlags` | if the given flags include a value that does not apply to the device
`tooManyOpen` | if the device cannot support any more open channels
`outOfChans` | if no more channels can be allocated
`wrongPermissions` | if file or directory permissions do not allow the request to be met
`noRoomOnDevice` | if storage limits on the device do not allow the request to be met
`noSuchFile` | if a needed file does not exist
`fileExists` | if a file of the given name already exists when a new one is required
`wrongFileType` | if the named file is of the wrong type to support the required operations
`noTextOperations` | if text operations have been requested, but are not supported by the device
`noRawOperations` | if raw operations have been requested, but are not supported by the device
`noMixedOperations` | if text and raw operations have been requested, but they are not supported in combination by the device
`alreadyOpen` | if the source/destination is already open for operations that are not supported in combination with the operations now requested
`otherProblem` | if the open failed for a reason other than the above

### Module StreamFile

The module `StreamFile` provides facilities for obtaining and releasing channels that are connected to named sources and/or destinations for independent sequential data streams.

The types `IOChan.ChanId`, `ChanConsts.FlagSet`, and `ChanConsts.OpenResults` are re-expored. The singleton values of the type `FlagSet` are declared for convinience:

    TYPE
      ChanId = IOChan.ChanId;
      FlagSet = ChanConsts.FlagSet;
      OpenResults = ChanConsts.OpenResults;

    CONST
      read = FlagSet{ChanConsts.readFlag};
        (* input operations are requested/available *)
      write = FlagSet{ChanConsts.writeFlag};
        (* output operations are requested/available *)
      old = FlagSet{ChanConsts.oldFlag};
        (* a file may/must/did exist
           before the channel is opened *)
      text = FlagSet{ChanConsts.textFlag};
        (* text operations are requested/available *)
      raw = FlagSet{ChanConsts.rawFlag};
        (* raw operations are requested/available *)

In a request to open a sequential stream, the flags `read`, `write`, `old`, `text`, and `raw` apply. If `raw` is not included in the request parameter `flags`, inclusion of `text` is implied.

- Open - Open sequential stream
- IsStreamFile - Query whether stream is sequential
- Close - Close sequential stream

#### Open - Open sequential stream

    PROCEDURE Open (VAR cid: ChanId;
                    name: ARRAY OF CHAR;
                    flags: FlagSet;
                    VAR res: OpenResults);

Module `StreamFile`

If successful, the procedure `Open` assigns to `cid` the identity of a channel that is connected to a sequential stream specified by `name`, and the value `opened` is assigned to `res`.

If `write` is not included in `flags`, inclusion of `read` is implied; if `read` is given or implied, inclusion of `old` is implied; a source of the given name has to already exist if the call is to succeed.

If `write` is included, a destination of the given name has to not already exist, unless the flag `old` is given or implied.

If a channel cannot be opened as required, the value of `res` indicates the reason, and `cid` identifies the invalid channel.

NOTE:

Distinct modes in combination with `text` and/or `raw` are given by the following equivalent sets of flags:

- read from an existing source: `read` `old` `read+old`
- write to a new destination: `write`
- write to a new or old destination: `write+old`
- read/write an existing source/destination: `read+write` `read+write+old`

#### IsStreamFile - Query whether stream is sequential

    PROCEDURE IsStreamFile (cid: ChanId): BOOLEAN;

Module `StreamFile`

The function procedure `IsStreamFile` returns `TRUE` if the channel identified by `cid` is open to a sequential stream, and `FALSE` otherwise.

#### Close - Close sequential stream

    PROCEDURE Close (VAR cid: ChanId);

Module `StreamFile`

If the channel identified by `cid` is open to a sequential stream, the procedure `Close` closes the channel and assigns the value identifying the invalid channel to `cid`; otherwise, the exception `wrongDevice` is raised.

### Module SeqFile

The module `SeqFile` provides facilities for obtaining and releasing channels that are connected to named rewindable sequential stored files.

If opened for both writing and reading, data written to the file may be read back from the start of the file. Rewriting from the start of the file causes the previous contents to be lost.

The types `IOChan.ChanId`, `ChanConsts.FlagSet`, and `ChanConsts.OpenResults` are re-expored. The singleton values of the type `FlagSet` are declared for convinience:

    TYPE
      ChanId = IOChan.ChanId;
      FlagSet = ChanConsts.FlagSet;
      OpenResults = ChanConsts.OpenResults;

    CONST
      read = FlagSet{ChanConsts.readFlag};
        (* input operations are requested/available *)
      write = FlagSet{ChanConsts.writeFlag};
        (* output operations are requested/available *)
      old = FlagSet{ChanConsts.oldFlag};
        (* a file may/must/did exist before the channel is opened *)
      text = FlagSet{ChanConsts.textFlag};
        (* text operations are requested/available *)
      raw = FlagSet{ChanConsts.rawFlag};
        (* raw operations are requested/available *)

In a request to open a rewindable sequential file, the flags `read`, `write`, `old`, `text`, and `raw` apply. If `raw` is not included in the request parameter flags, inclusion of `text` is implied.

Channels open to rewindable sequential files may be in input mode or in output mode. In input mode, only input operations are available, ``(IOChan.Flags()*(read+write) = read)'` is true, and an attempt to write over the channel raises the exception `notAvailable`. In output mode, only output operations are available, ``(IOChan.Flags()*(read+write) = write)'` is true, and an attempt to read from the channel raises the exception `notAvailable`. All data written to a rewindable sequential file is appended to previous data written to that file.

- OpenWrite - Open sequential file for writing
- OpenAppend - Open sequential file for appending
- OpenRead - Open sequential file for reading
- IsSeqFile - Query whether channel is open to a sequential file
- Reread - Rewind and select input mode
- Rewrite - Rewind and select output mode
- Close - Close sequential file

#### OpenWrite - Open sequential file for writing

    PROCEDURE OpenWrite (VAR cid: ChanId;
                         name: ARRAY OF CHAR;
                         flags: FlagSet;
                         VAR res: OpenResults);

Module `SeqFile`

If successful, the procedure `OpenWrite` assigns to `cid` the identity of a channel that is connected to a stored file specified by `name`; the value `opened` is assigned to `res`. Output mode is selected and the file is truncated to zero length.

Inclusion of the `write` flag in the parameter `flags` is implied.

If the call is to succeed, a destination of the given name has to not already exist unless the flag `old` is given; if the `read` flag is included in the request, the `Reread` operation is available.

The effect of a `Reset` operation on the channel is to truncate the file to zero length and to select output mode.

If a channel cannot be opened as required, the value of `res` indicates the reason, and `cid` identifies the invalid channel.

NOTE:

Distinct modes in combination with `text` and/or `raw` are given by the following equivalent sets of flags:

- write to a new file: `write`
- write to a new file or a truncated existing file: `old` `write+old`
- write to a new file, need read operations: `write+read` `read`
- write to a new or existing file, need read operations: `old+read` `write+old+read`

#### OpenAppend - Open sequential file for appending

    PROCEDURE OpenAppend (VAR cid: ChanId;
                          name: ARRAY OF CHAR;
                          flags: FlagSet;
                          VAR res: OpenResults);

Module `SeqFile`

If successful, the procedure `OpenAppend` assigns to `cid` the identity of a channel that is connected to a stored file specified by `name`; the value `opened` is assigned to `res`. Output mode is selected.

Have to write something here.

Inclusion of the `write` and `old` flags in the parameter `flags` is implied; a destination of the given name may already exist.

If the `read` flag is included in the request, the `Reread` operation is available if the call is to succeed.

The effect of a `Reset` operation on the channel is to select output mode.

If a channel cannot be opened as required, the value of `res` indicates the reason, and `cid` identifies the invalid channel.

NOTE:

Distinct modes in combination with `text` and/or `raw` are given by the following equivalent sets of flags:

- write to a new or append to an existing file: `write` `old` `write+old`
- write to a new or append to an existing file, need read operations: `read` `write+read` `old+read` `write+old+read`

#### OpenRead - Open sequential file for reading

    PROCEDURE OpenRead (VAR cid: ChanId;
                        name: ARRAY OF CHAR;
                        flags: FlagSet;
                        VAR res: OpenResults);

Module `SeqFile`

If successful, the procedure `OpenRead` assigns to `cid` the identity of a channel that is connected to a stored file specified by `name`; the value opened is assigned to `res`. Input mode is selected and the read position correspond to the start of the file.

Inclusion of the `read` and `old` flags in the parameter `flags` is implied; a destination of the given name has to already exist if the call is to succeed.

If the `write` flag is included in the request, the `Rewrite` operation is available if the call is to succeed.

The effect of a `Reset` operation on the channel is to select input mode and to set the read position to the start of the file.

If a channel cannot be opened as required, the value of `res` indicates the reason, and `cid` identifies the invalid channel.

NOTE:

Distinct modes in combination with `text` and/or `raw` are given by the following equivalent sets of flags:

- read from an existing file: `read` `old` `read+old`
- read from an existing file, need write operations: `write` `read+write` `old+write` `read+old+write`

#### IsSeqFile - Query whether channel is open to a sequential file

    PROCEDURE IsSeqFile (cid: ChanId): BOOLEAN;

Module `SeqFile`

The function procedure `IsSeqFile` returns `TRUE` if the channel identified by `cid` is open to a rewindable sequential file, and `FALSE` otherwise.

#### Reread - Rewind and select input mode

    PROCEDURE Reread (cid: ChanId);

Module `SeqFile`

If the channel identified by `cid` is open to a rewindable sequential file, the procedure `Reread` attempts to set the read position of the channel to the start of the file, and to select input mode; otherwise, the exception `wrongDevice` is raised.

If the operation cannot be performed, perhaps because of insufficient permissions, neither input mode nor output mode are selected.

#### Rewrite - Rewind and select output mode

    PROCEDURE Rewrite (cid: ChanId);

Module `SeqFile`

If the channel identified by `cid` is open to a rewindable sequential file, the procedure `Rewrite` attempts to set the write position of the channel to the start of the file, to truncate the file to zero length, and to select output mode; otherwise, the exception `wrongDevice` is raised.

If the operation cannot be performed, perhaps because of insufficient permissions, neither input mode nor output mode are selected.

#### Close - Close sequential file

    PROCEDURE Close (VAR cid: ChanId);

Module `SeqFile`

If the channel identified by `cid` is open to a rewindable sequential file, the procedure `Close` closes the channel and assigns the value identifying the invalid channel to `cid`; otherwise, the exception `wrongDevice` is raised.

### Module RndFile

The module `RndFile` provides facilities for obtaining and releasing channels that are connected to named random access files.

The types `IOChan.ChanId`, `ChanConsts.FlagSet`, and `ChanConsts.OpenResults` are re-expored. The singleton values of the type `FlagSet` are declared for convinience:

    TYPE
      ChanId = IOChan.ChanId;
      FlagSet = ChanConsts.FlagSet;
      OpenResults = ChanConsts.OpenResults;

    CONST
      read = FlagSet{ChanConsts.readFlag};
        (* input operations are requested/available *)
      write = FlagSet{ChanConsts.writeFlag};
        (* output operations are requested/available *)
      old = FlagSet{ChanConsts.oldFlag};
        (* a file may/must/did exist before the channel is opened *)
      text = FlagSet{ChanConsts.textFlag};
        (* text operations are requested/available *)
      raw = FlagSet{ChanConsts.rawFlag};
        (* raw operations are requested/available *)

Channels opened by the module `RndFile` have an associated read/write position in the corresponding random-access file. The read/write position is at the start of the file after opening, or after a `Reset` operation on the channel. It is moved forward by the number of positions occupied by data that are taken from the file by an input operation, or written to the file by an output operation.

    CONST
      FilePosSize = <implementation-defined whole
                     number greater than zero>;

    TYPE
      FilePos = ARRAY [1 .. FilePosSize] OF SYSTEM.LOC;

NOTE:

The implementation-defined type `FilePos` has been specified in a way that enables values of this type to be read from or written to a file, while maintaining a degree of opacity for the type.

A random-access file have a length corresponding to the position after the highest read/write position at which data have been written. This length is zero if no data have been written to the file. If the read/write position is set at the current length, either implicitly on an input or output operation, or explicitly by a positioning operation, the effect of an input operation is as if the input stream had ended. A write at that position, if necessary, attempts to allocate more physical storage for the file.

In a request to open a random-access file, the flags `read`, `write`, `old`, `text`, and `raw` apply. If `text` is not included in the request parameter flags, inclusion of `raw` is implied.

- OpenOld - Open existing random-aceess file
- OpenClean - Open and clear random-aceess file
- IsRndFile - Query whether channel is open to a random access file
- IsRndFileException - Query exceptional state
- StartPos - Query start position
- CurrentPos - Query current position
- EndPos - Query end position
- NewPos - Calculate new position
- SetPos - Set new position
- Close - Close random access file

#### OpenOld - Open existing random-aceess file

    PROCEDURE OpenOld (VAR cid: ChanId;
                       name: ARRAY OF CHAR;
                       flags: FlagSet;
                       VAR res: OpenResults);

Module `RndFile`

If successful, the procedure `OpenOld` assigns to `cid` the identity of a channel that is connected to a random access file specified by `name`; the value opened is assigned to `res`. The read/write position correspond to the start of the file.

Inclusion of the `old` flag in the parameter flags is implied; a file of the given name have to already exist if the call is to succeed.

If the `write` flag is not included in the request, inclusion of the `read` flag is implied.

If a channel cannot be opened as required, the value of `res` indicates the reason, and `cid` identifies the invalid channel.

NOTE:

Distinct modes in combination with `text` and/or `raw` are given by the following equivalent sets of flags:

- read from an existing file: `read` `old` `read+old`
- write to an existing file: `write` `write+old`
- read/write an existing file: `read+write` `read+write+old`

#### OpenClean - Open and clear random-aceess file

    PROCEDURE OpenClean (VAR cid: ChanId;
                         name: ARRAY OF CHAR;
                         flags: FlagSet;
                         VAR res: OpenResults);

Module `RndFile`

If successful, the procedure `OpenClean` assigns to `cid` the identity of a channel that is connected to a random access file specified by `name`; the value `opened` is assigned to `res`. The file is truncated to zero length.

Inclusion of the `write` flag in the parameter flags is implied; a destination of the given name has to not already exist unless the flag `old` is given.

If a channel cannot be opened as required, the value of `res` indicates the reason, and `cid` identifies the invalid channel.

NOTE:

Distinct modes in combination with `text` and/or `raw` are given by the following equivalent sets of flags:

- write to a new file: `write`
- write to a new file or a truncated existing file: `old` `write+old`
- write to a new file, read operations are needed: `read` `write+read`
- write to a new file or a truncated existing file, read operations are needed: `old+read` `write+old+read`

#### IsRndFile - Query whether channel is open to a random access file

    PROCEDURE IsRndFile (cid: ChanId): BOOLEAN;

Module `RndFile`

The function procedure `IsRndFile` returns `TRUE` if the channel identified by `cid` is open to a random access file, and `FALSE` otherwise.

#### IsRndFileException - Query exceptional state

    PROCEDURE IsRndFileException (): BOOLEAN;

Module `RndFile`

If the calling coroutine is in the state of exceptional execution because of the raising of the `RndFile` exception, the function procedure `IsRndFileException` returns `TRUE`; otherwise it returns `FALSE`.

#### StartPos - Query start position

    PROCEDURE StartPos (cid: ChanId): FilePos;

Module `RndFile`

If the channel identified by `cid` is open to a random access file, the function procedure `StartPos` returns the position of the start of the file; otherwise the exception `wrongDevice` is raised.

#### CurrentPos - Query current position

    PROCEDURE CurrentPos (cid: ChanId): FilePos;

Module `RndFile`

If the channel identified by `cid` is open to a random access file, the function procedure `CurrentPos` returns the current read/write position of the file; otherwise the exception `wrongDevice` is raised.

#### EndPos - Query end position

    PROCEDURE EndPos (cid: ChanId): FilePos;

Module `RndFile`

If the channel identified by `cid` is open to a random access file, the function procedure `EndPos` returns the first position in the file at or after which no data have been written; otherwise the exception `wrongDevice` is raised.

#### NewPos - Calculate new position

    PROCEDURE NewPos (cid: ChanId;
                      chunks: INTEGER;
                      chunkSize: CARDINAL;
                      from: FilePos): FilePos;

Module `RndFile`

If the channel identified by `cid` is open to a random access file, the function procedure `NewPos` returns the read/write position `chunks * chunkSize` places relative to the position in the file given by the value of `from`; otherwise, the exception `wrongDevice` is raised. The `RndFile` exception is raised if the required position cannot be represented as a value of the type `FilePos`.

NOTE:

Calculation of the position in a random access file at which to issue text operations is dependent upon knowledge of the external representation of text items in a particular file; the amount by which the read/write position is moved as a result of a text operation may vary depending upon the item that is read or written. For raw operations, the read/write position is always moved by a value equal to the storage size of variables of the type of the item read or written.

#### SetPos - Set new position

    PROCEDURE SetPos (cid: ChanId; pos: FilePos);

Module `RndFile`

If the channel identified by `cid` is open to a random access file, the procedure `SetPos` sets the read/write position for the file to the position given by the value of `pos`; otherwise the exception `wrongDevice` is raised.

If the position given by the value of `pos` is beyond the value returned by a call of `EndPos`, ``read <= IOChan.Flags()'` is false, and a call of an input operation raises the exception `notAvailable`; the value of ``write <= IOChan.Flags()'` is implementation-defined and correspond to the availability of output operations in this case. If data are subsequently written at such a position, those positions that have not been written to are filled with implementation-defined padding values.

NOTE:

Setting the read/write position beyond the value returned by `EndPos` does not of itself affect the size of the file.

#### Close - Close random access file

    PROCEDURE Close (VAR cid: ChanId);

Module `RndFile`

If the channel identified by cid is open to a random access file, the procedure `Close` closes the channel and assign the value identifying the invalid channel to `cid`; otherwise, the exception `wrongDevice` is raised.

### Module TermFile

The module `TermFile` provides facilities that allow elementary access to an interactive terminal.

The types `IOChan.ChanId`, `ChanConsts.FlagSet`, and `ChanConsts.OpenResults` are re-expored. The singleton values of the type `FlagSet` are declared for convinience:

    TYPE
      ChanId = IOChan.ChanId;
      FlagSet = ChanConsts.FlagSet;
      OpenResults = ChanConsts.OpenResults;

    CONST
      read = FlagSet{ChanConsts.readFlag};
        (* input operations are requested/available *)
      write = FlagSet{ChanConsts.writeFlag};
        (* output operations are requested/available *)
      text = FlagSet{ChanConsts.textFlag};
        (* text operations are requested/available *)
      raw = FlagSet{ChanConsts.rawFlag};
        (* raw operations are requested/available *)
      echo = FlagSet{ChanConsts.echoFlag};
        (* echoing by interactive device on reading of
           characters from input stream requested/applies *)

Channels connected to the terminal device are opened in line mode or in single-character mode. In line mode, items are echoed before being added to the input stream and are added a line at a time. In single character mode, items are added to the input stream as they are typed, and are echoed as they are removed from the input stream by a text read device operation, provided they have not already been echoed.

Typed characters are distributed between multiple channels according to the sequence of read requests.

NOTE:

If all the channels open to the terminal are open in line mode, the terminal device operates exclusively in line mode; in that case, echoing might be performed by an underlying operating system. Similarly, if all the channels open to the terminal are open in single-character mode, the terminal device operates exclusively in single-character mode; in that case, echoing only occurs on reading from a channel and not on looking or skipping: this allows interactive input routines to suppress the echoing of unwanted or unexpected characters.

If an implementation allows it, there might be one or more channels open in line mode, and one or more channels open in single-character mode. In that case, echoing is postponed until the treatment of characters can be determined according to the sequence of calls of input operations. This behaviour allows programs that use the terminal in different modes to be written in a modular fashion, there being no need explicitly to save and restore the state of the terminal device.

In a request to open a channel to the terminal device, the flags `read`, `write`, `text`, `raw`, and `echo` apply. If `raw` is not included in the request parameter flags, inclusion of `text` is implied. If the `read` flag is not included in the request, inclusion of the `write` flag is implied.

- Open - Open terminal
- IsTermFile - Query whether channel is opened to terminal
- Close - Close terminal

#### Open - Open terminal

    PROCEDURE Open (VAR cid: ChanId;
                    flags: FlagSet;
                    VAR res: OpenResults);

Module `TermFile`

If successful, the procedure `Open` assigns to `cid` the identity of a channel that is connected to the terminal device.

If the `echo` flag is included in the request, single-character mode is available if the call is to succeed and the channel operates in single-character mode. Without the `echo` flag, line mode is available if the call is to succeed and the channel operates in line mode.

If a channel cannot be opened as required, the value of `res` indicates the reason, and `cid` identifies the invalid channel.

#### IsTermFile - Query whether channel is opened to terminal

    PROCEDURE IsTermFile (cid: ChanId): BOOLEAN;

Module `TermFile`

The function procedure `IsTermFile` returns `TRUE` if the channel identified by `cid` is open to the terminal device, and `FALSE` otherwise.

#### Close - Close terminal

    PROCEDURE Close (VAR cid: ChanId);

Module `TermFile`

If the channel identified by `cid` is open to the terminal device, the procedure `Close` closes the channel and assigns the value identifying the invalid channel to `cid`; otherwise, the exception `wrongDevice` is raised.

### Module ProgramArgs

The module `ProgramArgs` provides a channel from which input can be taken from any arguments given to the program.

    TYPE
      ChanId = IOChan.ChanId;

The initialization of the module `ProgramArgs` opens the channel from which the implementation-defined program arguments may be read.

- ArgChan - Get program arguments channel id
- IsArgPresent - Query whether an argument is present
- NextArg - Skip to next argument

#### ArgChan - Get program arguments channel id

    PROCEDURE ArgChan (): ChanId;

Module `ProgramArgs`

The function procedure `ArgChan` returns a value identifying a channel from which the implementation-defined program arguments may be read.

#### IsArgPresent - Query whether an argument is present

    PROCEDURE IsArgPresent (): BOOLEAN;

Module `ProgramArgs`

The function procedure `IsArgPresent` returns `TRUE` if there is a current argument from which to read, and `FALSE` otherwise.

If there is no current argument, ``read <= IOChan.Flags()'` is false, and attempting to read from the argument channel raises the exception `notAvailable`.

#### NextArg - Skip to next argument

    PROCEDURE NextArg ();

Module `ProgramArgs`

After the call to the procedure `NextArg`, if there is another argument, subsequent input from the argument channel is taken from the start of that argument; otherwise a call of `IsArgPresent` returns `FALSE`.

NOTE:

Provision of `NextArg` allows the treatment of arguments that contain spaces or line marks.

## Interface to Channels for New Device Modules

Additional device modules may be provided to allow the library to be used with other input sources and output destinations. These might include, for example, files opened with host-specific options or parameters or with host-specific behaviour, a windowing system, or a speech output device.

- Module IOLink

### Module IOLink

The module `IOLink` provides facilities that allow a user to provide specialized device modules for use with channels, following the pattern of the rest of the library.

A device needs to identify itself in order to allow a check to be made that device-dependent operations are applied only for channels opened to that device. To this end, values of the hidden type `DeviceId` are used to identify new device modules, and are normally obtained by them during their initialization by a call to the procedure `AllocateDeviceId`.

    TYPE
      DeviceId;

A device module procedure provided for opening a channel can obtain a new channel by calling the procedure `MakeChan`. If a channel is allocated, but the call of the device module open procedure is not successful for some reason, the device module should release the channel by calling the procedure `UnMakeChan`, and return the value identifying the invalid channel to its client.

A call to `UnMakeChan` is also made on a successful call of a device module procedure provided for closing a channel.

If a call of a device module `open' procedure is successful, then by calling the function procedure `DeviceTablePtrValue`, a device module can obtain a pointer (of the type `DeviceTablePtr`) to a `device table' (of a record type `DeviceTable`) for the channel. The fields of this record are initialized by `MakeChan`, but the procedure can then change any fields of the device table needed to install its own values for the device data, supported operations, and flags.

Device tables have:

1. a field in which the device module can store private data,
2. a field in which the value identifying the device module is stored,
3. a field in which the value identifying the channel is stored,
4. a field in which the read result is stored,
5. a field in which device error numbers are stored prior to the raising of a device error exception,
6. a field in which flags are stored indicating those which apply,
7. a field for each device procedure.

(The fields are initialized by `MakeChan` to the values shown in the definition module below.)

By calling the function procedure `IsDevice`, a device module can enquire whether it was responsible for opening a given channel. This allows it to implement a corresponding enquiry function that is exported from the device module itself.

Client modules may raise appropriate exceptions; to support this facility, the type `DevExceptionRange` and the procedure `RAISEdevException` can be used.

    TYPE
      DeviceTablePtr = POINTER TO DeviceTable;
        (* Values of this type are used to refer to device tables *)

    TYPE
      LookProc      = PROCEDURE (DeviceTablePtr,
                                 VAR CHAR,
                                 VAR IOConsts.ReadResults);
      SkipProc      = PROCEDURE (DeviceTablePtr);
      SkipLookProc  = PROCEDURE (DeviceTablePtr,
                                 VAR CHAR,
                                 VAR IOConsts.ReadResults);
      WriteLnProc   = PROCEDURE (DeviceTablePtr);
      TextReadProc  = PROCEDURE (DeviceTablePtr,
                                 SYSTEM.ADDRESS,
                                 CARDINAL,
                                 VAR CARDINAL);
      TextWriteProc = PROCEDURE (DeviceTablePtr,
                                 SYSTEM.ADDRESS,
                                 CARDINAL);
      RawReadProc   = PROCEDURE (DeviceTablePtr,
                                 SYSTEM.ADDRESS,
                                 CARDINAL,
                                 VAR CARDINAL);
      RawWriteProc  = PROCEDURE (DeviceTablePtr,
                                 SYSTEM.ADDRESS,
                                 CARDINAL);
      GetNameProc   = PROCEDURE (DeviceTablePtr,
                                 VAR ARRAY OF CHAR);
      ResetProc     = PROCEDURE (DeviceTablePtr);
      FlushProc     = PROCEDURE (DeviceTablePtr);
      FreeProc      = PROCEDURE (DeviceTablePtr);
        (* Carry out the operations involved in closing
           the corresponding channel, including flushing buffers,
           but do not unmake the channel.
        *)

    TYPE
      DeviceData = SYSTEM.ADDRESS;

    DeviceTable =
      RECORD           (* Initialized by MakeChan to: *)
        cd:          DeviceData;
                       (* the value NIL *)
        did:         DeviceId;
                       (* the value given in the call of MakeChan *)
        cid:         IOChan.ChanId;
                       (* the identity of the channel *)
        result:      IOConsts.ReadResults;
                       (* the value notKnown *)
        errNum:      IOChan.DeviceErrNum;
                       (* undefined *)
        flags:       ChanConsts.FlagSet;
                       (* ChanConsts.FlagSet{} *)
        doLook:      LookProc;
                       (* raise exception notAvailable *)
        doSkip:      SkipProc;
                       (* raise exception notAvailable *)
        doSkipLook:  SkipLookProc;
                       (* raise exception notAvailable *)
        doLnWrite:   WriteLnProc;
                       (* raise exception notAvailable *)
        doTextRead:  TextReadProc;
                       (* raise exception notAvailable *)
        doTextWrite: TextWriteProc;
                       (* raise exception notAvailable *)
        doRawRead:   RawReadProc;
                       (* raise exception notAvailable *)
        doRawWrite:  RawWriteProc;
                       (* raise exception notAvailable *)
        doGetName:   GetNameProc;
                       (* return the empty string *)
        doReset:     ResetProc;
                       (* do nothing *)
        doFlush:     FlushProc;
                       (* do nothing *)
        doFree:      FreeProc;
                       (* do nothing *)
      END;

    TYPE
      DevExceptionRange =
        z[IOChan.notAvailable .. IOChan.textParseError];

- AllocateDeviceId - Allocate device id
- MakeChan - Allocate a new channel for device
- UnMakeChan - Deallocate channel from device
- DeviceTablePtrValue - Get device table for channel
- IsDevice - Query channel's device
- RAISEdevException - Raise device exception
- IsIOException - Query exceptional state
- IOException - Query exception id

#### AllocateDeviceId - Allocate device id

    PROCEDURE AllocateDeviceId (VAR did: DeviceId);

Module `IOLink`

The procedure `AllocateDeviceId` allocates an unique value of the type `DeviceId`, and assign this value to `did`.

#### MakeChan - Allocate a new channel for device

    PROCEDURE MakeChan (did: DeviceId;
                        VAR cid: IOChan.ChanId);

Module `IOLink`

The procedure `MakeChan` attempts to allocate a new channel for the device module identified by `did`. If no more channels can be allocated, the value identifying the invalid channel is assigned to `cid`. Otherwise, a value identifying a new initialized channel is assigned to `cid`.

#### UnMakeChan - Deallocate channel from device

    PROCEDURE UnMakeChan (did: DeviceId;
                          VAR cid: IOChan.ChanId);

Module `IOLink`

Provided the device module identified by `did` is the module that made the channel identified by `cid`, the procedure `UnMakeChan` deallocates the channel identified by `cid`, and assigns the value identifying the invalid channel to `cid`; otherwise the exception `wrongDevice` is raised.

#### DeviceTablePtrValue - Get device table for channel

    PROCEDURE DeviceTablePtrValue (cid: IOChan.ChanId;
                                   did: DeviceId
                                  ): DeviceTablePtr;

Module `IOLink`

Provided that the device module identified by `did` is the module that made the channel identified by `cid`, the function procedure `DeviceTablePtrValue` returns a pointer to the device table for the channel identified by `cid`; otherwise the exception `wrongDevice` is raised.

#### IsDevice - Query channel's device

    PROCEDURE IsDevice (cid: IOChan.ChanId;
                        did: DeviceId
                       ): BOOLEAN;

Module `IOLink`

The function procedure `IsDevice` returns `TRUE` if the device module identified by `did` is the module that made the channel identified by `cid`, and otherwise returns `FALSE`.

#### RAISEdevException - Raise device exception

    PROCEDURE RAISEdevException (cid: IOChan.ChanId;
                                 did: DeviceId;
                                 x: DevExceptionRange;
                                 s: ARRAY OF CHAR);

Module `IOLink`

Provided that the device module identified by `did` is the module that made the channel identified by `cid`, the procedure `RAISEdevException` raises the exception given by `x`, and includes the string value in `s` in the exception message; otherwise the exception `wrongDevice` is raised.

#### IsIOException - Query exceptional state

    PROCEDURE IsIOException (): BOOLEAN;

Module `IOLink`

If the calling coroutine is in the state of exceptional execution because of the raising of an exception from `IOChan.ChanExceptions`, the function procedure `IsIOException` returns `TRUE`; otherwise it returns `FALSE`.

#### IOException - Query exception id

    PROCEDURE IOException (): IOChan.ChanExceptions;

Module `IOLink`

If the calling coroutine is in the state of exceptional execution because of the raising of an exception from `IOChan.ChanExceptions`, the function procedure `IOException` returns the value that identifies the raised exception; otherwise the language exception `exException` is raised.

NOTE:

A single value of `EXCEPTIONS.ExceptionSource` is used to identify the source of input/output library exceptions corresponding to `IOChan.ChanExceptions`. The procedures `IsIOException` and `IOException` are included so that this value need not be exported for corresponding procedures to be provided through the `IOChan` interface.