1 The Standard Library

The ISO standard for Modula-2 contains not only the language definition itself, but also the definition of library modules for a lot of common functions. This ensures that machine independent tools are supported from all compilers in the same way.

Part of the modules in the standard library have to be supported by every implementation. All other modules may be supported, if they are provided, their form and meaning is fixed by the standard.

p1 Modula-2 V9.3 supports all defined modules.

The standard library has four parts:

The handling of runtime errors is done throughout the whole library by the concept of exceptions (cf. compiler manual, chapter 2.7). All modules, that may raise specific exceptions report these exceptions in the same way. Each of these modules exports a procedure with the name "Is<Modulename>Exceptions". In case of an exceptions, this procedure can be used to test whether the exception was raised by the module it belongs to. If "Is<Modulename>Exceptions" returns "TRUE" (exception was raised by this module), the reason for the exception can be obtained by "<Modulename>Exception". This function procedure has as result type an enumeration type, exported by the same module, that lists all reasons for exceptions. Some modules define only one reason for exceptions, in this case neither "<Modulename>Exception" nor the enumeration type are exported.

1.1 Obligatory Modules

1.1.1. Storage

DEFINITION MODULE Storage;

  (* Facilities for making areas of storage available to a program at
     execution time
  *)

IMPORT SYSTEM;

PROCEDURE ALLOCATE (VAR addr: SYSTEM.ADDRESS; amount: CARDINAL);
  (* Makes available to the program an area of storage whose size, in units
     of SYSTEM.LOC, is given by amount, and assigns the address of this area
     to addr.  If there is insufficient storage to do this, the value NIL is
     assigned to addr.
  *)

PROCEDURE DEALLOCATE (VAR addr: SYSTEM.ADDRESS; amount: CARDINAL);
  (* Makes an area of storage currently available to the program
     inaccessible, and assigns the value NIL to addr.  On entry addr must be
     an address of an area of storage previously delivered by ALLOCATE, whose
     size, in units of SYSTEM.LOC, is given by amount.
  *)

TYPE
  StorageExceptions =
  (nilDeallocation,  pointerToUnallocatedStorage, wrongStorageToUnallocate);

PROCEDURE StorageException (): StorageExceptions;
  (* Returns a value indicating which exception has been raised by
     the module Storage.
  *)

PROCEDURE IsStorageException (): BOOLEAN;
  (* Returns TRUE iff an exception has been raised by the module Storage *)

END Storage.
"Storage" is the base module for heap management. The procedures "ALLOCATE" and "DEALLOCATE" fullfil all the compiler requirements, to be used as replacement for "NEW" and "DISPOSE".

"ALLOCATE" reserves an area of "n" LOCs on the heap and returns the starting address in "v", if sufficient space is available. Otherwise, "NIL" is returned in "v".

"DEALLOCATE" frees the storage area starting at "v" and length "n". The following exceptions may occur:

The procedure "IsStorageException" returns, whether an exception has been raised by "Storage". In this case, "StorageExceptions" returns the reason for the exception.

"Storage" uses its own management for the heap portions and is therefore faster than the heap procedures provided by the system.

1.1.2 LowReal

DEFINITION MODULE LowReal;

  (* Access to underlying properties of the type REAL *)

CONST
  radix =      2;
  places =     24;
  expoMin =    -126;
  expoMax =    127;
  large =      MAX (REAL);
  small =      1.2E-38;
  IEEE =       TRUE;
  ISO =        TRUE;
  rounds =     TRUE;
  gUnderflow = TRUE;
  exception =  TRUE;
  extend =     <TRUE for ppc and FALSE for i386>;
  nModes =     32;

TYPE
  Modes = SET OF [0 .. nModes-1];

PROCEDURE IsLowException (): BOOLEAN;
  (* Returns TRUE iff an exception has been raised by the module LowReal *)
 
PROCEDURE exponent (x: REAL): INTEGER;
  (* Returns the exponent value of x *)

PROCEDURE fraction (x: REAL): REAL;
  (* Returns the significand or mantissa part of x *)
  
PROCEDURE sign (x: REAL): REAL;
  (* Returns the signum of x *)

PROCEDURE succ (x: REAL): REAL;
  (* Returns the next value of the type REAL greater than x *)

PROCEDURE ulp (x: REAL): REAL;
  (* Returns the value of the last digit of x *)

PROCEDURE pred (x: REAL): REAL;
  (* Returns the previous value of the type REAL less than x *)

PROCEDURE intpart (x: REAL): REAL;
  (* Returns the integer part of x *)

PROCEDURE fractpart (x: REAL): REAL;
  (* Returns the fractional part of x *)

PROCEDURE scale (x: REAL; n: INTEGER): REAL;
  (* Returns the value of x * radix ** n *)

PROCEDURE trunc (x: REAL; n: INTEGER): REAL;
  (* Returns the value of the first n places of x *)

PROCEDURE round (x: REAL; n: INTEGER): REAL;
  (* Returns the value of x rounded to the first n places *)

PROCEDURE synthesize (exponent: INTEGER; fraction: REAL): REAL;
  (* Returns a value of the type REAL constructed from the given exponent and
     fraction *)

PROCEDURE setMode (m: Modes);
  (* Sets status flags appropriate to the underlying implementation of the
     type REAL *)

PROCEDURE currentMode (): Modes;
  (* Returns the current status flags in the form set by setMode *)

END LowReal.
The module "LowReal" defines the properties of the type "REAL" (representation, boundaries, arithmetic behavior). Additionally, procedures for the direct analysis and manipulation of values of type "REAL" are provided.

p1 Modula-2 uses the IEEE conforming FPU ("IEEE = TRUE") in mode "RoundToNearest" ("rounds = TRUE"), allows non normalized numbers ("gUnderflow = TRUE") and raises exceptions ("exception = TRUE") if necessary. For ppc, all intermediate values are stored in double precision format ("extended = TRUE"), whereas for i386 all intermediate values are stored in single precision format ("extended = FALSE"). Infinities are included in type "REAL".

The type "Mode" is a direct representation of the FPU control register "FPSCR" resp. the the MMX control register "MXCSR".

1.1.3 LowLong

DEFINITION MODULE LowLong;

  (* Access to underlying properties of the type LONGREAL *)

CONST
  radix =      2;
  places =     53;
  expoMin =    -1022;
  expoMax =    1023;
  large =      MAX (LONGREAL);
  small =      2.2E-308;
  IEEE =       TRUE;
  ISO =        TRUE;
  rounds =     TRUE;
  gUnderflow = TRUE;
  exception =  TRUE;
  extend =     FALSE;
  nModes =     32;

TYPE
  Modes = SET OF [0 .. nModes-1];

PROCEDURE IsLowException (): BOOLEAN;
  (* Returns TRUE iff an exception has been raised by the module LowLong *)

PROCEDURE exponent (x: LONGREAL): INTEGER;
  (* Returns the exponent value of x *)

PROCEDURE fraction (x: LONGREAL): LONGREAL;
  (* Returns the significand or mantissa part of x *)

PROCEDURE sign (x: LONGREAL): LONGREAL;
  (* Returns the signum of x *)

PROCEDURE succ (x: LONGREAL): LONGREAL;
  (* Returns the next value of the type LONGREAL greater than x *)

PROCEDURE ulp (x: LONGREAL): LONGREAL;
  (* Returns the value of the last digit of x *)

PROCEDURE pred (x: LONGREAL): LONGREAL;
  (* Returns the previous value of the type LONGREAL less than x *)

PROCEDURE intpart (x: LONGREAL): LONGREAL;
  (* Returns the integer part of x *)

PROCEDURE fractpart (x: LONGREAL): LONGREAL;
  (* Returns the fractional part of x *)

PROCEDURE scale (x: LONGREAL; n: INTEGER): LONGREAL;
  (* Returns the value of x * radix ** n *)

PROCEDURE trunc (x: LONGREAL; n: INTEGER): LONGREAL;
  (* Returns the value of the first n places of x *)

PROCEDURE round (x: LONGREAL; n: INTEGER): LONGREAL;
  (* Returns the value of x rounded to the first n places *)

PROCEDURE synthesize (exponent: INTEGER; fraction: LONGREAL): LONGREAL;
  (* Returns a value of the type LONGREAL constructed from the given exponent
     and fraction *)

PROCEDURE setMode (m: Modes);
  (* Sets status flags appropriate to the underlying implementation of the
     type LONGREAL *)

PROCEDURE currentMode (): Modes;
  (* Returns the current status flags in the form set by setMode *)

END LowLong.
The module "LowLong" corresponds in form and contents exactly the module "LowReal". The main difference is, that it describes the properties of type "LONGREAL".

The only real difference is the value of the constant "extend": the value of this constant is "FALSE" as the intermediate results are stored with the same precision as the result.

1.1.4 CharClass

DEFINITION MODULE CharClass;

  (* Classification of values of the pervasive type CHAR *)

PROCEDURE IsNumeric (ch: CHAR): BOOLEAN;
  (* Tests if ch is classified as a numeric character *)

PROCEDURE IsLetter (ch: CHAR): BOOLEAN;
  (* Tests if ch is classified as a letter *)

PROCEDURE IsUpper (ch: CHAR): BOOLEAN;
  (* Tests if ch is classified as an upper case letter *)

PROCEDURE IsLower (ch: CHAR): BOOLEAN;
  (* Tests if ch is classified as a lower case letter *)

PROCEDURE IsControl (ch: CHAR): BOOLEAN;
  (* Tests if ch represents a control function *)

PROCEDURE IsWhiteSpace (ch: CHAR): BOOLEAN;
  (* Tests if ch represents either a space character or a format effector *)

END CharClass.
The module "CharClass" defines some classes of values for type "CHAR". This division is given as information for the user; within the standard library no reference is made to this module (e.g. "TextIO. ReadToken" uses only " " as delimiter, not "IsWhiteSpace").

p1 Modula-2 treats only 7-bit ASCII values as letters. Besides Blank, also Tabs, line feeds, form feeds and carriage returns are treated as "WhiteSpace". This results in:
IsNumeric"0" ≤ ch ≤ "9"
IsLetter"A" ≤ ch ≤ "Z" ∨ "a" ≤ ch ≤ "z"
IsUpper"A" ≤ ch ≤ "Z"
IsLower"a" ≤ ch ≤ "z"
IsControlch < " "
IsWhiteSpacech = " " ∨ ch = 11C ∨ ch = 12C ∨ ch = 14C ∨ ch = 15C (* Tab, LF, FF, CR *)

1.2 The Mathematical Libraries

1.2.1 RealMath

DEFINITION MODULE RealMath;

  (* Mathematical functions for the type REAL *)

CONST
  pi   = 3.1415926535897932384626433832795028841972;
  exp1 = 2.7182818284590452353602874713526624977572;

PROCEDURE IsRMathException (): BOOLEAN;
  (* Returns TRUE iff an exception has been raised by the module RealMath *)

PROCEDURE sqrt (x: REAL): REAL;
  (* Returns the positive square root of x *)

PROCEDURE exp (x: REAL): REAL;
  (* Returns the exponential of x *)

PROCEDURE ln (x: REAL): REAL;
  (* Returns the natural logarithm of x *)

  (* The angle in all trigonometric functions is measured in radians *)

PROCEDURE sin (x: REAL): REAL;
  (* Returns the sine of x *)

PROCEDURE cos (x: REAL): REAL;
  (* Returns the cosine of x *)

PROCEDURE tan (x: REAL): REAL;
  (* Returns the tangent of x *)

PROCEDURE arcsin (x: REAL): REAL;
  (* Returns the arcsine of x *)

PROCEDURE arccos (x: REAL): REAL;
  (* Returns the arccosine of x *)

PROCEDURE arctan (x: REAL): REAL;
  (* Returns the arctangent of x *)

PROCEDURE power (base, exponent: REAL): REAL;
  (* Returns the value of the number base raised to the power exponent *)

PROCEDURE round (x: REAL): INTEGER;
  (* Returns the value of x rounded to the next integer *)

END RealMath.
"RealMath" implements the mathematical functions square root, exponential function with base e, natural logarithm, sine, cosine, tangent, their reverse functions, "power" for all exponentiations and "round" for the normal rounding mode.

The trigonometric functions have arguments and results in radians.

Exceptions are raised if either a function is call with illegal arguments ("sqrt", "ln", "tan", "arcsin", "arccos", "power") or the result cannot be expressed as values of type "REAL" ("exp", "ln", "tan", "power").

Details tools:
The functions are implemented with the according functions of the runtime interface "math.h".

Details Carbon applications:
The functions are implemented with the according functions of the runtime module "fp.h".

1.2.2 LongMath

DEFINITION MODULE LongMath;

  (* Mathematical functions for the type LONGREAL *)

CONST
  pi   = 3.1415926535897932384626433832795028841972;
  exp1 = 2.7182818284590452353602874713526624977572;

PROCEDURE IsRMathException (): BOOLEAN;
  (* Returns TRUE iff an exception has been raised by the module LongRealMath *)

PROCEDURE sqrt (x: LONGREAL): LONGREAL;
  (* Returns the positive square root of x *)

PROCEDURE exp (x: LONGREAL): LONGREAL;
  (* Returns the exponential of x *)

PROCEDURE ln (x: LONGREAL): LONGREAL;
  (* Returns the natural logarithm of x *)

  (* The angle in all trigonometric functions is measured in radians *)

PROCEDURE sin (x: LONGREAL): LONGREAL;
  (* Returns the sine of x *)

PROCEDURE cos (x: LONGREAL): LONGREAL;
  (* Returns the cosine of x *)

PROCEDURE tan (x: LONGREAL): LONGREAL;
  (* Returns the tangent of x *)

PROCEDURE arcsin (x: LONGREAL): LONGREAL;
  (* Returns the arcsine of x *)

PROCEDURE arccos (x: LONGREAL): LONGREAL;
  (* Returns the arccosine of x *)

PROCEDURE arctan (x: LONGREAL): LONGREAL;
  (* Returns the arctangent of x *)

PROCEDURE power (base, exponent: LONGREAL): LONGREAL;
  (* Returns the value of the number base raised to the power exponent *)

PROCEDURE round (x: LONGREAL): INTEGER;
  (* Returns the value of x rounded to the next integer *)

END LongMath.
"LongMath" corresponds "RealMath" for type "LONGREAL".

1.2.3 ComplexMath

DEFINITION MODULE ComplexMath;

  (* Mathematical functions for the type COMPLEX *)
 
