2 Additional Library Modules

The additional library modules provide modules for the handling of the p1 Modula-2 specific data type "BCD", the 64-bit data types "SYSTEM.INT64" and "SYSTEM.CARD64", access to the Modula-2 runtime system, and some special services.

Some of the modules described in this chapter ("Terminal", "TermBase", "FSRndFile", "FSSeqFile") are available only for applications, others offer different functionality for tools resp. applications ("MacMisc"). For details see the description of those modules.

2.1 Extensions to the Standard Library

As the type "BCD" is a speciality of p1 Modula-2, there are no modules in the standard library to deal with this data type. The additional modules described in this chapter correspond in names and functionality with the modules of the standard library for the other numerical types.

For the data type "BCD" the following modules analogous to the standard library are provided: "BcdConv" / "BcdStr" and "BcdIO" / "SBcdIO".

To make it easier to handle 64-bit whole number data in 32-bit applications the types "SYSTEM.INT64" and "SYSTEM.CARD64" are now supported similar to the types "INTEGER" and "CARDINAL". So the following modules analogous to the standard library are provided: "LongWholeConv" / "LongWholeStr" and "LongWholeIO" / "SLongWholeIO".

Similar to the modules for types "REAL" and "LONGREAL" support has been added for the type "LONGDOUBLE". So the following modules analogous to the standard library are provided: "LongDoubleConv" / "LongDoubleStr" and "LongDoubleIO" / "SLongDoubleIO" as well as "LowLongDouble".

"FSRndFile" and "FSSeqFile" are counterparts of "RndFile" and "SeqFile" which specify files not by paths but by FSSepc structures as are returned from file open dialogs or application events.

"LineFile" is an additional device module to use the serial lines of the Apple Macintosh via the standard library modules.

"NetFile" is an additional device module to use network (TCP) connections via the standard library modules.

"ByteArrayFile" is an additional device module access data stored in memory via the standard library modules.

"LogStd" implements the possibility to log standardOut to a secondary output stream. This module is embedded into the internal structure of the library and cannot be added to the standard library with the predefined modules (in contrary to the other modules of this chapter). This restriction should be kept in mind while writing portable programs.

The module "FNames" is a useful auxiliary module to add default parts to file names.

The module "Terminal" offers the functionality of a simple terminal for the standard input and output window of an application (see also module "TermBase", chapter 2.2.4).

2.1.1 BcdConv

DEFINITION MODULE BcdConv;
 
IMPORT
  ConvTypes;

FROM SYSTEM IMPORT BCD;
 
TYPE
  ConvResults = ConvTypes.ConvResults; (* strAllRight, strOutOfRange, strWrongFormat, strEmpty *)

  BcdFormat = (
    formatOk,                (* correct conversion format *)
    decMarker,               (* none or more than one marker for the position
                                of the decimal point specified  *)
    missingChar,             (* missing characters after "=" or "\" *)
    illegalValue             (* a value that is too great to be represented
                                with this format *)
    );

(*
The format string accepted by the conversion routines has the following rules:

    Z : digit, leading " "
    # : digit, leading " "
    9 : digit, leading "0"
    = : sign, the two following characters represent "+" and "-"
    - : same as "= -"
    + : same as "=+-"
    ! : marks the position of the decimal point (no required representation)
    , : same as "!\,"
    . : same as "!\."
    \ : escape character, the follow character is printed without
         interpretation 
    other characters: copied to the result string as they are.

    Examples:
    format: " ###\.###\.###\.##9,999 =HS"
    23456.78    is converted to :    "    .   . 23.456,780 H"
    -0.123    is converted to :    "    .   .   .  0,123 S"

    "+999.99999"
    23456.78    formatResult becomes illegalValue
    -0.123    is converted to :    "-000.12300"

    "DM - ZZZZZZ,ZZ"
    23456.78    is converted to :    "DM    23456,78"
    -0.123    is converted to :    "DM -       ,12"

    "DM - #####9,99"
    23456.78    is converted to :    "DM    23456,78"
    -0.123    is converted to :    "DM -      0,12"


*)

PROCEDURE ScanBcd (inputCh: CHAR; VAR chClass: ConvTypes.ScanClass;
                   VAR nextState: ConvTypes.ScanState);
  (* Represents the start state of a finite state scanner for bcd numbers -
     assigns class of inputCh to chClass and a procedure representing the
     next state to nextState.
  *)
 
PROCEDURE FormatBcd (str: ARRAY OF CHAR): ConvResults;
  (* Returns the format of the string value for conversion to BCD *)
 
PROCEDURE ValueBcd (str: ARRAY OF CHAR): BCD;
  (* If str is well-formed, returns the value corresponding to the bcd number
     string value str, otherwise an exception is raised.
  *)
 
PROCEDURE LengthFixedBcd (bcd: BCD; place: INTEGER): CARDINAL;
  (* Returns the number of characters in the fixed-point string
     representation of bcd rounded to the given place relative to the decimal
     point.
  *)
 
PROCEDURE TestFreeFormat (format: ARRAY OF CHAR): BcdFormat ;
  (* Tests wether format is a format string accepted by conversion rouines,
     value checks cannot be done.
  *)

PROCEDURE LengthFreeBcd (bcd: BCD; format: ARRAY OF CHAR): CARDINAL;
  (* If format is a well-formed format string and bcd can be represented
     within this format, returns the number of characters in the given string
     representation of bcd, otherwise an exception is raised.
  *)
 
PROCEDURE IsBcdConvException (): BOOLEAN;
 
END BcdConv.
"BcdConv" provides the basic conversion procedures for type "BCD" analogous to the "...Conv" modules of the standard library.

"ScanBcd" is the start procedure of a finite state machine to test whether strings can be converted to type "BCD". "FormatBcd" tests a complete string whether it can be converted. "ValueBcd" converts a string to a value of type "BCD" or raises an exception, if the string does not represent a valid "BCD" number.

"LengthFixedBcd" calculates the number of characters necessary for the representation of "bcd" in fixed point notation, if the number is rounded to "place" digits.

"IsBcdConvException" allows to test, whether a exception has been raised by module "BcdConv".

A facility is provided for "BCD" numbers to define special formats for output. In particular, it is possible to define representation and position of the sign, the representation of leading zeros and the representation of decimal point and delimiter symbols. The following characters have a special meaning in the format definition string:
Zdigit, leading space
#digit, leading space (same as "Z")
9digit, leading zero
=sign is to be placed at this position, the following two format characters define the representation of "+" and "–" (e.g. "=HS" for the German "Soll / Haben")
sign is to place at this position, the representation for "+" is "  ", the representation for "–" is "–" (same as "=  –")
+sign is to be placed at this position, the representation for "+" is "+", the representation for "–" is "–" (same as "=+–")
!Defines the position of the decimal point without generation a representation (used to define a special representation)
.Defines the position of the decimal point, "." is used for representation (same as "!\.")
,Defines the position of the decimal point, "," is used for representation (same as "!\,")
\escape character to write special characters, the following character is output without any special interpretation.

All other characters are incorporated into the number at the position they occupy in the format string.

"TestFreeFormat" tests, whether "format" represents a valid format string.

"LengthFreeBcd" calculates the length of the result string when converting "bcd" to the format defined in "format".

2.1.2 BcdIO

DEFINITION MODULE BcdIO;
 
(* Input and output of bcd numbers in decimal text form *)
 
IMPORT
  IOChan;

FROM SYSTEM IMPORT BCD;
 
(* the text form of a signed bcd number is
     ["+" | "-"], decimal digit, {decimal digit},
     [".", {decimal digit}] ["$"]
*)
 
PROCEDURE ReadBcd (cid: IOChan.ChanId; VAR bcd: BCD);
  (* Skips leading spaces and removes any remaining characters
     that form part of a signed bcd number.  A corresponding value is
     assigned to the parameter bcd.  The read result is set to the
     value allRight, outOfRange, wrongFormat, endOfLine, or endOfInput.
  *)
 
PROCEDURE WriteFixed (cid: IOChan.ChanId; bcd: BCD; place: INTEGER;
                      width: CARDINAL);
  (* Writes the value of the parameter bcd in fixed-point text form,
     rounded to the given place relative to the decimal point,
     in a field of the given minimum width.
  *)
 
  (* Examples of fixed point output:
     value:     3923009   3.923009   0.0003923009
     places
     -5         3920000          0              0
     -2         3923010          0              0
     -1         3923009          4              0
      0        3923009.         4.             0.
      1       3923009.0        3.9            0.0
      4    3923009.0000     3.9230         0.0004
  *)
 
END BcdIO.
"BcdIO" provides the procedures "ReadBcd" and "WriteFixed" for input and output of values of type "BCD". The parameter "cid" has to specify a channel supporting text mode. The relationship of "BcdIO" to the standard library is that of all "...IO" modules.

2.1.3 BcdStr

DEFINITION MODULE BcdStr;
 
(* BCD/string conversions *)
 
IMPORT
  ConvTypes;
IMPORT
  BcdConv;

FROM SYSTEM IMPORT BCD;
 
TYPE
  ConvResults = ConvTypes.ConvResults; (* strAllRight, strOutOfRange,
                                          strWrongFormat, strEmpty *)
  BcdFormat = BcdConv.BcdFormat; (* formatOk, decMarker, missingChar,
                                    illegalValue *)
 
(* the string form of a signed bcd number is
     ["+" | "-"], decimal digit, {decimal digit},
     [".", {decimal digit}] ["$"]
*)
 
PROCEDURE StrToBcd (str: ARRAY OF CHAR; VAR bcd: BCD; VAR res: ConvResults);
  (* Ignores any leading spaces in str. If the subsequent characters in str
     are in the format of a signed bcd number, assigns a corresponding value
     to bcd. Assigns a value indicating the format of str to res.
  *)
 
 
PROCEDURE BcdToFixed (bcd: BCD; place: INTEGER; VAR str: ARRAY OF CHAR);
  (* Converts the value of bcd to fixed-point string form, rounded to the
     given place relative to the decimal point, and copies the possibly
     truncated result to str.
  *)
 
PROCEDURE BcdToFree (bcd: BCD; format: ARRAY OF CHAR; VAR str: ARRAY OF CHAR;
                     VAR formatResult: BcdFormat);
  (* If format is a well-format format string and bcd can be represented
     within this format, converts bcd to the given format, and assigns the
     possibly truncated result to str, and "formatOk" to formatResult.
     Otherwise assigns a value indicating the error to formatResult.
  *)
 
END BcdStr.
"Corresponding to the "...Str" modules of the standard library, "BcdStr" provides procedures for simple conversion of "BCD" to and from strings.

"StrToBcd" converts a string to a number of type "BCD" and returns the result of the format check in "res". "BcdToFixed" converts a number of type "BCD" into a string rounded to "places" digits.

"BcdToFree" converts the value "bcd" according to the format defined in "format" (cf. module "BcdConv", chapter 2.1.1). The result returned in "formatResult" indicates, whether the number could be converted.

2.1.4 ByteArrayFile

DEFINITION MODULE ByteArrayFile;
 
  (* File Data kept in memory *)
 
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 *)
  text = FlagSet{ChanConsts.textFlag};   (* text operations are requested/available *)
  raw = FlagSet{ChanConsts.rawFlag};     (* raw operations are requested/available *)

TYPE
  DataInfo = RECORD
    start: SYSTEM. ADDRESS;              (* Start address of the memory block contaiming the written data*)
    length: CARDINAL;                    (* Length of the written data *)
    allocLength: CARDINAL;               (* Length of allocated memory block *);
  END(*RECORD*);
  DataInfoPtr = POINTER TO DataInfo;
 
PROCEDURE OpenWrite (VAR cid: ChanId; VAR info: DataInfoPtr; flags: FlagSet;
                     VAR res: OpenResults);
  (* Attempts to obtain and open a channel connected to memory data.
     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, assigns a pointer to the memory description to info, and selects output mode,
     with the write position at the start of the memory location (i.e. length ist zero at start).
     If a channel cannot be opened as required, the value of res indicates the reason, and
     cid identifies the invalid channel.
     The information referenced by info is valid only after close has been performed. The
     user is responsible to DEALLOCATE the memory identfied by info when no longer needed.
  *)

PROCEDURE OpenRead (VAR cid: ChanId; start: SYSTEM. ADDRESS; length: CARDINAL; flags: FlagSet;
                    VAR res: OpenResults);
  (* Attempts to obtain and open a channel connected to the given memory data.
     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 memory location.
     If a channel cannot be opened as required, the value of res indicates the reason, and
     cid identifies the invalid channel.
  *)
 
PROCEDURE IsByteArrayFile (cid: ChanId): BOOLEAN;
  (* Tests if the channel identified by cid is open to a memory location file. *)
 
PROCEDURE Reread (cid: ChanId);
  (* If the channel identified by cid is not open to a memory location 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 memory location 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 memory location file, the
     exception wrongDevice is raised; otherwise closes the channel, and assigns the value
     identifying the invalid channel to cid.
     If the file is open for writing, the data info structure is set to the appropriate values.
  *)
 
END ByteArrayFile.
The device module "ByteArrayFile" allows to treat data stored in memory like data stored in a sequential file. For write operations, memory is allocated as needed. After closing the file, information about the allocated memory is returned. An open channel is either in read or in write mode. Switching is not possible but data may be read serveral times by using "Reread" or writen again by using "Rewrite".

"OpenWrite" opens a new memory location. 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 memorty location and "res" contains the value "opened". Otherwise, "res" indicates the error reason, and "cid" identifies the illegal channel.
The parameter "info" returns a pointer to an information record that is filled in only after "close" has been performed.

"OpenRead" opens a file for the memory location specified by "start" and "length". 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 memory location, and "res" contains the value "opened". Otherwise, "res" indicates the error reason and "cid" identifies the illegal channel.

"IsByteArrayFile" tests whether a channel has been opened by "ByteArrayFile".

If read access is specified, "Reread" positions to the start of the memory location to read the data again. Analogous, if write access is specified, "Rewrite" positions to the start of the memory location to overwrite the data. The size of the actually allocated buffer remains unchanged.