CONST
  i =    CMPLX (0.0, 1.0);
  one =  CMPLX (1.0, 0.0);
  zero = CMPLX (0.0, 0.0);

PROCEDURE IsCMathException(): BOOLEAN;
  (* Returns TRUE iff an exception has been raised by the module ComplexMath
  *)

PROCEDURE abs (z: COMPLEX): REAL;
  (* Returns the length of z *)

PROCEDURE arg (z: COMPLEX): REAL;
  (* Returns the angle that z subtends to the positive real axis *)
 
PROCEDURE conj (z: COMPLEX): COMPLEX;
  (* Returns the complex conjugate of z *)
 
PROCEDURE power (base: COMPLEX; exponent: REAL): COMPLEX;
  (* Returns the value of the number base raised to the power exponent *)

PROCEDURE sqrt (z: COMPLEX): COMPLEX;
  (* Returns the principal square root of z *)

PROCEDURE exp (z: COMPLEX): COMPLEX;
  (* Returns the complex exponential of z *)

PROCEDURE ln (z: COMPLEX): COMPLEX;
  (* Returns the principal value of the natural logarithm of z *)

PROCEDURE sin (z: COMPLEX): COMPLEX;
  (* Returns the sine of z *)

PROCEDURE cos (z: COMPLEX): COMPLEX;
  (* Returns the cosine of z *)

PROCEDURE tan (z: COMPLEX): COMPLEX;
  (* Returns the tangent of z *)

PROCEDURE arcsin (z: COMPLEX): COMPLEX;
  (* Returns the arcsine of z *)

PROCEDURE arccos (z: COMPLEX): COMPLEX;
  (* Returns the arccosine of z *)

PROCEDURE arctan (z: COMPLEX): COMPLEX;
  (* Returns the arctangent of z *)

PROCEDURE polarToComplex (abs, arg: REAL): COMPLEX;
  (* Returns the complex number with the specified polar coordinates *)

PROCEDURE scalarMult (scalar: REAL; z: COMPLEX): COMPLEX;
  (* Returns the scalar product of scalar with z *)

END ComplexMath.
"ComplexMath" supports the most common functions for complex numbers. The many-valued functions ("ln", "arcsin", "arccos", arctan") return—as usual—the principal value.

1.2.4 LongComplexMath

DEFINITION MODULE LongComplexMath;

  (* Mathematical functions for the type LONGCOMPLEX *)
 
CONST
  i =    CMPLX (0.0, 1.0);
  one =  CMPLX (1.0, 0.0);
  zero = CMPLX (0.0, 0.0);

PROCEDURE IsCMathException(): BOOLEAN;
  (* Returns TRUE iff an exception has been raised by the module
     LongComplexMath *)

PROCEDURE abs (z: LONGCOMPLEX): LONGREAL;
  (* Returns the length of z *)

PROCEDURE arg (z: LONGCOMPLEX): LONGREAL;
  (* Returns the angle that z subtends to the positive real axis *)
 
PROCEDURE conj (z: LONGCOMPLEX): LONGCOMPLEX;
  (* Returns the complex conjugate of z *)
 
PROCEDURE power (base: LONGCOMPLEX; exponent: LONGREAL): LONGCOMPLEX;
  (* Returns the value of the number base raised to the power exponent *)

PROCEDURE sqrt (z: LONGCOMPLEX): LONGCOMPLEX;
  (* Returns the principal square root of z *)

PROCEDURE exp (z: LONGCOMPLEX): LONGCOMPLEX;
  (* Returns the complex exponential of z *)

PROCEDURE ln (z: LONGCOMPLEX): LONGCOMPLEX;
  (* Returns the principal value of the natural logarithm of z *)

PROCEDURE sin (z: LONGCOMPLEX): LONGCOMPLEX;
  (* Returns the sine of z *)

PROCEDURE cos (z: LONGCOMPLEX): LONGCOMPLEX;
  (* Returns the cosine of z *)

PROCEDURE tan (z: LONGCOMPLEX): LONGCOMPLEX;
  (* Returns the tangent of z *)

PROCEDURE arcsin (z: LONGCOMPLEX): LONGCOMPLEX;
  (* Returns the arcsine of z *)

PROCEDURE arccos (z: LONGCOMPLEX): LONGCOMPLEX;
  (* Returns the arccosine of z *)

PROCEDURE arctan (z: LONGCOMPLEX): LONGCOMPLEX;
  (* Returns the arctangent of z *)

PROCEDURE polarToComplex (abs, arg: LONGREAL): LONGCOMPLEX;
  (* Returns the complex number with the specified polar coordinates *)

PROCEDURE scalarMult (scalar: LONGREAL; z: LONGCOMPLEX): LONGCOMPLEX;
  (* Returns the scalar product of scalar with z *)

END LongComplexMath.
Corresponds with "ComplexMath" for complex numbers of type "LONGCOMPLEX".

1.3 The Input / Output Library

The base principle of the IO library described in the standard is the management of io channels. Data is transported via this channels to and from abstract "devices" (files of various forms, terminals, serial lines, etc.). Because of this principle, uninterpreted ("raw") and interpreted ("as text") access to the data is possible for all devices (with their various features like random access, parallel read and write etc.). Thus, a restricting division e.g. in sequential text files and binary files with random access could be avoided. Machine or system specific "devices types" can be added easily and portably as well as data transfer modules for special data types. These possibilities for extensions are used by p1 Modula-2 (cf. chapter 2.1, "Extensions to the Standard Library").

The IO library may be divided into three groups.

The following graphic is a short summary of the modules. Bold borders and normal borders distinguish between subgroups within the main group (cf. text above).

In the following chapters, the modules are described in lexical order.

The implementation of the io library of p1 Modula-2 has two aspects worth knowing for the user, the implementation of the standard channels and the implementation of type "ChanId", variables of which identify the open channels.

1.3.1 ChanConsts

DEFINITION MODULE ChanConsts;
 
  (* Common types and values for channel open requests and results *)
 
  (* Device modules may allow combinations of the following flags to be given
     when a channel is opened.  A channel opening procedure may not be able
     to accept or honour all combinations.
  *)
 
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
                 *)
  );
 
  FlagSet = SET OF ChanFlags;
 
  (* Singleton values of FlagSet, to allow for example, read + write *)
 
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 *)
 
  (* Possible results of open requests *)
 
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 *)
    );
 
END ChanConsts.
The type "ChanFlags" describes the properties of an open channel or the desired properties of a channel to open. All properties of an open channel are stores for this channel in a field of type "FlagSet". The flags are also provided as single element sets for use with the open procedures.

The type "OpenResults" is used as result parameter to signal possible errors while opening a channel. The result "opened" indicates, that the channel could be opened with the desired properties. All other results indicate an error during opening. In these cases the returned channel identifier has the value of "IOChan. InvalidChan ()".

The flags relevant to a device module and the type "OpenResults" are reexported by each device module, so that the user will have to import directly from this module only in rare cases.

1.3.2 IOChan

DEFINITION MODULE IOChan;
 
  (* Types and procedures forming the interface to channels for device-
     independent data transfer modules
  *)
 
IMPORT IOConsts, ChanConsts, SYSTEM;
 
TYPE
  ChanId; (* Values of this type are used to identify channels *)
 
  (* There is one pre-defined value identifying an invalid channel on which
     no data transfer operations are available.  It may be used to initialize
     variables of type ChanId.
  *)
 
PROCEDURE InvalidChan (): ChanId;
  (* Returns the value identifying the invalid channel. *)
 
  (* For each of the following operations, if the device supports the
     operation on the channel, the behaviour of the procedure conforms with
     the description below.  The full behaviour is defined for each device
     module.  If the device does not support the operation on the channel,
     the behaviour of the procedure is to raise the exception notAvailable.
  *)
 
 
  (* Text operations - these perform any required translation between the
     internal and external representation of text.
  *)
 
PROCEDURE Look (cid: ChanId; VAR ch: CHAR; VAR res: IOConsts.ReadResults);
  (* If there is a character as the next item in the input stream cid,
     assigns its value to ch without removing it from the stream; otherwise
     the value of ch is not defined.  res (and the stored read result) are
     set to the value allRight, endOfLine, or endOfInput.
  *)
 
PROCEDURE Skip (cid: ChanId);
  (* If the input stream cid has ended, the exception skipAtEnd is raised;
     otherwise the next character or line mark in cid is removed, and the
     stored read result is set to the value allRight.
  *)
 
PROCEDURE SkipLook (cid: ChanId; VAR ch: CHAR;
                    VAR res: IOConsts.ReadResults);
  (* If the input stream cid has ended, the exception skipAtEnd is raised;
     otherwise the next character or line mark in cid is removed.  If there
     is a character as the next item in cid stream, assigns its value to ch
     without removing it from the stream. Otherwise, the value of ch is not
     defined.  res (and the stored read result) are set to the value
     allRight, endOfLine, or endOfInput.
  *)
 
PROCEDURE TextRead (cid: ChanId; to: SYSTEM.ADDRESS; maxChars: CARDINAL;
                    VAR charsRead: CARDINAL);
  (* Reads at most maxChars characters from the current line in cid, and
     assigns corresponding values to successive locations, starting at the
     address given by to, and continuing thereafter at increments
     corresponding to the address difference between successive components of
     an ARRAY OF CHAR. The number of characters read is assigned to
     charsRead. The stored read result is set to the value allRight,
     endOfLine, or endOfInput.
  *)
 
PROCEDURE TextWrite (cid: ChanId; from: SYSTEM.ADDRESS;
                     charsToWrite: CARDINAL);
  (* Writes a number of characters given by the value of charsToWrite,
     starting at the address given by from, and continuing thereafter at
     increments corresponding to the address difference between successive
     components of an ARRAY OF CHAR.
  *)
 
PROCEDURE WriteLn (cid: ChanId);
  (* Writes a line mark over the channel cid. *)
 
  (* Direct raw operations  - these do not effect translation between the
     internal and external representation of data
  *)
 
PROCEDURE RawRead (cid: ChanId; to: SYSTEM.ADDRESS; maxLocs: CARDINAL;
                   VAR locsRead: CARDINAL);
  (* Reads at most maxLocs items from cid, and assigns corresponding values
     to successive locations, starting at the address given by to.  The
     number of items read is assigned to locsRead.  The stored read result is
     set to the value allRight, or endOfInput.
  *)
 
PROCEDURE RawWrite (cid: ChanId; from: SYSTEM.ADDRESS;
                    locsToWrite: CARDINAL);
  (* Writes a number of items to cid, given by the value of locsToWrite, from
     successive locations starting at the address given by from.
  *)
 
  (* Common operations *)
 
PROCEDURE GetName (cid: ChanId; VAR s: ARRAY OF CHAR);
  (* Copies to s a name associated with the channel cid, possibly truncated
     (depending on the capacity of s).
  *)
 
PROCEDURE Reset (cid: ChanId);
  (* Resets the channel cid to a state defined by the device module. *)
 
PROCEDURE Flush (cid: ChanId);
  (* Flushes any data buffered by the device module out to the channel cid.*)
 
  (* Access to read results *)
 
PROCEDURE SetReadResult (cid: ChanId; res: IOConsts.ReadResults);
  (* Sets the read result value for the channel cid to the value res. *)
 
PROCEDURE ReadResult (cid: ChanId): IOConsts.ReadResults;
  (* Returns the stored read result value for the channel cid. (This is
     initially the value notKnown).
  *)

  (* Users can discover which flags actually apply to a channel *)
 
PROCEDURE CurrentFlags (cid: ChanId): ChanConsts.FlagSet;
  (* Returns the set of flags that currently apply to the channel cid. *)

  (* The following exceptions are defined for this module and its clients *)
 
TYPE
  ChanExceptions =
    (wrongDevice,     (* device specific operation on wrong device *)
     notAvailable,    (* operation attempted that is not available on that
                         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 *)
    );
 
PROCEDURE ChanException (): ChanExceptions;
  (* Returns the ChanExceptions value for the current context. *)
 
PROCEDURE IsChanException (): BOOLEAN;
  (* Returns whether a ChanException has been raised in the current context.
  *)
 
  (* When a device procedure detects a device error, it raises the exception
     softDeviceError or hardDeviceError.  If these exceptions are handled,
     the following facilities may be used to discover an implementation-
     defined error number for the channel.
  *)
 
TYPE
  DeviceErrNum = INTEGER;
 
PROCEDURE DeviceError (cid: ChanId): DeviceErrNum;
  (* If a device error exception has been raised for the channel cid, returns
     the error number stored by the device module.
  *)
 
END IOChan.
The module "IOChan" is the basic module of the front end of the io library. It implements procedural access to the elementary transfer procedures supplied by the device modules as well as some enquiry functions and the data types and procedures necessary for the exception handling.

Most users will not need to import directly from "IOChan".

The type "ChanId" is the type for identifiers of channels. The procedures "InvalidChan" returns the value of the "illegal channel", that is also returned e.g. from the open procedures of the device modules in case of an error.

The procedures "Look" and "Skip" implement the basic model for reading text. "Look" looks, which character (and if any) is the first character in the input stream and returns it without changing the state of that channel. Therefore "Look" never may cause errors. "Skip" removes the first character from the input stream. Calls to "Skip" at the end of a file result in the exception "skipAtEnd" being raised. "SkipLook" is a shortcut for the frequently used combination of "Skip; Look (...)". "TextRead" provides a more efficient possibility for reading strings than a repeated call of "Look" and "Skip".

"TextWrite" is used for the output of characters and strings. "WriteLn" writes a (device specific) end of line marker.

"RawRead" and "RawWrite" are the basic procedures for uninterpreted ("raw") data transfer.

"ReadResult" returns the state of the last read operation for the given channel. This state is set automatically by "Look", but may also be changed by "SetReadResult".

"GetName" returns the name of the device connected to the given channel. With p1 Modula-2, this is the full file name in the form "/folder_1/ … /folder_n/name". For channels not connected to files, the empty string is returned.

The reset operations done by "Reset" are device specific and explained within the device modules.

"Flush" ensures, that buffered data (if any) is written at once to the given device.

"CurrentFlags" allows to test for the actual properties of a channel.

Exceptions may be raised in the io library due to illegal channels, invalid operations, hardware errors or similar problems. The type "ChanExceptions" identifies the possible exceptions. "IsChanExceptions" returns, whether a exception has been raised by the io library. In this case, the function procedure "ChanException" returns the information about the current exception.