"Close" closes the file, filles in the info data for files in write mode, and destroys the assigned channel.

2.1.5 FNames

DEFINITION MODULE FNames;
 
 
PROCEDURE DefaultName (VAR namestr: ARRAY OF CHAR;
                       defaultstr: ARRAY OF CHAR);
  (* Completes missing parts in namestr with pieces provided for in defaultstr. *)
 
END(*MODULE*) FNames.
The procedure "DefaultName" is designed to add missing parts of file names from "defaultstr" to "namestr". If "defaultstr" starts with "." (but not "./" or "..") and "namestr" does not contain a dot, then "defaultstr" is appended as extension to "namestr". If "defaultstr" ends with "/" and "namestr" does not contain a slash, then "defaultstr" is inserted as path name at the start of "namestr".

2.1.6 FSRndFile

DEFINITION MODULE FSRndFile;
 
  (* Random access files *)
 
IMPORT IOChan, ChanConsts, SYSTEM;
IMPORT Files;
 
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; spec: Files. FSSpec; 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; spec: Files. FSSpec; 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 IsFSRndFile (cid: ChanId): BOOLEAN;
  (* Tests if the channel identified by cid is open to a random access file. *)
 
PROCEDURE IsFSRndFileException (): BOOLEAN;
  (* Returns TRUE if the current coroutine is in the exceptional execution state because
     of the raising of a RndFile exception; otherwise returns FALSE.
  *)
 
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 FSRndFile.
The device module "FSRndFile" 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.

"IsFSRndFile" tests whether a channel was opened by "FSRndFile".

An exception may be raised due to wrong positioning. "IsFSRndFileException" 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.

2.1.7 FSSeqFile

DEFINITION MODULE FSSeqFile;
 
  (* Rewindable sequential files *)
 
IMPORT IOChan, ChanConsts;
IMPORT Files;
 
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; spec: Files. FSSpec; 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; spec: Files. FSSpec; 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; spec: Files. FSSpec; 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 IsFSSeqFile (cid: ChanId): BOOLEAN;
  (* Tests if the channel identified by cid is open to a files sytem 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 FSSeqFile.
The device module "FSSeqFile" 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).

2.1.8 LineFile

DEFINITION MODULE LineFile;

(* serial lines *)

IMPORT IOChan, ChanConsts;

CONST
    B50 = 50;
    B75 = 75;
    B110 = 110;
    B134 = 134;
    B150 = 150;
    B200 = 200;
    B300 = 300;
    B600 = 600;
    B1200 = 1200;
    B1800 = 1800;
    B2400 = 2400;
    B4800 = 4800;
    B9600 = 9600;
    B19200 = 19200;
    B38400 = 38400;

TYPE
    StopBits = (stop1, stop2);
    Parity = (noParity, oddParity, evenParity);
    DataBits = (data5, data6, data7, data8);

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; openFlags: FlagSet; VAR res: OpenResults);
  (* Attempts to obtain and open a channel connected to a serial line of the given name.
     old and interactive are always implied; without the binary flag, text is implied.
     If successful, assigns to the parameter cid the identity of a channel
     open to a source/destination of the given name and assigns the value
     opened to the parameter res.
     If a channel cannot be opened as required, the value of the parameter
     res indicates the reason and cid identifies the bad channel.
  *)

PROCEDURE IsLineFile(cid: ChanId): BOOLEAN;
  (* Tests if the channel is open to a serial line. *)

PROCEDURE Close(VAR cid: ChanId);
  (* If the channel is not open to a serial line, the exception wrongDevice
     is raised. Otherwise, the channel is closed and the value identifying
     the bad channel is assigned to the parameter cid.
  *)

PROCEDURE LineReset (cid: ChanId; rate: CARDINAL; stop: StopBits; data: DataBits; parity: Parity);
  (* The line connected to cid is set to the given values. *)

PROCEDURE LineHandShake (cid: ChanId; software, hardware: BOOLEAN);
  (* The line connected to cid is set to the given handshake modes. *)

PROCEDURE GetWindowSize (cid: ChanId; VAR rows, cols: CARDINAL);
  (* Returns the size of the connected window (if any) in rows and columns *)

PROCEDURE SetWindowSize (cid: ChanId; rows, cols: CARDINAL);
  (* Sets the size of the connected window (if any) in rows and columns *)

END LineFile.
The module "LineFile" supplements the standard library with a module for direct access to serial ports (including those emulated over USB).

The procedures "Open", "Close" and "IsLineFile" parallel the corresponding procedures in the standard device modules.

"LineReset" and "LineHandShake" allow to change the parameter settings of the ports. Constans resp. enumeration types support for conveniant parameter values for "LineReset".

"GetWindowSize" and "SetWindowSize" allow to enquire resp. set the size of the window associated with this terminal line.

2.1.9 LogStd

DEFINITION MODULE LogStd;

IMPORT
  IOChan;

PROCEDURE SetLogChan (cid: IOChan. ChanId);
  (* Output to StdChans.  OutChan is coppied to this channel.
     Text operations are coppied, iff 
       ChanConsts. textFlag IN CurrentFlags (cid).
     Raw operations are coppied, iff
       ChanConsts. rawFlag IN CurrentFlags (cid).
     Logging is started iff cid <> IOChan. InvalidChan
  *)

PROCEDURE SuspendLogging ();
  (* suspends logging, nop if no log channel is defined. *)

PROCEDURE ResumeLogging ();
  (* resumes logging, nop if no log channel is defined. *)

PROCEDURE IsLogging (): BOOLEAN;
  (* TRUE, iff logging is enabled. *)

END LogStd.
The procedures of "LogStd" provide a facility for copying output to the standard output channel to a secondary channel. This allows automatic file protocols of the program output.

"SetLogChan" defines the channel for the copy and starts logging. Only these parts of the output ("text" and / or "raw") are copied, that the given channel can deal with. A call to "SetLogChan" with "IOChan. InvalidChan" stops logging.

"SuspendLogging" suspends logging temporarily, "ResumeLogging" resumes logging again. "IsLogging" tests, whether logging is turned on.

Attention:
Logging has an effect on the channel active as output channel in the moment of the call to "SetLogChan" only. Logging remains established for this channel, even if the output channel is changed via "StdChans. SetOutChan".

2.1.10 LongDoubleConv

DEFINITION MODULE LongDoubleConv;

  (* Low-level LONGDOUBLE/string conversions *)

IMPORT ConvTypes;
FROM SYSTEM IMPORT LONGDOUBLE;

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

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 LONGDOUBLE. *)

PROCEDURE ValueReal (str: ARRAY OF CHAR): LONGDOUBLE;
  (* Returns the value corresponding to the real number string value str if str is
     well-formed; otherwise raises the RealConv exception.
  *)

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

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

PROCEDURE LengthFixedReal (real: LONGDOUBLE; 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.
  *)

PROCEDURE IsRConvException (): 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 LongDoubleConv.
"LongDoubleConv " 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").

2.1.11 LongDoubleIO

DEFINITION MODULE LongDoubleIO;
 
  (* Input and output of real numbers in decimal text form over specified channels.
     The read result is of the type IOConsts.ReadResults.
  *)
 
IMPORT IOChan;
FROM SYSTEM IMPORT LONGDOUBLE;
 
  (* 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: LONGDOUBLE);
  (* 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: LONGDOUBLE; 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: LONGDOUBLE; 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: LONGDOUBLE; 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: LONGDOUBLE; 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 LongDoubleIO.
The module "LongDoubleIO" is corresponds to "RealIO" for input and output of values of type "LONGDOUBLE".

"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.

2.1.12 LongDoubleStr

DEFINITION MODULE LongDoubleStr;

  (* LONGDOUBLE/string conversions *)

IMPORT ConvTypes;
FROM SYSTEM IMPORT LONGDOUBLE;

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: LONGDOUBLE; 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: LONGDOUBLE; 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: LONGDOUBLE; 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: LONGDOUBLE; 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: LONGDOUBLE; 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 LongDoubleStr.
"LongDoubleStr" corresponds to "RealStr" for real numbers of type "LONGDOUBLE".

2.1.13 LongWholeConv

DEFINITION MODULE LongWholeConv;

  (* Low-level whole-number/string conversions *)

IMPORT ConvTypes;
FROM SYSTEM IMPORT INT64, CARD64;

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

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 INT64. *)

PROCEDURE ValueInt (str: ARRAY OF CHAR): INT64;
  (* Returns the value corresponding to the signed whole number string value str if str
     is well-formed; otherwise raises the WholeConv exception.
  *)

PROCEDURE LengthInt (int: INT64): 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 CARD64. *)

PROCEDURE ValueCard (str: ARRAY OF CHAR): CARD64;
  (* Returns the value corresponding to the unsigned whole number string value str if
     str is well-formed; otherwise raises the WholeConv exception.
   *)

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

PROCEDURE IsWholeConvException (): 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 LongWholeConv.
"LongWoleConv" is the low level module for conversion between strings and 64-bit whole numbers.

"ScanInt is the start procedure of a finite state machine to scan values of type "INT64" 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 := LongWholeConv. 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 "INT64" 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 "CARD64" as parameters.

2.1.14 LongWholeIO

DEFINITION MODULE LongWholeIO;
 
  (* Input and output of whole numbers in decimal text form over specified channels.
     The read result is of the type IOConsts.ReadResults.
  *)
 
IMPORT IOChan;
FROM SYSTEM IMPORT INT64, CARD64;
 
  (* 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: INT64);
  (* 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: INT64; 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: CARD64);
  (* 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: CARD64; width: CARDINAL);
  (* Writes the value of card to cid in text form, in a field of the given minimum width. *)
 
END LongWholeIO.
"LongWholeIO" handles the input and output of 64-bit 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.

2.1.15 LongWholeStr

DEFINITION MODULE LongWholeStr;

  (* Whole-number/string conversions *)

IMPORT ConvTypes;
FROM SYSTEM IMPORT INT64, CARD64;

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: INT64; 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: INT64; 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: CARD64; 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: CARD64; VAR str: ARRAY OF CHAR);
  (* Converts the value of card to string form and copies the possibly truncated result to str. *)

END LongWholeStr.
"LongWholeStr" provides simple procedures for conversions between strings and 64-bit whole numbers.

"StrToInt" converts a string into a value of type "INT64". "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 "CARD64". "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.

2.1.16 LowLongDouble

DEFINITION MODULE LowLongDouble;

FROM SYSTEM IMPORT LONGDOUBLE;

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

CONST
  radix =      2;
  places =     64;
  expoMin =    -16382;
  expoMax =    16383;
  large =      MAX (LONGDOUBLE);
  small =      0.0 (* %%%%% 3.37E-4932 *);
  IEEE =       TRUE;
  ISO =        TRUE;
  rounds =     TRUE;
  gUnderflow = TRUE;
  exception =  TRUE;
  extend =     FALSE;
  <* IF ARCH = ppc THEN *>
  nModes =     32;
  <* ELSIF (ARCH = i386) OR (ARCH = x86) THEN *>
  nModes =     16;
  <* END *>

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

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

PROCEDURE fraction (x: LONGDOUBLE): LONGDOUBLE;
  (* Returns the significand (or significant part) of x *)

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

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

PROCEDURE ulp (x: LONGDOUBLE): LONGDOUBLE;
  (* Returns the value of a unit in the last place of x *)

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

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

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

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

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

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

PROCEDURE synthesize (expart: INTEGER; frapart: LONGDOUBLE): LONGDOUBLE;
  (* Returns a value of the type LONGDOUBLE constructed from the given expart and frapart *)

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

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

PROCEDURE IsLowException (): 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 LowLongDouble.
The module "LowLongDouble" corresponds in form and contents exactly the module "LowReal". The main difference is, that it describes the properties of type "LONGDOUBLE".

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.

2.1.17 NetFile

DEFINITION MODULE NetFile;

(* 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 *)
  text = FlagSet{ChanConsts.textFlag};   (* text operations are requested/available *)
  raw = FlagSet{ChanConsts.rawFlag};     (* raw operations are requested/available *)

TYPE
  ServerId;
  CreateResults = (			(* Possible results of creating a server socket *)
    created,				(* Serversocket was successfully established *)
    portInUse,				(* Given port is already in use *)
    otherError);			(* Other error occurred *)

PROCEDURE CreateServer (VAR sid: ServerId; port: CARDINAL; VAR res: CreateResults);
  (*
     Attempts to create a server socket ready to listen on the given port.
  *)

PROCEDURE Listen (VAR cid: ChanId; sid: ServerId; openFlags: FlagSet; VAR res: OpenResults);
  (*
     Listens on the given server socket for an incomming connection (blocking call).
     Returns the channel id of a net file as soon as a connection is made to this socket.
     openFlags describe the requested features for the channel.
     Without the raw flag, text is implied; without read and write both flags are implied.
     If the channel could not be established, the invalid channel is returned.
  *)

PROCEDURE CloseServer (sid: ServerId);
  (*
     Closes the listening port.
  *)