In the case of an exception, "DeviceError" returns the device specific error code stored with each channel. p1 Modula-2 stores the error code of the Macintosh runtime system in this field.

1.3.3 IOConsts

DEFINITION MODULE IOConsts;
 
  (* Types and constants for input/output modules *)
 
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 *)
  );
 
END IOConsts.
"IOConsts" defines the state type for read operations. This type has been put inside a separate module to avoid dependencies between other library modules. For the user, this type is reexported from "IOResult", description see there.

1.3.4 IOLink

DEFINITION MODULE IOLink;
 
  (* Types and procedures for the standard implementation of channels *)
 
IMPORT IOChan, IOConsts, ChanConsts, SYSTEM;
 
  (* Devices need to identify themselves in order to allow a check to be made
     that device-dependent operations are applied only for channels opened to
     that device.
  *)
 
TYPE
  DeviceId;
    (* Values of this type are used to identify new device modules, and are
       normally obtained by them during their initialization.
    *)
 
PROCEDURE AllocateDeviceId (VAR did: DeviceId);
  (* Allocates a unique value of type DeviceId, and assigns this value to
     did.
  *)
 
  (* A new device module open procedure obtains a channel by calling
     MakeChan.
  *)
 
 
PROCEDURE MakeChan (did: DeviceId; VAR cid: IOChan.ChanId);
  (* Attempts to make a new channel for the device module identified by did.
     If no more channels can be made, the identity of the invalid channel is
     assigned to cid. Otherwise, the identity of a new channel is assigned to
     cid.
  *)
 
  (* If a channel is allocated, but the call of the device module open
     procedure is not successful, or on a successful call of a device module
     close procedure, the device module unmakes the channel, and returns the
     value identifying the invalid channel to its client.
  *)
 
PROCEDURE UnMakeChan (did: DeviceId; VAR cid: IOChan.ChanId);
  (* If the device module identified by did is not the module that made the
     channel identified by cid, the exception wrongDevice is raised;
     otherwise the channel is deallocated, and the value identifying the
     invalid channel is assigned to cid.
  *)
 
  (* If the call of the device module open procedure is successful, the
     device module obtains a pointer to a device table for the channel, which
     will have been initialized by MakeChan.  It then changes the fields of
     the device table to install its own values for the device data,
     supported operations, and flags, and returns to its client the identity
     of the channel.
  *)
 
TYPE
  DeviceTablePtr = POINTER TO DeviceTable;
    (* Values of this type are used to refer to device tables *)
 
  (* Device modules supply procedures of the following types: *)
 
TYPE
  LookProc =      PROCEDURE (DeviceTablePtr, VAR CHAR,
                             VAR IOConsts.ReadResults);
  SkipProc =      PROCEDURE (DeviceTablePtr);
  SkipLookProc =  PROCEDURE (DeviceTablePtr, VAR CHAR,
                             VAR IOConsts.ReadResults);
  TextReadProc =  PROCEDURE (DeviceTablePtr, SYSTEM.ADDRESS, CARDINAL,
                             VAR CARDINAL);
  TextWriteProc = PROCEDURE (DeviceTablePtr, SYSTEM.ADDRESS, CARDINAL);
  WriteLnProc =   PROCEDURE (DeviceTablePtr);
  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.
      *)
 
 
  (* Device tables have:
     a field in which the device module can store private data,
     a field in which the value identifying the device module is stored,
     a field in which the value identifying the channel is stored,
     a field in which the read result is stored,
     a field in which device error numbers are stored prior to the raising of
       a device error exception,
     a field in which flags are stored indicating those which apply,
     a field for each device procedure.
 
     The fields are initialized by MakeChan to the values shown for the type
     DeviceTable.
  *)
 
TYPE
  DeviceData = SYSTEM.ADDRESS;
 
  DeviceTable =
    RECORD
      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;
 
  (* The pointer to the device table for a channel is obtained using the
     following procedure:
  *)
 
PROCEDURE DeviceTablePtrValue (cid: IOChan.ChanId; did: DeviceId):
                              DeviceTablePtr;
  (* If the device module identified by did is not the module that made the
     channel identified by cid, the exception wrongDevice is raised;
     otherwise returns a pointer to the device table for the channel.
  *)
 
 
  (* A device module can enquire whether it opened a given channel.  It does
     this to implement a corresponding enquiry function that is exported from
     the device module
  *)
 
PROCEDURE IsDevice (cid: IOChan.ChanId; did: DeviceId): BOOLEAN;
  (* Tests if the device module identified by did is the module that made the
     channel identified by cid.
  *)
 
 
  (* Client modules may raise appropriate exceptions *)
 
PROCEDURE RAISEdevException (cid: IOChan.ChanId; did: DeviceId;
                             x: IOChan.ChanExceptions; s: ARRAY OF CHAR);
  (* If the device module identified by did is not the module that made the
     channel identified by cid, the exception wrongDevice is raised;
     otherwise the given exception is raised, and the string value in s is
     included in the exception message.
  *)
 
PROCEDURE IOException (): IOChan.ChanExceptions;
  (* Returns the ChanExceptions value for the current context. *)
 
PROCEDURE IsIOException (): BOOLEAN;
  (* Returns whether a ChanException has been raised in the current context. *)
 
END IOLink.
"IOLink" is the base module for the device modules. It defines the data structures for the implementation of new devices, and supplies the auxiliary functions necessary to create and destroy a channel. Most users of the io library will not import from "IOLink", this module is used only for writing additional device modules.

"DevicdId" is a data type used to identify the various device modules. Every device module may allocate its specific identifier with "AllocateDeviceId".

"MakeChan" and "UnMakeChan" open and close channels.

"DeviceTable" (and "DeviceTablePtr") defines the common part of the data structure of each channel. Besides some status data, the procedures for data transfer are defined here. These procedures have to be provided by each device module. "IOChan" passes these procedures to the front end of the library. The device modules get access to the data structures of their own channels with "DeviceTablePtrValue". For safety purposes there is no possibility to access the data structures of any channel directly. With "IsDevice" a device module may test, whether a channel is one of its own.

The procedures "RAISEdevException" is provided for raising exceptions. It test whether the given channel is correct and if so, raises the exception "x". "IsIOException" allows to inform, whether an exception has been raised by the io library, "IOException" returns the exact exception. "IsIOException" and "IOException" are identical with "IOChan. IsChanException" and "IOChan. ChanException".

1.3.5 IOResult

DEFINITION MODULE IOResult;
 
  (* Read results for specified channels *)
 
IMPORT IOConsts, IOChan;
 
TYPE
  ReadResults = IOConsts.ReadResults;
 
  (*
    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 *)
    );
  *)
 
PROCEDURE ReadResult (cid: IOChan.ChanId): ReadResults;
  (* Returns the result for the last read operation on the channel cid. *)
 
END IOResult.
"IOResult" provides the procedure "ReadResult" and the type "ReadResults" for information about the read state of a given channel. The possible values are:
notKnownundefined state, e.g. before the first read operation.
allRightlast operation was successful.
outOfRangedata could not be represented, e.g string too small or number too large.
wrongFormatwrong format, e.g. on reading number
endOfLineno data read because of end of line (possible only with text operations).
endOfInputno data read because of end of file.

1.3.6 LongIO

DEFINITION MODULE LongIO;
 
  (* Input and output of long real numbers in decimal text form over
     specified channels. The read result is of the type IOConsts.ReadResults.
  *)
 
IMPORT IOChan;
 
  (* 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", ["+" | "-"], decimal digit, {decimal digit}
  *)
 
PROCEDURE ReadReal (cid: IOChan.ChanId; VAR real: LONGREAL);
  (* Skips leading spaces, and removes any remaining characters from cid that
     form part of a signed fixed or floating point number.  The value of this
     number is assigned to real.  The read result is set to the value
     allRight, outOfRange, wrongFormat, endOfLine, or endOfInput.
  *)
 
PROCEDURE WriteFloat (cid: IOChan.ChanId; real: LONGREAL; sigFigs: CARDINAL;
                      width: CARDINAL);
  (* Writes the value of real to cid in floating-point text form, with
     sigFigs significant figures, in a field of the given minimum width.
  *)
 
PROCEDURE WriteEng (cid: IOChan.ChanId; real: LONGREAL; sigFigs: CARDINAL;
                    width: CARDINAL);
  (* As for 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.
  *)
 
PROCEDURE WriteFixed (cid: IOChan.ChanId; real: LONGREAL; place: INTEGER;
                      width: CARDINAL);
  (* Writes the value of real to cid in fixed-point text form, rounded to the
     given place relative to the decimal point, in a field of the given
     minimum width.
  *)
 
PROCEDURE WriteReal (cid: IOChan.ChanId; real: LONGREAL; width: CARDINAL);
  (* Writes the value of real to cid, as WriteFixed if the sign and magnitude
     can be shown in the given width, or otherwise as WriteFloat.  The number
     of places or significant digits depends on the given width.
  *)
 
END LongIO.
The module "LongIO" is corresponds to "RealIO" for input and output of values of type "LONGREAL".

"ReadReal" reads a real number from the given channel and sets the read state to the according value.

"WriteFloat" writes a real number in scientific notation with the given number of significant digits. "WriteEng" is analogous to "WriteFloat", but sets the exponent to a multiple of three.

"WriteFixed" writes a real number in fixed point notation. "place" is the number of digits the number is rounded to. A value greater than 0 signifies digits right to the decimal point, a value less than 0 signifies digits left to the decimal point.

"WriteReal" writes a real number in fixed point notation, if "width" is large enough to take the number. Otherwise the number is written in scientific notation.

1.3.7 ProgramArgs

DEFINITION MODULE ProgramArgs;
 
  (* Access to program arguments *)
 
IMPORT IOChan;
 
TYPE
  ChanId = IOChan.ChanId;
 
PROCEDURE ArgChan (): ChanId;
  (* Returns a value that identifies a channel for reading program arguments
   *)
 
PROCEDURE IsArgPresent (): BOOLEAN;
  (* Tests if there is a current argument to read from. If not, read <=
     IOChan.CurrentFlags() will be FALSE, and attempting to read from the
     argument channel will raise the exception notAvailable.
  *)
 
PROCEDURE NextArg ();
  (* If there is another argument, causes subsequent input from the argument
     device to come from the start of the next argument.  Otherwise there is
     no argument to read from, and a call of IsArgPresent will return FALSE.
  *)
 
END ProgramArgs.
"ProgramArgs" provides access to the command line (of a MPW tool) via the channel returned by "ArgChan". "IsArgPresent" informs, wether there are (more) parameters available. "NextArg" switches to the next parameter.

For a application, "IsArgPresent" returns always "FALSE". Trying to read from the argument channel leads to the exception "notAvailable".

For command line tools the command line is split into arguments according to the shell rules. Each argument can be read separately until "IOResults. ReadResult" returns "endOfInput". "NextArg" switches to the next argument.

According to the shell conventions, the first argument is always the name of the tool.

"IOChan. Reset" switches back to the start of the argument list. Thus, multiple reads of the command line are possible.

1.3.8 RawIO

DEFINITION MODULE RawIO;
 
  (* Reading and writing data over specified channels using raw operations,
     that is, with no conversion or interpretation. The read result is of the
     type IOConsts.ReadResults.
  *)
 
IMPORT IOChan, SYSTEM;
 
PROCEDURE Read (cid: IOChan.ChanId; VAR to: ARRAY OF SYSTEM.LOC);
  (* Reads storage units from cid, and assigns them to successive components
     of to. The read result is set to the value allRight, wrongFormat, or
     endOfInput.
  *)
 
PROCEDURE Write (cid: IOChan.ChanId; from: ARRAY OF SYSTEM.LOC);
  (* Writes storage units to cid from successive components of from. *)
 
END RawIO.
"RawIO" is the "high level" module for uninterpreted ("raw") data transfer.

"Write" writes to the given channel.

"Read" reads the appropriate number of LOCs into the given array. If the end of the file is encountered before the array is filled, the read result is set to "wrongFormat". A read result of "endOfInput" indicates, that no data at all could be read.

1.3.9 RealIO

DEFINITION MODULE RealIO;
 
  (* Input and output of real numbers in decimal text form over specified
     channels. The read result is of the type IOConsts.ReadResults.
  *)
 
IMPORT IOChan;
 
  (* 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", ["+" | "-"], decimal digit, {decimal digit}
  *)
 
PROCEDURE ReadReal (cid: IOChan.ChanId; VAR real: REAL);
  (* Skips leading spaces, and removes any remaining characters from cid that
     form part of a signed fixed or floating point number.  The value of this
     number is assigned to real.  The read result is set to the value
     allRight, outOfRange, wrongFormat, endOfLine, or endOfInput.
  *)
 
PROCEDURE WriteFloat (cid: IOChan.ChanId; real: REAL; sigFigs: CARDINAL;
                      width: CARDINAL);
  (* Writes the value of real to cid in floating-point text form, with
     sigFigs significant figures, in a field of the given minimum width.
  *)
 
PROCEDURE WriteEng (cid: IOChan.ChanId; real: REAL; sigFigs: CARDINAL;
                    width: CARDINAL);
  (* As for 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.
  *)
 
PROCEDURE WriteFixed (cid: IOChan.ChanId; real: REAL; place: INTEGER;
                      width: CARDINAL);
  (* Writes the value of real to cid in fixed-point text form, rounded to the
     given place relative to the decimal point, in a field of the given
     minimum width.
  *)
 
PROCEDURE WriteReal (cid: IOChan.ChanId; real: REAL; width: CARDINAL);
  (* Writes the value of real to cid, as WriteFixed if the sign and magnitude
     can be shown in the given width, or otherwise as WriteFloat.  The number
     of places or significant digits depends on the given width.
  *)
 
END RealIO.
The module "RealIO" corresponds to "LongIO" for input and output of values of type "REAL".

"ReadReal" reads a real number from the given channel and sets the read state to the according value.

"WriteFloat" writes a real number in scientific notation with the given number of significant digits. "WriteEng" is analogous to "WriteFloat", but sets the exponent to a multiple of three.

"WriteFixed" writes a real number in fixed point notation. "place" is the number of digits the number is rounded to. A value greater than 0 signifies digits right to the decimal point, a value less than 0 signifies digits left to the decimal point.

"WriteReal" writes a real number in fixed point notation, if "width" is large enough to take the number. Otherwise the number is written in scientific notation.