PROCEDURE Open (VAR cid: ChanId; servername: ARRAY OF CHAR; port: CARDINAL; openFlags: FlagSet; VAR res: OpenResults);
  (*
     Attempts to obtain and open a channel connected to a network stream to the given server and port.
     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 IsNetFile (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 network stream, the exception
     wrongDevice is raised; otherwise closes the channel, and assigns the value identifying
     the invalid channel to cid.
  *)

END NetFile.
"NetFile" models sequential data streams over TCP connections. Parallel reading and writing is thus the default. Creation of a listening (server-)socket is also provided for.

"CreateServer" creates a TCP server socket bound to the given port and ready to listen on this port. If the socket cannot be created, either "portInUse" (if the port is not available) or "otherError" (for any other network problem) is returned.

"Listen" blocks until a connetion is made to the socket identified by "sid". On return, "cid" identifies a net file channel open for communication through the TCP stream with the requested features.

"CloseServer" releases the socket identified by "sid" and assigns the undefined server id to "sid".

"Open" opens a TCP connection to the requested server and port for reading and writing. The available operations may be restricted to read or write exclusively (specification necessary). If neither "text" nor "raw" is passed in "flags", only text access is allowed. After successful opening, "cid" contains the opened channel and "res" contains the value "opened". Otherwise, "res" indicates the error reason and "cid" identifies the illegal channel.

"IsNetFile" tests whether a channel has been opened by "NetFile".

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

"IOChan. Reset (cid)" does nothing.

2.1.18 SBcdIO

DEFINITION MODULE SBcdIO;

FROM SYSTEM IMPORT BCD;
 
(* Input and output of bcd numbers in decimal text form over default channels
*)
 
PROCEDURE ReadBcd (VAR bcd: BCD);
  (* Skips leading spaces and removes any remaining characters that
     form part of a signed bcd number.  A corresponding value is assigned
     to the parameter bcd.  The read result is set to the value
     allRight, outOfRange, wrongFormat, endOfLine, or endOfInput.
  *)
 
PROCEDURE WriteFixed (bcd: BCD; place: INTEGER; width: CARDINAL);
  (* Writes the value of the parameter bcd in fixed-point text form,
    rounded to the given place relative to the decimal point,
    in a field of the given minimum width.
  *)
 
END SBcdIO.
"SBcdIO" is the equivalent to "BcdIO" with predefined standard in- and outchannel.

2.1.19 SLongDoubleIO

DEFINITION MODULE SLongDoubleIO;

FROM SYSTEM IMPORT LONGDOUBLE;

  (* 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: LONGDOUBLE);
  (* 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: LONGDOUBLE; 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: LONGDOUBLE; 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: LONGDOUBLE; 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: LONGDOUBLE; 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 SLongDoubleIO.
"SLongDoubleIO" is the equivalent to "LongDoubleIO" with predefined standard in- and outchannel.

2.1.20 SLongWholeIO

DEFINITION MODULE SLongWholeIO;

FROM SYSTEM IMPORT INT64, CARD64;
 
  (* 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: INT64);
  (* 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: INT64; 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: CARD64);
  (* 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: CARD64; width: CARDINAL);
  (* Writes the value of card to the default output channel in text form, in a field of the
     given minimum width.
  *)
 
END SLongWholeIO.
"SLongWholeIO" is the equivalent to "LongWholeIO" with predefined standard in- and outchannel.

2.1.21 Terminal

DEFINITION MODULE Terminal;

  (* Input and output of character and string types directly to and
     from the Terminal window.
  *)

FROM SYSTEM IMPORT ADDRESS;

TYPE
    WrapMode = (noWrapping, wrapping);
    (* For specification of wrapping at end ot line. *)

PROCEDURE ReadChar (VAR ch: CHAR) ;
(* Reads a character from the input stream (operating in line mode) if
   possible, at end of line or end of file, the string termination character
   "" is returned.
*)

PROCEDURE ReadString (VAR str: ARRAY OF CHAR) ;
(* Reads at most HIGH (str) + 1 characters from the input stream (operating
   in line mode).  The empty string "" is returned, if reading starts at end
   of line or end of file.
*)

PROCEDURE SkipLine ;
(* Skips all characters from the input stream (operating in line mode) to and
   including the end of line mark.
*)

PROCEDURE ReadKey (VAR ch: CHAR; wait: BOOLEAN) ;
(* Returns one character from the input stream (operating in single character
   mode).  No echoing is done, but characters may be obtained from a input
   line read in line mode, that is not fully processed by calls to ReadChar /
   ReadString / SkipLine.  If "wait" is TRUE, "ReadKey" waits until a
   character is available.  If "wait" is FALSE, "ReadKey" returns immediately
   and returns the string termination character "", if no character is
   available.
*)

PROCEDURE WriteChar (ch: CHAR);
(* Writes the value of ch to the terminal.  The following control characters
   are interpreted:
   backspace:     erases the position at the left of the cursor and
                  decrements the actual column by 1.
   tab:           moves the cursor to the next tab stop (see "SetTabStops").
   carr. return:  moves the cursor to the leftmost column.
   line feed:     moves the cursor to the next row. If the cursor is in the
                  bottom line of the window, the window contents is scrolled
                  up one line and the cursor position remains unchanged.
   form feed:     erases the entire window and places the cursor in the
                  topleft corner.
   bell:          rings the bell (SysBeep (5)).
   All other control characters are ignored.
*)
   
PROCEDURE WriteString (str: ARRAY OF CHAR);
(* Writes the contents of str to the terminal. Control characters are
   interpreted as by WriteChar.
*)

PROCEDURE WriteLn;
(* Places the cursor to the beginning of the next line (writes cr + lf *)


PROCEDURE SetWrapMode (mode: WrapMode);
(* Sets the wrapping mode of the terminal according to "mode":
   noWrapping:  characters are discarded at and of line.
   wrapping:    characters are wrapped to the next line if necessary.
*)

PROCEDURE GetWrapMode (VAR mode: WrapMode);
(* Returns the actual wrapping mode *)

PROCEDURE SetTabStops (pos: CARDINAL);
(* Defines the positions of the tab stops (every "pos" columns). *)

PROCEDURE GetTabStops (VAR pos: CARDINAL);
(* Returns the actual position of the tab stops. *)


PROCEDURE NumRows (): CARDINAL ;
(* Returns the currently available number of rows for the terminal window *)

PROCEDURE NumCols (): CARDINAL ;
(* Returns the currently available number of columns for the terminal window
*)

PROCEDURE GotoRowCol (row, col: CARDINAL) ;
(* Places the cursor in row "row" and column "col".  The topleft corner is 
   (0/0).  If "col >= NumCols ()" holds, the cursor is placed in the
   rightmost column.  If "row >= NumRows ()" holds, the cursor is placed in
   the bottom row.
*)

PROCEDURE EraseScreen ;
(* Erases the entire terminal window and positions the cursor in the topleft
   corner.
*)

PROCEDURE EraseToEOL ;
(* Erases the rest of the line (including the cursor position). *)

PROCEDURE EraseToEOS ;
(* Erases the rest of the line (including the cursor position) and all
   following lines.
*)

PROCEDURE Home ;
(* Positions the cursor in the topleft corner. *)


PROCEDURE GetWindowPtr (): ADDRESS;
(* Returns the "WindowPtr" of the terminal window, to allow the user to
   customize the window (font, font size, foreground color, background color,
   window size etc.).  Please have in mind that the window may look funny, if
   you use a proportional fond.  The window is opened with "NewCWindow" if
   available, and with "NewWindow" otherwise.
*)

PROCEDURE ReInitialize;
(* This procedure should be called every time the window size, font or
   character size have changed.  It recalculates the number of rows and
   columns, and the character positions.  It then erases the window and
   positions the cursor in the topleft corner.
*)

END Terminal.
The module "Terminal" is available only for applications and offers a simple Terminal in replacement for the Terminal application. It allows to use a window for standard input and output as a simple terminal (cf. section 2.2.4 "TermBase"). Channels opened using module "TermFile" are also directed to the window used by "Terminal "(cf. section 1.3.20 "TermFile").

Output procedures

Input procedures
All input procedures recognize the key strokes "<COMMAND> ." (program termination via "HALT") and "<COMMAND><RETURN>" (end of input, cf. section 2.2.4).

Output control procedures

Window control procedures

2.1.22. VectorStorage

DEFINITION MODULE VectorStorage;

  (* 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
  VectorStorageExceptions =
  (nilDeallocation,  pointerToUnallocatedStorage, wrongStorageToUnallocate);

PROCEDURE VectorStorageException (): VectorStorageExceptions;
  (* Returns a value indicating which exception has been raised by
     the module VectorStorage.
  *)

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

END VectorStorage.

"VectorStorage" offers the same functionality as the module "Storage" part of the standard library (cf. 1.1.1). Additionally it guarantees 16 byte alignment for all returned pointers. As the compiler alignes record fields and other vector data on 16 byte boundary within their super structure, all vector data stored in dynamically allocated memory allocated by this module is correctly aligned.

2.2 Basic Modules of the Library

These modules are internal modules; the implementation of the standard library is based on it. For most of the users, these modules are only of theoretical interest, in special cases basic functionality of the library can be manipulated with these modules.

ATTENTION!

2.2.1 BasicRealConv

DEFINITION MODULE BasicRealConv;

CONST
    maxSigFigs = 16;
    defaultSigFigsReal = 8;
    defaultSigFigsLong = 16;

TYPE
    BasicRealType = LONGREAL;
    SyntaxFlags = (                     (* syntax properties *)
        leadingZero,                    (* at least one digit befor the decimal point is required *)
        decimalPoint,                   (* allow decimal point (e.g. "0.0") *)
        decimalComma,                   (* allow decimal comma (e.g. "0,0") *)
        lowercaseE);                    (* allow "e" for exponent *)
    SyntaxFlagSet = SET OF SyntaxFlags;
    ScanConvertClass = (                (* state of scanner *)
        empty,                          (* terminated before start of number *)
        continuing,                     (* scanning, number continues *)
        terminated,                     (* terminated by termination character "" *)
        stopped,                        (* terminated by other character *)
        error);                         (* terminated due to wrong syntax *)
    ScanConvertState = PROCEDURE (CHAR, VAR InputDescriptor, VAR ScanConvertClass, VAR ScanConvertState);
    InputDescriptor = RECORD
        float: BasicRealType;           (* value of already processed charachters *)
        negative: BOOLEAN;              (* sign of mantissa *)
        expNegative: BOOLEAN;           (* sign of exponent *)
        exponent: INTEGER;              (* from conversion of fraction *)
        exphi: INTEGER;                 (* converted from exponent behind "E" *)
        sigfigs: CARDINAL;              (* already processed significant characters *)
        idleState: ScanConvertClass;    (* scanner state at the end of the number *)
    END(*RECORD*);
    OutputDescriptor = RECORD
        mantissa: ARRAY [0 .. maxSigFigs - 1] OF CHAR;        (* mantissa trimmed to "m.fff..." *)
        exponent: INTEGER;                                    (* corresponding exponent *)
        negative: BOOLEAN;                                    (* sign of mantissa *)
    END(*RECORD*);

CONST                                    (* default syntax corresponds with standard *)
    defaultSyntax = SyntaxFlagSet {lowercaseE, decimalPoint};

PROCEDURE ScanConvertReal
  (inputCh: CHAR; VAR data: InputDescriptor; VAR chClass: ScanConvertClass; VAR nextState: ScanConvertState);
(* Start of a scanner that stores the scanned real number in a descriptor pointed to by "data" *)

PROCEDURE GetExponent (x: BasicRealType; sigFigs: CARDINAL): INTEGER;
(* calculates exponent for representation rounded to "sigFigs" digits *)

PROCEDURE FloatToDesc (x: BasicRealType; sigFigs: CARDINAL; VAR desc: OutputDescriptor);
(* converts "x" to string *)

PROCEDURE SetRealSyntax (flags: SyntaxFlagSet);
(* sets the properties of the scanner started with ScanConvertReal *)

PROCEDURE GetRealSyntax (VAR flags: SyntaxFlagSet);
(* returns the actual properties of the scanner started with ScanConvertReal *)

PROCEDURE GetSpecialStringReal (r: REAL; VAR str: ARRAY OF CHAR): BOOLEAN;
(* returns true iff r denotes one of the special values inf or nan and assign the text to str *)

PROCEDURE GetSpecialStringLong (r: LONGREAL; VAR str: ARRAY OF CHAR): BOOLEAN;
(* returns true iff r denotes one of the special values inf or nan and assign the text to str *)

END BasicRealConv.
All conversion and io modules for real numbers are based on "BasicRealConv". The type used for storing all internal data is determined by the this module.

The scanner starting with "ScanConvertReal" inserts the read string automatically into the record "data" for further processing. If the string is syntactically correct, it can be directly processed with "DescToFloat". The result type "ScanConvertClass" is designed in a form that allows to distinguish whether the scanning has stopped due to a syntax error ("error"), end of string at a correct point ("terminated") or a not fitting character after a correct string ("stopped"). In this situation, the user can do a test of its own, whether he treats the termination character as legal.

"DescToFloat" converts a number described in "Descriptor" into a number of type "BasicRealType".

"GetExponent" calculates the exponent of "x" after rounding to "sigFigs" significant figures.

"FloatToDesc" converts a number of type "BasicRealType" to a descriptor.

"SetRealSyntax" allows to change the behaviour of the universal scanner "ScanConvertReal". The elements of "SyntaxFlags" have the following meaning:

The default "SyntaxFlagSet {leadingZero, decimalPoint}" corresponds with the syntax for real numbers as defined in the standard.

"GetRealSyntax" returns the actual setting of the universal scanner "ScanConvertReal". This allows to reset the original state.

2.2.2 ChanDefs

DEFINITION MODULE ChanDefs;

FROM EXCEPTIONS IMPORT ExceptionSource;
FROM MacTypes IMPORT OSType;
FROM SYSTEM IMPORT ADDRESS, INT32;
IMPORT IOLink;


CONST
    illDevice = 0;
    stdInOutDevice = 1;
    streamDevice = 2;
    rewDevice = 3;
    rndDevice = 4;
    argDevice = 5;
    firstFreeDevice = 6;

    illChannel = 0;
    maxChans = 31;

TYPE
    DeviceTablePtr = IOLink. DeviceTablePtr;
    ChannIds = [0 .. maxChans];
    ChannelTable = ARRAY ChannIds OF DeviceTablePtr;
    ChanSet = SET OF ChannIds;

CONST
    allChannels = ChanSet {illChannel + 1 .. maxChans};

VAR
    openChans: ChanSet;
    channelTable: ChannelTable;
    libException: ExceptionSource;

PROCEDURE MakeChan
  (VAR cid: CARDINAL; VAR ptr: ADDRESS; tableSize: CARDINAL);
PROCEDURE UnMakeChan (cid: CARDINAL; tableSize: CARDINAL);

PROCEDURE SetTypeAndCreator (fileDescriptor: INT32; type, creator: OSType);
PROCEDURE GetFileName (fileDescriptor: INT32; VAR fname: ARRAY OF CHAR);

END ChanDefs.
The module "ChanDefs" is the basic module for the management of io channels. It provides some Mac specific functionality, which is used by other modules.

Variables of type "ChanId" (channels) are internally of type "CARDINAL" and represent a index into the array "ChanDefs. channelTable". The elements of this array are of type "IOLink. DeviceTablePtr". Manipulation of the pointers stored in this array generally cause program termination, as the various device modules store private data behind the part described by "IOLink. DeviceTable". For implementation of filter procedures the "device procedures" described in "IOLink. DeviceTable" may be overridden in the sense of the methods of an object.

The set "openChans" store all currently open channels. It is possible to test whether "cid" specifies an open channel by "CAST (CARDINAL, cid) IN openChans".

2.2.3 StdDevices

DEFINITION MODULE StdDevices;

FROM IOChan IMPORT ChanId;

VAR
    stdIn, stdOut, stdErr, stdNull: ChanId;

END StdDevices.
The modules "StdDevices" contains the actual implementation of the standard channels. Linking of "StdDevices" to an application generates and using one of the standard channels creates—indirect via "TermBase" (cf. section 2.2.4)—a terminal input / output window for this application. The functionality is described in chapter 1.3 (The Input / Output Library).

2.2.4 TermBase

DEFINITION MODULE TermBase;

FROM MacTypes IMPORT Rect;
FROM Quickdraw IMPORT WindowPtr;
FROM IOConsts IMPORT ReadResults;
FROM IOLink IMPORT DeviceTablePtr;
FROM SYSTEM IMPORT ADDRESS;

CONST
    lineTop = 255;
VAR
    textWindow: WindowPtr;
    wrap: BOOLEAN;
    numCols, numRows: INTEGER;
    actCol, actRow: INTEGER;
    tabPos: INTEGER;
    textRect: Rect;
    charHight, charWidth, charDesc, topOffset, leftOffset: INTEGER;
    inLine: ARRAY [0 .. lineTop] OF CHAR;
    inWritePos, inReadPos: INTEGER;
    mustRead, endOfFile: BOOLEAN;
    termChar: CHAR;

(* ---------------------- Internal Terminal Funktions -------------------- *)

PROCEDURE GenTerminalWindow;
PROCEDURE InitWindowData;
PROCEDURE GetCharRect (): Rect;
PROCEDURE PutSpecial (ch: CHAR);
PROCEDURE PutText (textBuf: ADDRESS; byteCount: CARDINAL);
PROCEDURE ReadAChar (wait: BOOLEAN): CHAR;
PROCEDURE GetText ;

(* ---------------------- Channel Funktions ------------------------------ *)

PROCEDURE LookLine (ptr: DeviceTablePtr; VAR ch: CHAR; VAR res: ReadResults);
PROCEDURE SkipLine (ptr: DeviceTablePtr);
PROCEDURE SkipLookLine (ptr: DeviceTablePtr; VAR ch: CHAR;
                        VAR res: ReadResults);
PROCEDURE TextReadLine (ptr: DeviceTablePtr; to: ADDRESS; maxChars: CARDINAL;
                        VAR charsRead: CARDINAL);

PROCEDURE LookEcho (ptr: DeviceTablePtr; VAR ch: CHAR; VAR res: ReadResults);
PROCEDURE SkipEcho (ptr: DeviceTablePtr);
PROCEDURE SkipLookEcho (ptr: DeviceTablePtr; VAR ch: CHAR;
                        VAR res: ReadResults);
PROCEDURE TextReadEcho (ptr: DeviceTablePtr; to: ADDRESS; maxChars: CARDINAL;
                        VAR charsRead: CARDINAL);

PROCEDURE TextWrite (ptr: DeviceTablePtr; from: ADDRESS; chars: CARDINAL);
PROCEDURE LnWrite (ptr: DeviceTablePtr);
PROCEDURE Reset (ptr: DeviceTablePtr);

PROCEDURE RawRead (ptr: DeviceTablePtr; to: ADDRESS; maxLocs: CARDINAL; VAR locsRead: CARDINAL);
PROCEDURE RawReadEcho (ptr: DeviceTablePtr; to: ADDRESS; maxLocs: CARDINAL; VAR locsRead: CARDINAL);
PROCEDURE RawWrite (ptr: DeviceTablePtr; from: ADDRESS; bytes: CARDINAL);

END TermBase.
"TermBase" is the base module for the user modules "TermFile" and "TermBase", for applications also for the module "StdDevices". It coordinates the various input streams and modes, and holds the information for correct output.

According to the definition of module "TermFile" two input modes are provided:

If channels are opened in both modes at a time, the necessary read operations for channels open in line mode always operate in line mode. If reading via a channel open in single character mode, characters available in the line buffer are processed before any new characters are read. These characters always have been echoed during input in line mode. The procedures "ReadChar", "ReadString" and "SkipLine" from module "Terminal" operate in line mode, "Terminal. ReadKey" operates in single character mode.

The following key combinations are treated specially:
"<COMMAND><RETURN>"
"<COMMAND><ENTER>"
The flag for "end of input" is set. "Terminal. ReadKey" clears this flag as does "IOChan. Reset" for a channel opened with "TermFile".
"<COMMAND> ." The program terminates via "HALT".
"<COMMAND><OPTION> ." "SYSTEM. BREAK" is called.

The output window is opened automatically for applications by "TermBase". Though "TermBase" is also linked to MPW tools (via "StdDevices") if the standard channels are used, the terminal window is only opened by the modules "Terminal" or "TermFile" in this case.

For text output he following control characters are treated specially:

For raw output, all data is processed by "QuickdrawText. DrawText" without any replacement.

2.3 Miscellaneous

This chapter summarizes all services of the library of p1 Modula-2, that do not fit into any other context.

"QuickCopy" and "SysExtensions" provide well defined access to the runtime procedures of p1 Modula-2 where this access may be necessary for the user. The use is—if not mentioned otherwise—without any hidden influence in the program.

"MacMisc" and "MacString" provide auxiliary procedures for the connection of library modules with runtime procedures of other languages or with procedures of the operating system.

2.3.1 MacMisc

DEFINITION MODULE MacMisc;

FROM IOChan IMPORT ChanId;
FROM MacTypes IMPORT OSType;

PROCEDURE SetTypeAndCreator (cid: ChanId; type, creator: OSType);
(* if "cid" identifies an open channel to a disk file, type and creator are
   set according to the parameters. Otherwise the exception "notAChannel"
   or "notAvailable" is raised.
*)

PROCEDURE Remove (VAR cid: ChanId);
(* if "cid" identifies an open channel to a disk file, the file is removed.
   The channel is closed and the value identifying the invalid channel
   is assigned to cid.
*)
    
PROCEDURE GetFileDescriptor (cid: ChanId): INTEGER;							(*V9.2*)
(* if "cid" identifies an open channel associated with a Unix file descriptor (or socket),
   the according file descriptor is returned.
*)

END MacMisc.
The procedure "SetTypeAndCreator" allows to specify type and creator according to the conventions of the Macintosh OS for all files opened with the modules "StreamFile", "SeqFile", "RndFile", "FSSeqFile", or "FSRndFile" of the standard library.
Attention: For tools "SetTypeAndCreator" is based directly upon the kernel APIs. It does not check whether a file system does support the finder flags. If applied to a file system other than HFS(+), it will silently do nothing.

The procedure "Remove" closes a file and then removes it. Like "SetTypeAndCreator", "Remove" is only applicable to files opened with the modules "StreamFile", "SeqFile", or "RndFile" of the standard library.

The procedure "GetFileDescriptor" returnes the Unix file descriptor associated with the open channel. This is mainly inteded for access to features not mapped by the standard library (like unblocking reads, setting special serial line behaviour, using "select" to survey open conections, etc.).

2.3.2 MacString

DEFINITION MODULE MacString;
 
FROM MacTypes IMPORT Str255;
 
PROCEDURE MacToModString (macStr: ARRAY OF CHAR; VAR modStr: ARRAY OF CHAR);
 
PROCEDURE ModToMacString (modStr: ARRAY OF CHAR; VAR macStr: ARRAY OF CHAR);

PROCEDURE STR255 (modStr: ARRAY OF CHAR): Str255;
 
END MacString.
This module provides conversion procedures between Macintosh Pascal strings with length information in the first byte and Modula-2 strings with termination character.

All procedures truncate the source string without error report, if it does not fit into the destination string.

The procedure "STR255" is alike "ModToMacString", but the produced Pascal string is returned on the stack instead as a parameter. The name "STR255" is kept for compatibility to earlier releases; it should not be confused with the data type "STR255" of module "SYSTEM".

For Pascal strings of maximal size (255 bytes) it is more advantageous to use the procedures "SYSTEM. FROMSTR255" and "SYSTEM. TOSTR255".

2.3.3 QuickCopy

<* ASSIGN (Foreign, TRUE) *>
DEFINITION MODULE QuickCopy;

FROM SYSTEM IMPORT
    ADDRESS;
FROM SYSTEM IMPORT
    CARD16, CARD32;

PROCEDURE CopyB (src, dst: ADDRESS; count: CARD16);
(*  Bytewise copying of count bytes from src to dst.
    Overlapping (src < dst < src + count) generates
    multiple copies of the range src .. src+bytes-1.
*)

PROCEDURE CopyBytes (src, dst: ADDRESS; count: CARD32);
(*  Optimized copying of count bytes from src to dst.
    Overlapping is handled correctly.
    CopyBytes has more fixed overhead as CopyB but is
    faster for large numbers and has no overlap problems!
*)

END QuickCopy.
"QuickCopy" provides access to two assembler procedures for fast copying of byte arrays.

"CopyB" is a simple procedure, which copies a byte array of length "count" with byte move instructions from "src" to "dest" without checks or optimization. If the destination address is within the source, this procedure will cause copy errors.

"CopyBytes" is a more general copy procedure with range check and optimization. It has more starting overhead than "CopyB". But for large arrays, it is normally faster, as it uses long word instructions whenever possible.

2.3.4 SysExceptions

DEFINITION MODULE  SysExceptions;

FROM M2EXCEPTION IMPORT M2Exceptions;
FROM M2OOEXCEPTION IMPORT M2OOExceptions;


TYPE
    SYSEXCEPTIONS =
		(busError, segmentationError, illegalInstr, trapInstr,
		 stackOverflow,
		 bcdOverflow, bcdDivZero, bcdNobcd);
    ExceptionSet = SET OF M2Exceptions;
    SysExceptionSet = SET OF SYSEXCEPTIONS;
    OOExceptionSet = SET OF M2OOExceptions;
    CallErrorDialogInfo = RECORD
        onException: ExceptionSet;
        onOOException: OOExceptionSet;
        onSysException: SysExceptionSet;
        onUserDefined: BOOLEAN;
    END(*RECORD*);

PROCEDURE SysException (): SYSEXCEPTIONS;

PROCEDURE IsSysException (): BOOLEAN;

(* There are two sets of information to decide wether or not
   the error dialog is called if the debugger is not present.
   One set (OnHandled) is used, if an exception handler is installed.
   The other set (OnUnHandled) is used, if no exception handler is installed.
   The default is: no call, if an exception handler is present, call
   on all but user defined exceptions, if no handler is present.
*)
PROCEDURE SetCallOnHandled (info: CallErrorDialogInfo);
PROCEDURE SetCallOnUnhandled (info: CallErrorDialogInfo);
PROCEDURE GetCallOnHandled (VAR info: CallErrorDialogInfo);
PROCEDURE GetCallOnUnhandled (VAR info: CallErrorDialogInfo);

PROCEDURE SetTrapsCaught (catch: BOOLEAN);

END SysExceptions.
The module "SysExceptions" provides basic services for exception handling.

The Type "SYSEXCEPTIONS" defines all runtime errors of the Macintosh OS not predefined in the standard ("busError .. stackOverflow") and the exceptions possible by the use of the type "BCD" ("bcdOverflow .. bcdNobcd"). The meaning of the first group is clear from the name. The meaning of the second group is as follows:
bcdOverflow Arithmetic overflow in an operation with operands of type "BCD" or in a conversion to type "BCD".
bcdDivZero Division by 0 in BCD division.
bcdNobcd Access to variables / constants that do not contain a valid BCD value.

"IsSysException" allows to inform, whether an exception is defined in this module, "SysException" returns the according value from "SYSEXCEPTIONS" (cf. compiler manual, chapter 2.7 (Exception Handling) and 2.11 (The Module M2EXCEPTION)).

For applications, p1 Modula-2 allows an error dialog to be shown in case of an exception before the according exception handler (or the debugger, if linked into the application) is called.
The procedures "SetCallOn..." allow to define the conditions, on which the error dialog of p1 Modula-2 shall be activated or on which the corresponding exception handler shall be activated at once. These values can also be changed from within the debugger (cf. utilities manual, chapter 1.5.4). The record "CallErrorDialogInfo" contains one set for the exceptions defined in "M2Exceptions" and one for those of "SysExceptions" and a boolean variable for all user defined exceptions. The error dialog is activated for all exceptions set in these sets. If "onUserDefined" has the value "true", the error dialog is (also) activated for user defined exceptions.

The error dialog may be raised in two situations:

The procedures "GetCallOnHandled" and "GetCallOnUnHandled" return the actual conditions for the activation of the error dialog. Thus, it is possible to do a local change without influence on the rest of the program.

The procedure "SetTrapsCaught" can be used to temporarily turn off the catching of all runtime errors of the Macintosh OS. With "SetTrapsCaught (false)" catching of those exceptions is turned off, with "SetTrapsCaught (true)" it is turned on again. If a system exception is raised while exception handling is turned off, the program is terminated immediately and a crash dump is produced This dump, which includes the register settings and the stack chain including procedure names and relative program counter values, can be viewed with the utility "Console". This can come in useful when the exact location of an exception has to be determined without the use of the debugger.

2.3.5 StackDump

DEFINITION MODULE StackDump;

PROCEDURE Dump (VAR text: ARRAY OF CHAR);

END StackDump.
The procedure "Dump" returns a textual representation of the procedure nesting at the point of call. For each stack frame module name, procedure or method number and program counter relative to the procedure start are given. The frames are separated by ", " so that the may be printed as returned or split e.g. into separate lines.
chapter 1 (library) start page chapter 3 (library)