1.3.10 RndFile

DEFINITION MODULE RndFile;
 
  (* Random access files *)
 
IMPORT IOChan, ChanConsts, SYSTEM;
 
TYPE
  ChanId = IOChan.ChanId;
  FlagSet = ChanConsts.FlagSet;
  OpenResults = ChanConsts.OpenResults;
 
  (* Accepted singleton values of FlagSet *)
 
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 *)

PROCEDURE OpenOld (VAR cid: ChanId; name: ARRAY OF CHAR; flags: FlagSet;
                   VAR res: OpenResults);
  (* Attempts to obtain and open a channel connected to a stored random
     access file of the given name.
     The old flag is implied; without the write flag, read is implied;
     without the text flag, raw is implied.
     If successful, assigns to cid the identity of the opened channel,
     assigns the value opened to res, and sets the read/write 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.
  *)
 
PROCEDURE OpenClean (VAR cid: ChanId; name: ARRAY OF CHAR; flags: FlagSet;
                     VAR res: OpenResults);
  (* Attempts to obtain and open a channel connected to a stored random
     access file of the given name.
     The write flag is implied; without the text flag, raw is implied.
     If successful, assigns to cid the identity of the opened channel,
     assigns the value opened to res, and truncates the file to zero length.
     If a channel cannot be opened as required, the value of res indicates
     the reason, and cid identifies the invalid channel.
  *)
 
PROCEDURE IsRndFile (cid: ChanId): BOOLEAN;
  (* Tests if the channel identified by cid is open to a random access file.
  *)
 
PROCEDURE IsRndFileException (): BOOLEAN;
  (* Returns TRUE iff an exception has been raised by the module RndFile *)
 
CONST
  FilePosSize = 8;
 
TYPE
  FilePos = ARRAY [1 .. FilePosSize] OF SYSTEM.LOC;
 
PROCEDURE StartPos (cid: ChanId): FilePos;
  (* If the channel identified by cid is not open to a random access file,
     the exception wrongDevice is raised; otherwise returns the position of
     the start of the file.
  *)
 
PROCEDURE CurrentPos (cid: ChanId): FilePos;
  (* If the channel identified by cid is not open to a random access file,
     the exception wrongDevice is raised; otherwise returns the position of
     the current read/write position.
  *)
 
PROCEDURE EndPos (cid: ChanId): FilePos;
  (* If the channel identified by cid is not open to a random access file,
     the exception wrongDevice is raised; otherwise returns the first
     position after which there have been no writes.
  *)
 
PROCEDURE NewPos (cid: ChanId; chunks: INTEGER; chunkSize: CARDINAL;
                  from: FilePos): FilePos;
  (* If the channel identified by cid is not open to a random access file,
     the exception wrongDevice is raised; otherwise returns the position
     (chunks * chunkSize) relative to the position given by from, or raises
     the exception posRange if the required position cannot be represented as
     a value of type FilePos.
  *)
 
PROCEDURE SetPos (cid: ChanId; pos: FilePos);
  (* If the channel identified by cid is not open to a random access file,
     the exception wrongDevice is raised; otherwise sets the read/write
     position to the value given by pos.
  *)
 
PROCEDURE Close (VAR cid: ChanId);
  (* If the channel identified by cid is not open to a random access file,
     the exception wrongDevice is raised; otherwise closes the channel, and
     assigns the value identifying the invalid channel to cid.
  *)
 
END RndFile.
The device module "RndFile" deals with random access files.

"OpenOld" opens a file that has to exist. If neither "write" nor "read" is passed in "flags", the files is opened for read access. If neither "text" nor "raw" is passed in "flags", only raw access is allowed. After successful opening, "cid" contains the opened channel, the read / write position is at the start of the file and "res" contains the value "opened". Otherwise, "res" indicates the error reason, and "cid" identifies the illegal channel.

"OpenClean" opens a file, that may exist only if "old" is given, and clears its contents if necessary. Write access is enabled automatically. If neither "text" nor "raw" is passed in "flags", only raw access is allowed. After successful opening, "cid" contains the opened channel, the read / write position is at the start of the file, and "res" contains the value "opened". Otherwise, "res" indicates the error reason, "cid" identifies the illegal channel.

"IsRndFile" tests whether a channel was opened by "RndFile".

An exception may be raised due to wrong positioning. "IsRndFileException" is the according enquiry function, a result of "TRUE" indicates a illegal file position.

File positions can be stored in variables of type "FilePos".

The procedure "StartPos" returns the position at the start of the file, "CurrentPos" returns the current read / write position, and "EndPos" the position after the last element in the file.

"NewPos" calculates a file position relative to "from". The distance is calculated from the element size "chunkSize" and the number of elements "chunks". A positive number of elements indicates a position towards the end of the file, a negative number of elements indicates a position towards the start of the file.

"NewPos" repositions the read / write marker within the file. As long as a file position is at the end of this file, read access is disabled

"Close" writes buffered data if necessary, closes the file, and destroys the assigned channel.

"IOChan. Reset (cid)" has the same effect as "SetPos (cid, StartPos (cid))".

For positioning in text files, the end-of-line marker (CR) counts as one character.

1.3.11 SeqFile

DEFINITION MODULE SeqFile;
 
  (* Rewindable sequential files *)
 
IMPORT IOChan, ChanConsts;
 
TYPE
  ChanId = IOChan.ChanId;
  FlagSet = ChanConsts.FlagSet;
  OpenResults = ChanConsts.OpenResults;
 
  (* Accepted singleton values of FlagSet *)
 
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 *)
 
PROCEDURE OpenWrite (VAR cid: ChanId; name: ARRAY OF CHAR; flags: FlagSet;
                     VAR res: OpenResults);
  (* Attempts to obtain and open a channel connected to a stored rewindable
     file of the given name.
     The write flag is implied; without the raw flag, text is implied.
     If successful, assigns to cid the identity of the opened channel,
     assigns the value opened to res, and selects output mode, with the write
     position at the start of the file (i.e. the file is of zero length).
     If a channel cannot be opened as required, the value of res indicates
     the reason, and cid identifies the invalid channel.
  *)
 
PROCEDURE OpenAppend (VAR cid: ChanId; name: ARRAY OF CHAR; flags: FlagSet;
                      VAR res: OpenResults);
  (* Attempts to obtain and open a channel connected to a stored rewindable
     file of the given name.
     The write and old flags are implied; without the raw flag, text is
     implied.  If successful, assigns to cid the identity of the opened
     channel, assigns the value opened to res, and selects output mode, with
     the write position corresponding to the length of the file.
     If a channel cannot be opened as required, the value of res indicates
     the reason, and cid identifies the invalid channel.
  *)
 
PROCEDURE OpenRead (VAR cid: ChanId; name: ARRAY OF CHAR; flags: FlagSet;
                    VAR res: OpenResults);
  (* Attempts to obtain and open a channel connected to a stored rewindable
     file of the given name.
     The read and old flags are implied; without the raw flag, text is
     implied. If successful, assigns to cid the identity of the opened
     channel, assigns the value opened to res, and selects input mode, with
     the read position corresponding 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.
  *)
 
PROCEDURE IsSeqFile (cid: ChanId): BOOLEAN;
  (* Tests if the channel identified by cid is open to a rewindable
     sequential file.
   *)
 
PROCEDURE Reread (cid: ChanId);
  (* If the channel identified by cid is not open to a rewindable sequential
     file, the exception wrongDevice is raised; otherwise attempts to set the
     read position to the start of the file, and to select input mode.
     If the operation cannot be performed (perhaps because of insufficient
     permissions) neither input mode nor output mode is selected.
  *)
 
PROCEDURE Rewrite (cid: ChanId);
  (* If the channel identified by cid is not open to a rewindable sequential
     file, the exception wrongDevice is raised; otherwise, attempts to
     truncate the file to zero length, and to select output mode.
     If the operation cannot be performed (perhaps because of insufficient
     permissions) neither input mode nor output mode is selected.
  *)
 
PROCEDURE Close (VAR cid: ChanId);
  (* If the channel identified by cid is not open to a rewindable sequential
     file, the exception wrongDevice is raised; otherwise closes the channel,
     and assigns the value identifying the invalid channel to cid.
  *)
 
END SeqFile.
The device module "SeqFile" deals with sequential files that allow positioning at the start or end of the file. An open channel is either in read or in write mode. Switching is possible (if the necessary flags were specified at opening of the file) via "Reread" or "Rewrite".

"OpenWrite" opens a file, that may exist only if "old" is given. Write access is enabled automatically. If neither "text" nor "raw" is passed in "flags", only text access is allowed. After successful opening, "cid" contains the opened channel, the write position is at the start of the file and "res" contains the value "opened". Otherwise, "res" indicates the error reason, and "cid" identifies the illegal channel.

"OpenAppend" opens a file that has to exist. Write access is enabled automatically. If neither "text" nor "raw" is passed in "flags", only text access is allowed. After successful opening, "cid" contains the opened channel, the write position is at the end of the file, and "res" contains the value "opened". Otherwise, "res" indicates the error reason and "cid" identifies the illegal channel.

"OpenRead" opens a file that has to exist. Read access is enabled automatically. If neither "text" nor "raw" is passed in "flags", only text access is allowed. After successful opening, "cid" contains the opened channel, the read position is at the start of the file, and "res" contains the value "opened". Otherwise, "res" indicates the error reason and "cid" identifies the illegal channel.

"IsSeqFile" tests whether a channel has been opened by "SeqFile".

If read access is specified, "Reread" positions to the start of the file and switches to read mode. Analogous, if write access is specified, "Rewrite" positions to the start of the file and switches to write mode.

"Close" writes buffered data if necessary, closes the file, and destroys the assigned channel.

"IOChan. Reset (cid)" has the same effekt as "Reread" or "Rewrite", depending on the mode (read or write).

1.3.12 SIOResult

DEFINITION MODULE SIOResult;
 
  (* Read results for the default input channel *)
 
IMPORT IOConsts;
 
TYPE
  ReadResults = IOConsts.ReadResults;
 
  (*
    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 *)
    );
  *)
 
PROCEDURE ReadResult (): ReadResults;
  (* Returns the result for the last read operation on the default input
     channel.
  *)
 
END SIOResult.
"SIOResult" implements the same functionality as "IOResult", but returns always the state of the standard input channel.

1.3.13 SLongIO

DEFINITION MODULE SLongIO;
 
  (* Input and output of long real numbers in decimal text form using default
     channels.  The read result is of the type IOConsts.ReadResults.
  *)

  (* 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", ["+" | "-"], decimal digit, {decimal digit}
  *)
 
PROCEDURE ReadReal (VAR real: LONGREAL);
  (* Skips leading spaces, and removes any remaining characters from the
     default input channel that form part of a signed fixed or floating point
     number. The value of this number is assigned to real.  The read result
     is set to the value allRight, outOfRange, wrongFormat, endOfLine, or
     endOfInput.
  *)
 
PROCEDURE WriteFloat (real: LONGREAL; sigFigs: CARDINAL; width: CARDINAL);
  (* Writes the value of real to the default output channel in floating-point
     text form, with sigFigs significant figures, in a field of the given
     minimum width.
  *)
 
PROCEDURE WriteEng (real: LONGREAL; sigFigs: CARDINAL; width: CARDINAL);
  (* As for 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.
  *)
 
PROCEDURE WriteFixed (real: LONGREAL; place: INTEGER; width: CARDINAL);
  (* Writes the value of real to the default output channel in fixed-point
     text form, rounded to the given place relative to the decimal point, in
     a field of the given minimum width.
  *)
 
PROCEDURE WriteReal (real: LONGREAL; width: CARDINAL);
  (* Writes the value of real to the default output channel, as WriteFixed if
     the sign and magnitude can be shown in the given width, or otherwise as
     WriteFloat.  The number of places or significant digits depends on the
     given width.
  *)
 
END SLongIO.
"SLongIO" is the equivalent to "LongIO" with predefined standard in- and outchannel.

1.3.14 SRawIO

DEFINITION MODULE SRawIO;
 
  (* Reading and writing data over default channels using raw operations,
     that is, with no conversion or interpretation. The read result is of the
     type IOConsts.ReadResults.
  *)
 
IMPORT SYSTEM;
 
PROCEDURE Read (VAR to: ARRAY OF SYSTEM.LOC);
  (* Reads storage units from the default input channel, and assigns them to
     successive components of to.  The read result is set to the value
     allRight, wrongFormat, or endOfInput.
  *)
 
PROCEDURE Write (from: ARRAY OF SYSTEM.LOC);
  (* Writes storage units to the default output channel from successive
     components of from.
  *)
 
END SRawIO.
"SRawIO" is the equivalent to "RawIO" with predefined standard in- and outchannel.

1.3.15 SRealIO

DEFINITION MODULE SRealIO;
 
  (* Input and output of real numbers in decimal text form over default
     channels.  The read result is of the type IOConsts.ReadResults.
  *)

  (* 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", ["+" | "-"], decimal digit, {decimal digit}
  *)
 
PROCEDURE ReadReal (VAR real: REAL);
  (* Skips leading spaces, and removes any remaining characters from the
     default output channel that form part of a signed fixed or floating
     point number. The value of this number is assigned to real.  The read
     result is set to the value allRight, outOfRange, wrongFormat, endOfLine,
     or endOfInput.
  *)
 
PROCEDURE WriteFloat (real: REAL; sigFigs: CARDINAL; width: CARDINAL);
  (* Writes the value of real to the default output channel in floating-point
     text form, with sigFigs significant figures, in a field of the given
     minimum width.
  *)
 
PROCEDURE WriteEng (real: REAL; sigFigs: CARDINAL; width: CARDINAL);
  (* As for 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.
  *)
 
PROCEDURE WriteFixed (real: REAL; place: INTEGER; width: CARDINAL);
  (* Writes the value of real to the default output channel in fixed-point
     text form, rounded to the given place relative to the decimal point, in
     a field of the given minimum width.
  *)
 
PROCEDURE WriteReal (real: REAL; width: CARDINAL);
  (* Writes the value of real to the default output channel, as WriteFixed if
     the sign and magnitude can be shown in the given width, or otherwise as
     WriteFloat.  The number of places or significant digits depends on the
     given width.
  *)
 
END SRealIO.
"SRealIO" is the equivalent to "RealIO" with predefined standard in- and outchannel.

1.3.16 StdChans

DEFINITION MODULE StdChans;
 
  (* Access to standard and default channels *)
 
IMPORT IOChan;
 
TYPE
  ChanId = IOChan.ChanId;
    (* Values of this type are used to identify channels *)
 
(* The following functions return the standard channel values.
   These channels cannot be closed.
*)
 
PROCEDURE StdInChan (): ChanId;
  (* Returns the identity of the implementation-defined standard source for
     program input.
  *)
 
PROCEDURE StdOutChan (): ChanId;
  (* Returns the identity of the implementation-defined standard source for
     program output.
  *)
 
PROCEDURE StdErrChan (): ChanId;
  (* Returns the identity of the implementation-defined standard destination
     for program error messages.
  *)
 
PROCEDURE NullChan (): ChanId;
  (* Returns the identity of a channel open to the null device. *)
 
  (* The following functions return the default channel values *)
 
PROCEDURE InChan (): ChanId;
  (* Returns the identity of the current default input channel. *)
 
PROCEDURE OutChan (): ChanId;
  (* Returns the identity of the current default output channel. *)
 
PROCEDURE ErrChan (): ChanId;
  (* Returns the identity of the current default error message channel. *)
 
  (* The following procedures allow for redirection of the default channels
  *)
 
PROCEDURE SetInChan (cid: ChanId);
  (* Sets the current default input channel to that identified by cid. *)
 
PROCEDURE SetOutChan (cid: ChanId);
  (* Sets the current default output channel to that identified by cid. *)
 
PROCEDURE SetErrChan (cid: ChanId);
  (* Sets the current default error channel to that identified by cid. *)
 
END StdChans.
"StdChans" manages the standard channels.

"StdInChan", "StdOutChan", and "StdErrChan" identify the predefined standard channels. For command line tools they are assigned to the corresponding channels of the operating system, all redirections in the command line are passed to the program. For applications a simple text window is assigned to these channels if necessary.

At the start of a program, "InChan", "OutChan", and "ErrChan" are assigned to "StdInChan", "StdOutChan", and "StdErrChan". The value of these channels can be changed with "SetInChan", "SetOutChan", and "SetErrChan". The S-modules use "InChan" and "OutChan".

"NullChan" is a waste basket. All written data is thrown away and reading results always in reaching "endOfInput".

1.3.17 STextIO

DEFINITION MODULE STextIO;
 
  (* Input and output of character and string types over default channels.
     The read result is of the type IOConsts.ReadResults.
  *)
 
  (* The following procedures do not read past line marks *)
 
PROCEDURE ReadChar (VAR ch: CHAR);
  (* If possible, removes a character from the default input stream, and
     assigns the corresponding value to ch.  The read result is set to
     allRight, endOfLine or endOfInput.
  *)
 
PROCEDURE ReadRestLine (VAR s: ARRAY OF CHAR);
  (* Removes any remaining characters from the default input stream before
     the next line mark, copying to s as many as can be accommodated as a
     string value.  The read result is set to the value allRight, outOfRange,
     endOfLine, or endOfInput.
  *)
 
PROCEDURE ReadString (VAR s: ARRAY OF CHAR);
  (* Removes only those characters from the default input stream before the
     next line mark that can be accommodated in s as a string value, and
     copies them to s.  The read result is set to the value allRight,
     endOfLine, or endOfInput.
  *)
 
PROCEDURE ReadToken (VAR s: ARRAY OF CHAR);
  (* Skips leading spaces, and then removes characters from the default input
     stream before the next space or line mark, copying to s as many as can
     be accommodated as a string value.  The read result is set to the value
     allRight, outOfRange, endOfLine, or endOfInput.
  *)
 
  (* The following procedure reads past the next line mark *)
 
PROCEDURE SkipLine;
  (* Removes successive items from the default input stream up to and
     including the next line mark or until the end of input is reached. The
     read result is set to the value allRight, or endOfInput.
  *)
 
 
  (* Output procedures *)
 
PROCEDURE WriteChar (ch: CHAR);
  (* Writes the value of ch to the default output stream. *)
 
PROCEDURE WriteLn;
  (* Writes a line mark to the default output stream. *)
 
PROCEDURE WriteString (s: ARRAY OF CHAR);
  (* Writes the string value of s to the default output stream. *)
 
END STextIO.
"STextIO" is the equivalent to "TextIO" with predefined standard in- and outchannel.

1.3.18 StreamFile

DEFINITION MODULE StreamFile;
 
  (* Independent sequential data streams *)
 
IMPORT IOChan, ChanConsts;
 
TYPE
  ChanId = IOChan.ChanId;
  FlagSet = ChanConsts.FlagSet;
  OpenResults = ChanConsts.OpenResults;
 
  (* Accepted singleton values of FlagSet *)
 
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 *)
 
 
PROCEDURE Open (VAR cid: ChanId; name: ARRAY OF CHAR; flags: FlagSet; VAR res: OpenResults);
  (* Attempts to obtain and open a channel connected to a sequential stream
     of the given name.
     The read flag implies old; without the raw flag, text is implied.
     If successful, assigns to cid the identity of the opened channel, and
     assigns the value opened to res.
     If a channel cannot be opened as required, the value of res indicates
     the reason, and cid identifies the invalid channel.
  *)
 
PROCEDURE IsStreamFile (cid: ChanId): BOOLEAN;
  (* Tests if the channel identified by cid is open to a sequential stream.
  *)
 
PROCEDURE Close (VAR cid: ChanId);
  (* If the channel identified by cid is not open to a sequential stream, the
     exception wrongDevice is raised; otherwise closes the channel, and
     assigns the value identifying the invalid channel to cid.
  *)
 
END StreamFile.
"StreamFile" models sequential data streams. As disk files allow only either reading or writing, parallel reading and writing is available only for ttys, serial lines etc.

"Open" opens a file for reading or writing exclusively (specification necessary). "read" implies "old" and needs a existing file. "write + old" has to be specified for rewriting a file. If neither "text" nor "raw" is passed in "flags", only text access is allowed. After successful opening, "cid" contains the opened channel, the file position is at the start of the file, and "res" contains the value "opened". Otherwise, "res" indicates the error reason and "cid" identifies the illegal channel.

"IsStreamFile" tests whether a channel has been opened by "StreamFile".

"Close" writes buffered data if necessary, closes the file, and destroys the assigned channel.

"IOChan. Reset (cid)" does nothing.

1.3.19 SWholeIO

DEFINITION MODULE SWholeIO;
 
  (* Input and output of whole numbers in decimal text form over default
     channels.  The read result is of the type IOConsts.ReadResults.
  *)
 
  (* 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}
  *)
 
PROCEDURE ReadInt (VAR int: INTEGER);
  (* Skips leading spaces, and removes any remaining characters from the
     default input channel that form part of a signed whole number.  The
     value of this number is assigned to int.  The read result is set to the
     value allRight, outOfRange, wrongFormat, endOfLine, or endOfInput.
  *)
 
PROCEDURE WriteInt (int: INTEGER; width: CARDINAL);
  (* Writes the value of int to the default output channel in text form, in a
     field of the given minimum width.
  *)
 
PROCEDURE ReadCard (VAR card: CARDINAL);
  (* Skips leading spaces, and removes any remaining characters from the
     default input channel that form part of an unsigned whole number.  The
     value of this number is assigned to card.  The read result is set to the
     value allRight, outOfRange, wrongFormat, endOfLine, or endOfInput.
  *)
 
PROCEDURE WriteCard (card: CARDINAL; width: CARDINAL);
  (* Writes the value of card to the default output channel in text form, in
     a field of the given minimum width.
  *)
 
END SWholeIO.
"SWholeIO" is the equivalent to "WholeIO" with predefined standard in- and outchannel.

1.3.20 TermFile

DEFINITION MODULE TermFile;
 
  (* Access to the terminal device *)
 
  (* Channels opened by this module are connected to a single terminal
     device; typed characters are distributed between channels according to
     the sequence of read requests.
  *)
 
IMPORT IOChan, ChanConsts;
 
TYPE
  ChanId = IOChan.ChanId;
  FlagSet = ChanConsts.FlagSet;
  OpenResults = ChanConsts.OpenResults;
 
  (* Accepted singleton values of FlagSet *)
 
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 *)
 
PROCEDURE Open (VAR cid: ChanId; flags: FlagSet; VAR res: OpenResults);
  (* Attempts to obtain and open a channel connected to the terminal.
     Without the raw flag, text is implied.
     Without the echo flag, line mode is requested, otherwise single
     character mode is requested.
     If successful, assigns to cid the identity of the opened channel, and
     assigns the value opened to res.
     If a channel cannot be opened as required, the value of res indicates
     the reason, and cid identifies the invalid channel.
  *)
 
PROCEDURE IsTermFile (cid: ChanId): BOOLEAN;
  (* Tests if the channel identified by cid is open to the terminal. *)
 
PROCEDURE Close (VAR cid: ChanId);
  (* If the channel identified by cid is not open to the terminal, the
     exception wrongDevice is raised; otherwise closes the channel and
     assigns the value identifying the invalid channel to cid.
  *)
 
END TermFile.
"TermFile" offers access to either the terminal window of the current shell (for command line tools) or the terminal window opened by module "TermBase" (for applications, cf. section 2.1.10 / 2.2.4) with control of echoing and buffering. If channels are opened in line mode as well as in character mode, read operations in line mode always lead to buffering of a whole line. Characters not processed by this operation may than be read in single character mode.

1.3.21 TextIO

DEFINITION MODULE TextIO;
 
  (* Input and output of character and string types over specified channels.
     The read result is of the type IOConsts.ReadResults.
  *)
 
IMPORT IOChan;
 
  (* The following procedures do not read past line marks *)
 
PROCEDURE ReadChar (cid: IOChan.ChanId; VAR ch: CHAR);
  (* If possible, removes a character from the input stream cid and assigns
     the corresponding value to ch.  The read result is set to the value
     allRight, endOfLine, or endOfInput.
  *)
 
PROCEDURE ReadRestLine (cid: IOChan.ChanId; VAR s: ARRAY OF CHAR);
  (* Removes any remaining characters from the input stream cid before the
     next line mark, copying to s as many as can be accommodated as a string
     value. The read result is set to the value allRight, outOfRange,
     endOfLine, or endOfInput.
  *)
 
PROCEDURE ReadString (cid: IOChan.ChanId; VAR s: ARRAY OF CHAR);
  (* Removes only those characters from the input stream cid before the next
     line mark that can be accommodated in s as a string value, and copies
     them to s.  The read result is set to the value allRight, endOfLine, or
     endOfInput.
  *)
 
PROCEDURE ReadToken (cid: IOChan.ChanId; VAR s: ARRAY OF CHAR);
  (* Skips leading spaces, and then removes characters from the input stream
     cid before the next space or line mark, copying to s as many as can be
     accommodated as a string value. The read result is set to the value
     allRight, outOfRange, endOfLine, or endOfInput.
  *)
 
  (* The following procedure reads past the next line mark *)
 
PROCEDURE SkipLine (cid: IOChan.ChanId);
  (* Removes successive items from the input stream cid up to and including
     the next line mark, or until the end of input is reached.  The read
     result is set to the value allRight, or endOfInput.
  *)
 
  (* Output procedures *)
 
PROCEDURE WriteChar (cid: IOChan.ChanId; ch: CHAR);
  (* Writes the value of ch to the output stream cid. *)
 
PROCEDURE WriteLn (cid: IOChan.ChanId);
  (* Writes a line mark to the output stream cid. *)
 
PROCEDURE WriteString (cid: IOChan.ChanId; s: ARRAY OF CHAR);
  (* Writes the string value in s to the output stream cid. *)
 
END TextIO.
"TextIO" is the high level module for input and output of text. Success of each read operation can be tested with "IOResults. ReadResult".

"ReadChar" reads one character if not at end of line or at end of file.

"ReadString" reads a string of characters until either the given array is filled or end of line / end of file is reached. "endOfLine" or "endOfFile" are returned, if no character could be read.

"ReadRestLine" works similar to "ReadString", but discards the rest of the line (if any). If not all characters could be stored in the given array, a read result of "outOfRange" is set.

"ReadToken" skips leading blanks and tries to store the entire text up to the next blank, end of line, or end of input in the given array. A read result of "allRight", "endOfLine (no character has been read because end of line), "endOfInput" (no character has been read because end of input), or "outOfRange" (array too small for whole string) is set accordingly.

"SkipLine" skips all characters up to and including the next line mark (if not reaching the end of file first).

"WriteChar" and "WriteString" write the given character or string to the specified channel.

"WriteLn" writes a device dependent line mark.

The following example program copies a file character by character observing end of file and end of line results of "IOResult. ReadResult". Other examples (copying by line, copying with the procedures of "IOChan") can be found in the folder "Examples" of the distribution kit.

MODULE CopyByChar;
(* Copies a text file character by character.*)

FROM STextIO IMPORT
  WriteString, WriteChar, WriteLn, ReadString, SkipLine;
FROM SeqFile IMPORT
  text, old, ChanId, OpenResults, OpenRead, OpenWrite, Close;
FROM IOResult IMPORT
  ReadResults, ReadResult;
IMPORT Text;

VAR
  inFile, outFile: ChanId;
  inFileName, outFileName: ARRAY [0 .. 79] OF CHAR;
  ch: CHAR;
  ores: OpenResults;

BEGIN
  WriteString ('Name of input file ?');
  WriteLn;
  WriteChar (">");
  ReadString (inFileName);
  SkipLine;
  WriteString ('Name of output file ?');
  WriteLn;
  WriteChar (">");
  ReadString (outFileName);
  SkipLine;
  OpenRead (inFile, inFileName, text, ores);
  (* open input file in text mode, only read operations are requested. *)
  IF ores <> opened
  THEN
    WriteString ('Could not open input file.');
    WriteLn;
    HALT;
  END(*IF*);
  OpenWrite (outFile, outFileName, text + old, ores);
  (* open output file in text mode, the file may exist. *)
  IF ores <> opened
  THEN
    WriteString ('Could not open output file.');
    WriteLn;
    HALT;
  END(*IF*);
  LOOP
    Text. ReadChar (inFile, ch);
    (* reads a character from the current line. *)
    CASE ReadResult (inFile) OF
      endOfInput:                   (* End of input stream encountered. *)
        EXIT;
    | endOfLine:                    (* End of current line encountered. *)
        Text. SkipLine (inFile);
        Text. WriteLn (outFile);
    ELSE                            (* Only "allRight" is possible here. *)
        Text. WriteChar (outFile, ch);
    END(*CASE*);
  END(*LOOP*);
  Close (inFile);
  Close (outFile);
END CopyByChar.

1.3.22 WholeIO

DEFINITION MODULE WholeIO;
 
  (* Input and output of whole numbers in decimal text form over specified
     channels.  The read result is of the type IOConsts.ReadResults.
  *)
 
IMPORT IOChan;
 
  (* 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}
  *)
 
PROCEDURE ReadInt (cid: IOChan.ChanId; VAR int: INTEGER);
  (* Skips leading spaces, and removes any remaining characters from cid that
     form part of a signed whole number.  The value of this number is
     assigned to int.  The read result is set to the value allRight,
     outOfRange, wrongFormat, endOfLine, or endOfInput.
  *)
 
PROCEDURE WriteInt (cid: IOChan.ChanId; int: INTEGER; width: CARDINAL);
  (* Writes the value of int to cid in text form, in a field of the given
     minimum width.
  *)
 
PROCEDURE ReadCard (cid: IOChan.ChanId; VAR card: CARDINAL);
  (* Skips leading spaces, and removes any remaining characters from cid that
     form part of an unsigned whole number.  The value of this number is
     assigned to card.  The read result is set to the value allRight,
     outOfRange, wrongFormat, endOfLine, or endOfInput.
  *)
 
PROCEDURE WriteCard (cid: IOChan.ChanId; card: CARDINAL; width: CARDINAL);
  (* Writes the value of card to cid in text form, in a field of the given
     minimum width.
  *)
 
END WholeIO.
"WholeIO" handles the input and output of whole numbers in textual form.

"ReadInt" and "ReadCard" read a number from the specified channel and set the according read result. "outOfRange" indicates, that the number has been too large (absolute value).

"WriteInt" and "WriteCard" write a number with at least "width" places. If "width" equals 0, exactly one leading blank is written.

1.4 Other Modules

Procedures for examination and manipulation of string are collected in module "Strings".

The conversion modules "xxxConv" and "xxxStr", together with module "ConvTypes", provide the procedures for conversion of numerical data to strings and vice versa. The modules "xxxStr" are the high level modules with simple conversion procedures. The modules "xxxConv" provide the basic procedures for the conversion of string to numbers.

The modules "Processes" and "Semaphores" provide mechanisms for the management of (virtually) parallel processes.

"SysClock" date and time procedures.

1.4.1 Strings

DEFINITION MODULE Strings;

(* Facilities for manipulating strings *)

TYPE
  String1 = ARRAY [0..0] OF CHAR;
    (* String1 is provided for constructing a value of a single-character
       string type from a single character value in order to pass CHAR values
       to ARRAY OF CHAR parameters.
    *)

PROCEDURE Length (stringVal: ARRAY OF CHAR): CARDINAL;
  (* Returns the length of stringVal (the same value as would be returned by
     the predefined function LENGTH).
  *)


(* The following seven procedures construct a string value, and attempt to
   assign it to a variable parameter.  They all have the property that if the
   length of the constructed string value exceeds the capacity of the
   variable parameter, a truncated value is assigned, while if the length of
   the constructed string value is less than the capacity of the variable
   parameter, a string terminator is appended before assignment is performed.
*)

PROCEDURE Assign (source: ARRAY OF CHAR; VAR destination: ARRAY OF CHAR);
  (* Copies source to destination *)

PROCEDURE Extract (source: ARRAY OF CHAR; startIndex, numberToExtract:
                   CARDINAL; VAR destination: ARRAY OF CHAR);
  (* Copies at most numberToExtract characters from source to destination,
     starting at position startIndex in source.
  *)

PROCEDURE Delete (VAR stringVar: ARRAY OF CHAR;
                  startIndex, numberToDelete: CARDINAL);
  (* Deletes at most numberToDelete characters from stringVar, starting at
     position startIndex.
  *)

PROCEDURE Insert (source: ARRAY OF CHAR; startIndex: CARDINAL;
                  VAR destination: ARRAY OF CHAR);
  (* Inserts source into destination at position startIndex *)

PROCEDURE Replace (source: ARRAY OF CHAR; startIndex: CARDINAL;
                   VAR destination: ARRAY OF CHAR);
  (* Copies source into destination, starting at position startIndex. Copying
     stops when all of source has been copied, or when the last character of
     the string value in destination has been replaced.
  *)

PROCEDURE Append (source: ARRAY OF CHAR; VAR destination: ARRAY OF CHAR);
  (* Appends source to destination. *)

PROCEDURE Concat (source1, source2: ARRAY OF CHAR;
                  VAR destination: ARRAY OF CHAR);
  (* Concatenates source2 onto source1 and copy the result into destination.
  *)

(* The following predicates provide for pre-testing of the operation-
   completion conditions for the procedures above.
*)

PROCEDURE CanAssignAll (sourceLength: CARDINAL;
                        VAR destination: ARRAY OF CHAR): BOOLEAN;
  (* Returns TRUE if a number of characters, indicated by sourceLength, will
     fit into destination, and FALSE otherwise.
  *)

PROCEDURE CanExtractAll (sourceLength, startIndex, numberToExtract: CARDINAL;
                         VAR destination: ARRAY OF CHAR): BOOLEAN;
  (* Given the length of a string, sourceLength, the startIndex for
     extraction, and the number of characters to extract, numberToExtract,
     returns TRUE if, there are numberToExtract characters starting at
     startIndex and within the sourceLength, and if the capacity of
     destination is sufficient to hold numberToExtract characters.
     Otherwise it returns FALSE
  *)

PROCEDURE CanDeleteAll (stringLength, startIndex, numberToDelete: CARDINAL)
                       : BOOLEAN;
  (* Given the length of a string, stringLength, the startIndex for deletion,
     and the number of characters to delete, numberToDelete, returns TRUE if,
     there are numberToDelete characters starting at startIndex and within
     the stringLength. Otherwise it returns FALSE
  *)

PROCEDURE CanInsertAll (sourceLength, startIndex: CARDINAL;
                        VAR destination: ARRAY OF CHAR): BOOLEAN;
  (* Given the length of a string to insert, sourceLength, and the startIndex
     for insertion in the destination, returns TRUE if, there is room in the
     destination for the insertion. Otherwise it returns FALSE
  *)

PROCEDURE CanReplaceAll (sourceLength, startIndex: CARDINAL;
                         VAR destination: ARRAY OF CHAR): BOOLEAN;
  (* Given the length of a replacement string, sourceLength, and the
     startIndex for the replacement in the destination, returns TRUE if,
     there is room in the string value in. the destination. Otherwise it
     returns FALSE
  *)

PROCEDURE CanAppendAll (sourceLength: CARDINAL;
                        VAR destination: ARRAY OF CHAR): BOOLEAN;
  (* Returns TRUE if there is sufficient room in destination to append a
     string of length sourceLength to the string in destination and FALSE
     otherwise.
  *)

PROCEDURE CanConcatAll (source1Length, source2Length: CARDINAL;
                        VAR destination: ARRAY OF CHAR): BOOLEAN;
  (* Returns TRUE if there is sufficient room in destination for a two
     strings of lengths source1Length and source2Length and FALSE otherwise.
  *)

(* The following type and procedures provide for the comparison of string
   values, and for the location of substrings within strings.
*)

TYPE
  CompareResults = (less, equal, greater);

PROCEDURE Compare (stringVal1, stringVal2: ARRAY OF CHAR): CompareResults;
  (* Returns less, equal or greater according as stringVal1 is lexically less
     than, equal to, or greater than stringVal2.
  *)

PROCEDURE Equal (stringVal1, stringVal2: ARRAY OF CHAR): BOOLEAN;
  (* Returns Strings.Compare(stringVal1, stringVal2) = Strings.equal *)

PROCEDURE FindNext (pattern, stringToSearch: ARRAY OF CHAR;
                    startIndex: CARDINAL;
                    VAR patternFound: BOOLEAN; VAR posOfPattern: CARDINAL);
  (* Looks forward for next occurrence of pattern in stringToSearch, starting
     the search at position startIndex. If startIndex < LENGTH
     (stringToSearch) and pattern is found, patternFound is returned as TRUE,
     and posOfPattern contains the start position in stringToSearch of
     pattern. Otherwise patternFound is returned as FALSE, and posOfPattern
     is unchanged.
  *)

PROCEDURE FindPrev (pattern, stringToSearch: ARRAY OF CHAR;
                    startIndex: CARDINAL;
                    VAR patternFound: BOOLEAN; VAR posOfPattern: CARDINAL);
  (* Looks backward for the previous occurrence of pattern in stringToSearch
     and returns the position of the first character of the pattern if found.
     The search for the pattern begins at startIndex.If pattern is found,
     patternFound is returned as TRUE, and posOfPattern contains the start
     position in stringToSearch of pattern in the range [0..startIndex].
     Otherwise patternFound is returned as FALSE, and posOfPattern is
     unchanged.
  *)

PROCEDURE FindDiff (stringVal1, stringVal2: ARRAY OF CHAR;
                    VAR differenceFound: BOOLEAN;
                    VAR posOfDifference: CARDINAL);
  (* Compares the string values in stringVal1 and stringVal2 for differences.
     If the are equal differenceFound is returned as FALSE and TRUE
     otherwise. If differenceFound is TRUE, posOfDifference is set to the
     position of the first difference; otherwise posOfDifference is
     unchanged.
  *)

PROCEDURE Capitalize (VAR stringVar: ARRAY OF CHAR);
  (* Applies the function CAP to each character of the string value in
     stringVar.
  *)

END Strings.
"Strings" provides procedures for the handling of strings, like comparison, search, concatenation etc. Procedures which have result strings use as many space as available in the result parameter, too long result strings are truncated. The user may—if necessary—use test functions to ask whether the result parameter is large enough to keep the whole result.

"Length" calculates the length of a string and is identical to the pervasive function "LENGTH".

"Assign" assigns the first string to the second one.

"Extract" copies a substring starting from position "startIndex" and of length "numberToExtract" from "source" to "destination."

"Delete" deletes a substring starting from position "startIndex" and of length "numberToExtract" from "source"

"Insert" inserts "source" into "destination" starting from position "startIndex".

"Append" appends "source" to "destination".

"Concat" concatenates "source1" and "source2" and assigns the result to "destination".

"Capitalize" changes all lowercase letters to capitals.

"Compare" compares "stringVal1" and "stringVal2" and returns the according result.

"Equal" compares "stringVal1" and "stringVal2" and returns "TRUE" if the strings are equal ("FALSE" otherwise).

"FindNext" searches the next occurrence of "pattern" in "stringVal", starting at position "startIndex". If the pattern is found ("patternFound = TRUE"), the starting position of the pattern is returned in "posOfPattern".

"FindPrev" is like "FindNext", but searches backwards.

"FindDiff" looks for the first difference between "stringVal1" and "stringVal2" ("differenceFound = TRUE") and returns this position in "posOfDifference". If the strings are equal, "differenceFound" returns "FALSE".

The "Can..." procedures test, whether a desired operation can be performed with the given parameters. A result of "TRUE" indicates, that the result string is large enough to keep the entire result.

The following examples are a short overview over usage and functionality of the procedures of this module. All examples use the following declarations:

  VAR
    small: ARRAY [0 .. 4] OF CHAR;
    large: ARRAY [0 .. 255] OF CHAR;
    alpha: ARRAY ['A' .. 'E'] OF CHAR;
    ch: CHAR;
    found, arediff: BOOLEAN;
    pos: CARDINAL;
Examples for "Assign":
callresult
ch := "X";
Assign (String1{ch}, small)

small[0] = "X"

small[1] = ""
Assign ("pq", small) small[0] = "p"
small[2] = ""
small[1] = "q"
Assign ("", small) small[0] = ""
Assign ("Hello!", small) small[0] = "H"
small[2] = "l"
small[4] = "o"
small[1] = "e"
small[3] = "l"
CanAssignAll (6, small) FALSE
Assign ("Go", alpha) alpha['A'] = "G"
alpha['C'] = ""
alpha['C'] = "o"
small := "Hello";
large:="";
IF CanAssignAll (LENGTH (small), large)
THEN
    Assign (small, large)
END;
large[0] = "H"
large[2] = "l"
large[4] = "o"
large[1] = "e"
large[3] = "l"
Examples for "Extract":
callresult
large := "ABCDE";
small := "";
IF CanExtractAll (LENGTH (large), 2, 3, small)
THEN
    Extract (large, 2, 3, small)
END;
small[0] = "C"
small[2] = "E"
small[1] = "D"
small[3] = ""
large := "ABCDE";
small := "";
Extract (large, 2, 3, small)
small[0] = "C"
small[2] = "E"
small[1] = "D"
small[3] = ""
Examples for "Delete":
callresult
small := "ABCDE";
IF CanDeleteAll (LENGTH (small), 2, 2)
THEN
    Delete (small, 2, 2)
END;
small[0] = "A"
small[2] = "E"
small[1] = "B"
small[3] = ""
small := "ABC";
CanDeleteAll (3, 2, 2)
FALSE
small := "ABC";
Delete (small, 2, 2)
small[0] = "A"
small[2] = ""
small[1] = "B"
Examples for "Insert":
callresult
small := "ABCD";
CanInsertAll (LENGTH ("XYZ"), 2, small)
FALSE
small := "ABCD";
Insert ("XYZ", 2, small)
small[0] = "A"
small[2] = "X"
small[4] = "Z"
small[1] = "B"
small[3] = "Y"
large := "ABC";
IF CanInsertAll (3, 2, large)
THEN
    Insert ("XYZ", 2, large)
END;
large[0] = "A"
large[2] = "X"
large[4] = "Z"
large[6] = ""
large[1] = "B"
large[3] = "Y"
large[5] = "C"
large := "ABCD";
ch := "X";
Insert (String1 {ch}, 2, large)
large[0] = "A"
large[2] = "X"
large[4] = "D"
large[1] = "B"
large[3] = "C";
large[5] = ""
Examples for "Replace":
callresult
small := "ABC";
CanReplaceAll (LENGTH ("XY"), 2, small)
FALSE
small := "ABC";
Replace ("XY", 2, small)
small[0] = "A"
small[2] = "X"
small[1] = "B"
small[3] = ""
large := "ABCDEF";
IF CanReplaceAll (3, 2, large)
THEN
    Replace ("XYZ", 2, large)
END;
large[0] = "A"
large[2] = "X"
large[4] = "Z"
large[6] = ""
large[1] = "B"
large[3] = "Y"
large[5] = "F"
Examples for "Append":
callresult
small := "pqr";
CanAppendAll (LENGTH ("XYZ"), small)

FALSE
small := "pqr";
Append ("XYZ", small)
small[0] = "p"
small[2] = "r"
small[4] = "Y"
small[1] = "q"
small[3] = "X"
small := "pqr";
ch := "s";
Append (String1 {ch}, small)
small[0] = "p"
small[2] = "r"
small[4] = ""
small[1] = "q"
small[3] = "s"
Examples for "Concat":
callresult
small := "pqr";
CanConcatAll (4, LENGTH (small), small)
FALSE
small := "pqr";
Concat ("WXYZ", small, small)
small[0] = "W"
small[2] = "Y"
small[4] = "p"
small[1] = "X"
small[3] = "Z"
small := "jk"; large := "";
ch := "s";
Concat (String1 {ch}, small, large)
large[0] = "s"
large[2] = "k"
large[1] = "j"
large[3] = ""
Examples for "Capitalize":
callresult
small := "pqr";
Capitalize (small)
small[0] = "P"
small[2] = "R"
small[1] = "Q"
small[3] = ""
Examples for "Compare":
callresult
Compare ("", "") equal
Compare ("", "abc") less
Compare ("abc", "") greater
Compare ("pqr", "pqr") equal
Compare ("pqr", "pqrstuv") less
Compare ("pqrstuv", "pqr") greater
Compare ("abc", "pqr") less
Compare ("pqr", "abc") greater
Compare ("abcdef", "p") less
Compare ("p", "abcdef") greater
Examples for "FindNext":
callresult
large := "Hello hello hello";
FindNext ("ll", large, 0, found, pos)

found = TRUE

pos = 2
large := "Hello hello hello";
FindNext ("ll", large, 0, found, pos)
FindNext ("ll", large, pos + 1, found, pos)


found = TRUE


pos = 8
large := "abcdefghijklmnopqrstuvwxyz";
ch := "x";
FindNext (String1 {ch}, large, 0, found, pos)


found = TRUE


pos = 23
large := "abcdefghijklmnopqrstuvwxyz";
ch := "x";
FindNext (String1 {ch}, large, 26, found, pos)


found = FALSE


pos = not changed
Examples for "FindPrev":
callresult
large := "aabbbcccc";
FindPrev ("cc", large, 200, found, pos)

found = TRUE

pos = 7
large := "aabbbcccc";
FindPrev ("cc", large, 200, found, pos)
FindPrev ("cc", large, pos - 1, found, pos)


found = TRUE


pos = 6
large := "Maybe this makes sense";
FindPrev ("se", large, 200, found, pos)

found = TRUE

pos = 20
large := "Maybe this makes sense";
FindPrev ("se", large, 200, found, pos)
FindPrev ("se", large, pos - 1, found, pos)


found = TRUE


pos = 17
Examples for "FindDiff":
callresult
FindDiff ("", "", arediff, pos) arediff = FALSE pos = not changed
FindDiff ("abc", "", arediff, pos) arediff = TRUE pos = 0
FindDiff ("", "abcd", arediff, pos) arediff = TRUE pos = 0
FindDiff ("pqr", "pqt", arediff, pos) arediff = TRUE pos = 2
FindDiff ("pqr", "pqrstu", arediff, pos) arediff = TRUE pos = 3
FindDiff ("pqrstu", "pqr", arediff, pos) arediff = TRUE pos = 3

1.4.2 ConvTypes

DEFINITION MODULE ConvTypes;

(* Common types used in the string conversion modules *)

TYPE
  ConvResults =     (* Values of this type are used to express the format of
                       a string *)
  (
    strAllRight,    (* the string format is correct for the corresponding
                       conversion *)
    strOutOfRange,  (* the string is well-formed but the value cannot be
                       represented *)
    strWrongFormat, (* the string is in the wrong format for the conversion 
                       *)
    strEmpty        (* the given string is empty *)
  );

  ScanClass =  (* Values of this type are used to classify characters input
                  to finite state scanners *)
  ( 
    padding,   (* a leading or padding character at this point in the scan -
                  ignore it *)
    valid,     (* a valid character at this point in the scan - accept it *)
    invalid,   (* an invalid character at this point in the scan - reject it
                  *)
    terminator (* a terminating character at this point in the scan (not part
                  of token) *)
  );

  ScanState =  (* The type of lexical scanning control procedures *)
    PROCEDURE(CHAR, VAR ScanClass, VAR ScanState);

END ConvTypes.
"ConvTypes" contains all data types used in the conversion modules.

"ConvResults" identities all errors possible during conversion ("all right", "out of range", "wrong format", "empty string").

"ScanClass" and "ScanResult" are used to implement a finite state machine to read a string with a given format character by character. "ScanClass" identifies the class of a character. "ScanState" is the procedure type for the action procedure representing the state of the machine.

1.4.3 WholeConv

DEFINITION MODULE WholeConv;

IMPORT
  ConvTypes;

TYPE
  ConvResults = ConvTypes.ConvResults; (* strAllRight, strOutOfRange,
                                          strWrongFormat, strEmpty *)

PROCEDURE IsWholeConvException (): BOOLEAN;
  (* Returns TRUE iff an exception has been raised by the module WholeConv *)

PROCEDURE ScanInt (inputCh: CHAR; VAR chClass: ConvTypes.ScanClass;
                   VAR nextState: ConvTypes.ScanState);
  (* Represents the start state of a finite state scanner for signed whole
     numbers - assigns class of inputCh to chClass and a procedure
     representing the next state to nextState.
  *)

PROCEDURE FormatInt (str: ARRAY OF CHAR): ConvResults;
  (* Returns the format of the string value for conversion to INTEGER *)

PROCEDURE ValueInt (str: ARRAY OF CHAR): INTEGER;
  (* If str is well-formed, returns the value corresponding to the signed
     whole number string value str; otherwise raises an exception.
  *)

PROCEDURE LengthInt (int: INTEGER): CARDINAL;
  (* Returns the number of characters in the string representation of int *)


PROCEDURE ScanCard (inputCh: CHAR; VAR chClass: ConvTypes.ScanClass;
                    VAR nextState: ConvTypes.ScanState);
  (* Represents the start state of a finite state scanner for unsigned whole
     numbers - assigns class of inputCh to chClass and a procedure
     representing the next state to nextState.
  *)

PROCEDURE FormatCard (str: ARRAY OF CHAR): ConvResults;
  (* Returns the format of the string value for conversion to CARDINAL. *)

PROCEDURE ValueCard (str: ARRAY OF CHAR): CARDINAL;
  (* If str is well-formed, returns the value corresponding to the unsigned
     whole number string value str; otherwise raises an exception.
  *)

PROCEDURE LengthCard (card: CARDINAL): CARDINAL;
  (* Returns the number of characters in the string representation of card.
  *)

END WholeConv.
"WholeConv" is the low level module for conversion between strings and whole numbers.

"ScanInt is the start procedure of a finite state machine to scan values of type "INTEGER" given as string. "inputCh" is the next character to be processed. The type of this character is returned in "chClass". The procedure that corresponds to the state of the scanner is stored in "nextState".

The following example demonstrates the use of the scanner. "GetCh" and "StoreCh" identify two procedures to read characters from the input stream and to store characters for further processing.

VAR
    scan: ConvTypes. ScanState;
    class: ConvTypes. ScanClass;
    ch: CHAR;

    scan := WholeConv. ScanInt;
    REPEAT
      GetCh (ch);
      scan (ch, class, scan);
      IF class = valid THEN
        StoreCh (ch);
      END(*IF*);
    UNTIL (class = invalid) OR (class = terminator );
    IF class = invalid THEN
      (* report error *)
    ELSE
      (* process input *)
    END(*IF*);
"FormatInt" tests, whether a string is a correct representation of a whole number.

"ValueInt" returns the "INTEGER" value of a input string or raises an exception.

"LengthInt" returns the number of places needed to represent "int" as a string.

The procedures "ScanCard", "FormatCard", "ValueCard", and "LengthCard" are similar to the procedures describes above, but take values of type "CARDINAL" as parameters.

1.4.4 RealConv

DEFINITION MODULE RealConv;

IMPORT
  ConvTypes;

TYPE
  ConvResults = ConvTypes.ConvResults; (* strAllRight, strOutOfRange,
                                          strWrongFormat, strEmpty *)

PROCEDURE IsRConvException (): BOOLEAN;
  (* Returns TRUE iff an exception has been raised by the module RealConv *)

PROCEDURE ScanReal (inputCh: CHAR; VAR chClass: ConvTypes.ScanClass;
                    VAR nextState: ConvTypes.ScanState);
  (* Represents the start state of a finite state scanner for real numbers -
     assigns class of inputCh to chClass and a procedure representing the
     next state to nextState.
  *)

PROCEDURE FormatReal (str: ARRAY OF CHAR): ConvResults;
  (* Returns the format of the string value for conversion to REAL *)

PROCEDURE ValueReal (str: ARRAY OF CHAR): REAL;
  (* If str is well-formed, returns the value corresponding to the real
     number string value str; otherwise raises an exception.
  *)

PROCEDURE LengthFloatReal (real: REAL; sigFigs: CARDINAL): CARDINAL;
  (* Returns the number of characters in the floating-point string
     representation of real with sigFigs significant figures.
  *)

PROCEDURE LengthEngReal (real: REAL; sigFigs: CARDINAL): CARDINAL;
  (* Returns the number of characters in the floating-point engineering
     string representation of real with sigFigs significant figures.
  *)

PROCEDURE LengthFixedReal (real: REAL; place: INTEGER): CARDINAL;
  (* Returns the number of characters in the fixed-point string
     representation of real rounded to the given place relative to the
     decimal point.
  *)

END RealConv.
"RealConv " is the low level module for conversion between strings and real numbers.

The procedures "ScanReal", "FormatReal", and "ValueReal" correspond in functionality and usage with the procedures "ScanInt", "FormatInt", and "ValueInt" of module "WholeConv" (cf. chapter 1.4.3).

"LengthFloat" calculates the number of characters necessary for the representation of "real" in scientific notation with "sigFigs" significant figures.

"LengthEng" is analogous to "LengthFloat", but with an exponent set to a multiple of three.

"LengthFixedReal" calculates the number of characters necessary for the representation of "real" in fixed point notation, if the number is rounded to "place" digits. "place > 0" indicates places to the right of the decimal point, "place < 0" means rounding to "ABS (place)" places left to the decimal point. Examples of this format are part of chapter 1.3.9 (module "RealIO").

1.4.5 LongConv

DEFINITION MODULE LongConv;

IMPORT
  ConvTypes;

TYPE
  ConvResults = ConvTypes.ConvResults; (* strAllRight, strOutOfRange,
                                          strWrongFormat, strEmpty *)

PROCEDURE IsRConvException (): BOOLEAN;
  (* Returns TRUE iff an exception has been raised by the module LongConv *)

PROCEDURE ScanReal (inputCh: CHAR; VAR chClass: ConvTypes.ScanClass;
                    VAR nextState: ConvTypes.ScanState);
  (* Represents the start state of a finite state scanner for real numbers -
     assigns class of inputCh to chClass and a procedure representing the 
     next state to nextState.
  *)

PROCEDURE FormatReal (str: ARRAY OF CHAR): ConvResults;
  (* Returns the format of the string value for conversion to LONGREAL *)

PROCEDURE ValueReal (str: ARRAY OF CHAR): LONGREAL;
  (* If str is well-formed, returns the value corresponding to the real
     number string value str; otherwise raises an exception.
  *)

PROCEDURE LengthFloatReal (real: LONGREAL; sigFigs: CARDINAL): CARDINAL;
  (* Returns the number of characters in the floating-point string
     representation of real with sigFigs significant figures.
  *)

PROCEDURE LengthEngReal (real: LONGREAL; sigFigs: CARDINAL): CARDINAL;
  (* Returns the number of characters in the floating-point engineering
     string representation of real with sigFigs significant figures.
  *)

PROCEDURE LengthFixedReal (real: LONGREAL; place: INTEGER): CARDINAL;
  (* Returns the number of characters in the fixed-point string
     representation of real rounded to the given place relative to the
     decimal point.
  *)

END LongConv.
"LongConv" corresponds to "RealConv" for real numbers of type "LONGREAL".

1.4.6 WholeStr

DEFINITION MODULE WholeStr;

(* Whole-number/string conversions *)

IMPORT
  ConvTypes;

TYPE
  ConvResults = ConvTypes.ConvResults; (* strAllRight, strOutOfRange,
                                          strWrongFormat, strEmpty *)

(* the string form of a signed whole number is
     ["+" | "-"], decimal digit, {decimal digit}
*)

PROCEDURE StrToInt (str: ARRAY OF CHAR; VAR int: INTEGER; VAR res: ConvResults);
  (* Ignores any leading spaces in str. If the subsequent characters in str
     are in the format of a signed whole number, assigns a corresponding
     value to int.  Assigns a value indicating the format of str to res.
  *)

PROCEDURE IntToStr (int: INTEGER; VAR str: ARRAY OF CHAR);
  (* Converts the value of int to string form and copies the possibly
     truncated result to str.
  *)

(* the string form of an unsigned whole number is
     decimal digit, {decimal digit}
*)

PROCEDURE StrToCard (str: ARRAY OF CHAR;
                     VAR card: CARDINAL; VAR res: ConvResults);
  (* Ignores any leading spaces in str. If the subsequent characters in str
     are in the format of an unsigned whole number, assigns a corresponding
     value to card.  Assigns a value indicating the format of str to res.
  *)

PROCEDURE CardToStr (card: CARDINAL; VAR str: ARRAY OF CHAR);
  (* Converts the value of card to string form and copies the possibly
     truncated result to str.
  *)

END WholeStr.
"WholeStr" provides simple procedures for conversions between strings and whole numbers.

"StrToInt" converts a string into a value of type "INTEGER". "res" indicates, whether the format of the string is correct.

"IntToStr" converts the value "int" into a string. If the variable "str" is too small to store the result, the string is truncated at the right.

"StrToCard" converts a string into a value of type "CARDINAL". "res" indicates, whether the format of the string is correct.

"CardToStr" converts the value "card" into a string. If the variable "str" is too small to store the result, the string is truncated at the right.

1.4.7 RealStr

DEFINITION MODULE RealStr;

(* REAL/string conversions *)

IMPORT
  ConvTypes;

TYPE
  ConvResults = ConvTypes.ConvResults; (* strAllRight, strOutOfRange,
                                          strWrongFormat, strEmpty *)

(* the string form of a signed fixed-point real number is
     ["+" | "-"], decimal digit, {decimal digit},
     [".", {decimal digit}]
*)

(* the string form of a signed floating-point real number is
     signed fixed-point real number,
     "E", ["+" | "-"], decimal digit, {decimal digit} 
*)

PROCEDURE StrToReal (str: ARRAY OF CHAR;
                     VAR real: REAL; VAR res: ConvResults);
  (* Ignores any leading spaces in str. If the subsequent characters in str
     are in the format of a signed real number, assigns a corresponding value
     to real.  Assigns a value indicating the format of str to res.
  *)

PROCEDURE RealToFloat (real: REAL; sigFigs: CARDINAL;
                       VAR str: ARRAY OF CHAR);
  (* Converts the value of real to floating-point string form, with sigFigs
     significant figures, and copies the possibly truncated result to str.
  *)

PROCEDURE RealToEng (real: REAL; sigFigs: CARDINAL; VAR str: ARRAY OF CHAR);
  (* Converts the value of real to floating-point string form, with sigFigs
     significant figures, and copies the possibly truncated result to str.
     The number is scaled with one to three digits in the whole number part
     and with an exponent that is a multiple of three.
  *)

PROCEDURE RealToFixed (real: REAL; place: INTEGER; VAR str: ARRAY OF CHAR);
  (* Converts the value of real to fixed-point string form, rounded to the
     given place relative to the decimal point, and copies the possibly
     truncated result to str.
  *)

PROCEDURE RealToStr (real: REAL; VAR str: ARRAY OF CHAR);
  (* Converts the value of real as RealToFixed if the sign and magnitude can 
     be shown within the capacity of str, or otherwise as RealToFloat, and
     copies the possibly truncated result to str.  The number of places or
     significant digits are implementation-defined.
  *)

END RealStr.
"RealStr" provides simple procedures for conversion between strings and real numbers.

"StrToReal" converts a string into a value of type "REAL". "res" indicates, whether the format of the string is correct.

"RealToFloat" converts the value "real" into a string in scientific notation with "sigFigs" significant numbers. If the variable "str" is too small to store the result, the string is truncated at the right.

"RealToEng" converts the value "real" into a string in scientific notation with "sigFigs" significant numbers. The exponent is adjusted to a multiple of three. If the variable "str" is too small to store the result, the string is truncated at the right.

"RealToFixed" converts the value "real" into a string in fixed point notation rounded to "places" digits. "place > 0" indicates places to the right of the decimal point, "place < 0" means rounding to "ABS (place)" places left to the decimal point. If the variable "str" is too small to store the result, the string is truncated at the right.

1.4.8 LongStr

DEFINITION MODULE LongStr;

(* LONGREAL/string conversions *)

IMPORT
  ConvTypes;

TYPE
  ConvResults = ConvTypes.ConvResults; (* strAllRight, strOutOfRange,
                                          strWrongFormat, strEmpty *)

(* the string form of a signed fixed-point real number is
     ["+" | "-"], decimal digit, {decimal digit},
     [".", {decimal digit}]
*)

(* the string form of a signed floating-point real number is
     signed fixed-point real number,
     "E", ["+" | "-"], decimal digit, {decimal digit} 
*)

PROCEDURE StrToReal (str: ARRAY OF CHAR;
                     VAR real: LONGREAL; VAR res: ConvResults);
  (* Ignores any leading spaces in str. If the subsequent characters in str
     are in the format of a signed real number, assigns a corresponding value
     to real.  Assigns a value indicating the format of str to res.
  *)

PROCEDURE RealToFloat (real: LONGREAL; sigFigs: CARDINAL;
                       VAR str: ARRAY OF CHAR);
  (* Converts the value of real to floating-point string form, with sigFigs
     significant figures, and copies the possibly truncated result to str.
  *)

PROCEDURE RealToEng (real: LONGREAL; sigFigs: CARDINAL;
                     VAR str: ARRAY OF CHAR);
  (* Converts the value of real to floating-point string form, with sigFigs
     significant figures, and copies the possibly truncated result to str.
     The number is scaled with one to three digits in the whole number part
     and with an exponent that is a multiple of three.
  *)

PROCEDURE RealToFixed (real: LONGREAL; place: INTEGER;
                       VAR str: ARRAY OF CHAR);
  (* Converts the value of real to fixed-point string form, rounded to the
     given place relative to the decimal point, and copies the possibly
     truncated result to str.
  *)

PROCEDURE RealToStr (real: LONGREAL; VAR str: ARRAY OF CHAR);
  (* Converts the value of real as RealToFixed if the sign and magnitude can
     be shown within the capacity of str, or otherwise as RealToFloat, and
     copies the possibly truncated result to str.  The number of places or
     significant digits depend on the capacity of str.
  *)

END LongStr.
"LongStr" corresponds to "RealStr" for real numbers of type "LONGREAL".

1.4.9 Processes

DEFINITION MODULE Processes;

  (* This module allows concurrent algorithms to be expressed using
     processes.  A process is a unit of a program that has the potential to
     run in parallel with other processes.
  *)

IMPORT SYSTEM;

TYPE    
  ProcessId;                      (* Used to identify processes *)
  Parameter     = SYSTEM.ADDRESS; (* Used to pass data between processes *)
  Body          = PROC;           (* Used as the type of a process body *)
  Urgency       = INTEGER;        (* Used by the internal scheduler *)
  Sources       = CARDINAL;       (* Used to identify event sources *)
  ProcExceptions =                (* Exceptions raised by this module *)
    (procsNoException, notProcsException, passiveProgram, processError);

(* The following procedures create processes and switch control between them.
*)

PROCEDURE Create (procBody: Body; extraSpace: CARDINAL; procUrg: Urgency;
                  procParams: Parameter; VAR procId: ProcessId);
  (* Creates a new process with procBody as its body, and with urgency and
     parameters given by procUrg and procParams.  At least as much workspace
     (in units of SYSTEM.LOC) as is specified by extraSpace is allocated to
     the process.  An identity for the new process is returned in procId.
     The process is created in the passive state; it will not run until
     activated.
  *)

PROCEDURE Start (procBody: Body; extraSpace: CARDINAL; procUrg: Urgency;
                 procParams: Parameter; VAR procId: ProcessId);
  (* Creates a new process, with parameters as for Create.
     The process is created in the ready state; it is eligible to run
     immediately.
  *)

PROCEDURE StopMe ();
  (* Terminates the calling process, and reclaims the workspace allocated
     when it was first created.  The process must not be associated with a
     source of events.
  *)

PROCEDURE SuspendMe ();
  (* Causes the calling process to enter the passive state.  The procedure
     only returns when the calling process is again activated by another
     process.
  *)

PROCEDURE Activate (procId: ProcessId);
  (* Causes the process identified by procId to enter the ready state, and
     thus to become eligible to run again.  This process must not be
     currently be eligible to run.
  *)

PROCEDURE SuspendMeAndActivate (procId: ProcessId);
  (* Executes an atomic sequence of SuspendMe() and Activate(procId). *)

PROCEDURE Switch (procId: ProcessId; VAR info: Parameter );
  (* Causes the calling process to enter the passive state; the process
     identified by procId becomes the currently executing process.
     info is used to pass parameter information from the calling to the
     activated process. On return, info will contain information from the
     process that chooses to switch back to this one (or will be NIL if
     Activate or SuspendMeAndActivate are used instead of Switch).
  *)

PROCEDURE Wait ();
  (* Causes the calling process to enter the waiting state.  The procedure
     will return when the calling process is activated by another process, or
     when one of its associated eventSources has generated an event.
  *)

(* The following procedures allow the association of processes with sources
   of external events.
*)

PROCEDURE Attach (eventSource: Sources);
  (* Associates the specified eventSource with the calling process. *)

PROCEDURE Detach (eventSource: Sources);
  (* Dissociates the specified eventSource from the program. *)

PROCEDURE IsAttached (eventSource: Sources): BOOLEAN;
  (* Returns TRUE if and only if the specified eventSource is currently
     associated with one of the processes of the program.
  *)

PROCEDURE Handler (eventSource: Sources): ProcessId;
  (* Returns the identity of the process, if any, that is associated with the
     specified eventSource.
  *)

(* The following procedures allow processes to obtain their identity,
   parameters, and urgency.
*)

PROCEDURE Me (): ProcessId;
  (* Returns the identity of the calling process (as assigned when the
     process was first created).
  *)

PROCEDURE MyParam (): Parameter;
  (* Returns the value specified as procParams when the calling process was
     created.
  *)

PROCEDURE UrgencyOf (procId: ProcessId): Urgency;
  (* Returns the urgency established when the process identified by procId
     was first created.
  *)

(* The following procedure provides facilities for exception handlers. *)
    
PROCEDURE ProcessesException (): ProcessesExceptions;
  (* If the current coroutine is in the exceptional execution state because of the raising
     of a language exception, returns the corresponding enumeration value, and
     otherwise raises an exception.
  *)
    
PROCEDURE IsProcessesException (): BOOLEAN;
  (* Returns TRUE if the current coroutine is in the exceptional execution state
     because of the raising of an exception in a routine from this module; otherwise
     returns FALSE.
  *)
END Processes.
This module is based on the Posix threads implemented in the Darwin kernel of MacOS X and reflects the features provided for by these threads.
No sources for asynchronous events are defined.

"Create" creates a new suspended thread with the given procedure body as start routine. The stack space given in "extraSpace" is added to the minimum size a thread needs to execute.

"Start" same as Create but the thread is immediately activated.

"StopMe" terminates the actual thread; if this is the last remaining thread, program termination is invoked.

"SuspendMe" suspends the actual thread.

"Activate" activates the given thread.

"SuspendMeAndActivate" suspends the actual thread and activates the given thread.

"Switch" same as SuspendMeAndActivate but allows to pass a paramter address between the threads.

"Wait" same as SuspendMe, as no event sources are defined.

"Attach" always raises an exception, as no event sources are defined.

"Detach" always raises an exception, as no event sources are defined.

"IsAttached" always returns FALSE, as no event sources are defined

"Handler" always returns NIL, as no event sources are defined

"Me" returns the identity of the calling thread.

"MyParam" returns the parameter given when the thread was created.

"UrgencyOf" returns the urgency given when the thread was created.

"ProcessesException" returns the current exception given that is was raised by this module; otherwise raises an exception.

"IsProcessesException" returns TRUE iff the current exception was raised by this module.

1.4.10 Semaphores

DEFINITION MODULE Semaphores;

(* This module provides mutual exclusion facilities for use by processes. *)

TYPE
  SEMAPHORE;

PROCEDURE Create (VAR s: SEMAPHORE; initialCount: CARDINAL );
  (* Creates and returns s as the identity of a new semaphore that has its
     associated count initialized to initialCount, and has no processes yet
     waiting on it.
  *)

PROCEDURE Destroy (VAR s: SEMAPHORE);
  (* Recovers the resources used to implement the semaphore s, provided that
     no process is waiting for s to become free.
  *)

PROCEDURE Claim (s: SEMAPHORE);
  (* If the count associated with the semaphore s is non-zero, decrements
     this count and allows the calling process to continue; otherwise
     suspends the calling process until s is released.
  *)

PROCEDURE Release (s: SEMAPHORE);
  (* If there are any processes waiting on the semaphore s, allows one of
     them to enter the ready state; otherwise increments the count associated
     with s.
  *)

PROCEDURE CondClaim (s: SEMAPHORE): BOOLEAN;
  (* If the call Claim(s) s would cause the calling process to be suspended,
     the count associated with s is not changed, and the procedure returns
     FALSE.  Otherwise the associated count is decremented, and the procedure
     returns TRUE.
  *)

END Semaphores.
The module "Semaphores" is implemented using the data structures "mutex" and "condition" in conjungtion with the Posix threads also used in module "Proceses".
The meaning of the procedures is exactly as described in the definition module.

1.4.11 SysClock

DEFINITION MODULE SysClock;

(* Facilities for accessing a system clock that records the date and time of
   day.
*)

CONST
  maxSecondParts = 0;
  
TYPE
  Month    = [1 .. 12];
  Day      = [1 .. 31];
  Hour     = [0 .. 23];
  Min      = [0 .. 59];
  Sec      = [0 .. 59];
  Fraction = [0 .. maxSecondParts];
  UTCDiff  = [-780 .. 720];
  DateTime =
    RECORD
      year:      CARDINAL;
      month:     Month;
      day:       Day;
      hour:      Hour;
      minute:    Min;
      second:    Sec;
      fractions: Fraction;      (* parts of a second *)
      zone:      UTCDiff;       (* Time zone Differential Factor which is the
                                   number of minutes to add to local time to 
                                   obtain UTC. *)
      summerTimeFlag: BOOLEAN;  (* Interpretation of flag depends on local
                                   usage. *)
    END;
  
PROCEDURE CanGetClock (): BOOLEAN;
  (* Tests if a system clock can be read *)
  
PROCEDURE CanSetClock (): BOOLEAN;
  (* Tests if a system clock can be set *)
  
PROCEDURE IsValidDateTime (userData: DateTime): BOOLEAN;
  (* Tests if the value of userData represents a valid date and time *)
  
PROCEDURE GetClock (VAR userData: DateTime);
  (* If possible, assigns system date and time of day to userData *)
  
PROCEDURE SetClock (userData: DateTime);
  (* If possible, sets the system clock to the values of userData *)
  
END SysClock.
The module "SysClock" provides procedures to read and set the system clock. The constant "maxSecondParts" indicates the number of fractions a second is split into by the system clock. The system clock of the Apple Macintosh uses whole seconds, thus "maxSecondParts = 0".

"CanGetClock" indicates whether the system clock can be read. This result is always "TRUE" for the Mac OS.

"CanSetClock" indicates whether the system clock can be set. This result is always "FALSE" for the Mac OS.

"IsValidDateTime" checks, whether "userData" contains a correct date and time.

"GetClock" returns the actual time of the system clock.

"SetClock" sets the system clock to the time given in "userData".

table of contents (library) start page chapter 2 (library)