[comp.lang.modula2] Number 5 of 5 mailings of the proposed BSI I/O Library def mods

rbh@computer-science.nottingham.ac.UK (Roger Henry) (08/20/87)

**************
Number 5 of 5 Mailings of the Proposed BSI I/O Library Def Mods
Please see an earlier mailing for the complete list
**************
::::::::::::::
IOTermination.def
::::::::::::::
DEFINITION MODULE IOTermination;

(* Proposed BSI Standard Modula-2 I/O Library
 * Copyright Roger Henry, University of Nottingham
 * Version WG/2.0, August 17th 1987
 * Permission is given to copy this Definition Module, with the
 * copyright notice intact, for the purposes of evaluation and test.
 * At the stage of a formal draft standard, Copyright will be transferred
 * to BSI (and through BSI to other recognised standards bodies).
 * Status: For review by BSI/IST/5/13
*)


(*
Actions on program termination
*)

IMPORT
  Channel;

(*
EXPORT QUALIFIED
  Handler, Establish, Terminate;
*)

TYPE
  Private;
  Handler =
    RECORD
      code: PROC;
      data: Private;
    END;
    
(* There is a list of procedures to be called on program termination *)
(* initially the list is empty *)

PROCEDURE Establish(VAR h: Handler);
(* post: the given procedure is on the front of the list of those which *)
(*       will be called on termination *)

PROCEDURE Terminate(cn: Channel.Numbers; source, message: ARRAY OF CHAR);
(* displays channel number, source module.procedure and message *)
(* calls established procedures in the order of the list *)
(* halts the program *)

(* notes:
If module A imports module B, and both call Establish
from their initialisation part, B will be initialised before A
and terminated after A.  This is normally safe unless B calls
procedures of A through procedure variables.

If the Modula-2 system provides a general termination facility,
this module should establish its own general termination code
which will implicitly invoke procedures on its list of handlers
*)

END IOTermination.
::::::::::::::
IOErrors.def
::::::::::::::
DEFINITION MODULE IOErrors;

(* Proposed BSI Standard Modula-2 I/O Library
 * Copyright Roger Henry, University of Nottingham
 * Version WG/2.0, August 17th 1987
 * Permission is given to copy this Definition Module, with the
 * copyright notice intact, for the purposes of evaluation and test.
 * At the stage of a formal draft standard, Copyright will be transferred
 * to BSI (and through BSI to other recognised standards bodies).
 * Status: For review by BSI/IST/5/13
*)


(*
Device Error Handling Manager
*)

IMPORT
  Channel;

(*
EXPORT QUALIFIED
  ErrorHandlers, Abort, Continue,
  GetErrorHandler, SetErrorHandler,
  DeviceOK, DeviceError,
  ReportOK, ReportError;
*)
  
(* Device driver routines are required to report when *)
(* their error state changes. *)
(* The state of all channels is initiall OK *)
(* On the report of an error, *)
(* a per-channel handler routine is called. *)
(* In itially a handler is installed which causes program termination. *)
(* Post conditions given in the specifications of all library procedures *)
(* which call device driver routines assume that the default handler is *)
(* installed or that there has been no device error *)

TYPE
  ErrorHandlers =
    PROCEDURE(
	  Channel.Numbers,      (* number of Linked channel *)
	  INTEGER,              (* device dependent error number *)
      VAR ARRAY OF CHAR,        (* source module.procedure name *)
      VAR ARRAY OF CHAR         (* descriptive error message *)
    );

(*
The standard error handlers
*)
  
PROCEDURE Abort(
      cn: Channel.Numbers;
      errNum: INTEGER;
  VAR source: ARRAY OF CHAR;
  VAR msg: ARRAY OF CHAR
);
(* default error handler *)
(* shows messages and terminates the program *)

PROCEDURE Continue(
      cn: Channel.Numbers;
      errNum: INTEGER;
  VAR source: ARRAY OF CHAR;
  VAR msg: ARRAY OF CHAR
);
(* alternative standard error handler *)
(* does nothing *)

(*
The user can get and set the error handler for a channel:
*)

PROCEDURE GetErrorHandler(cn: Channel.Numbers; VAR eh: ErrorHandlers);
(* post: the current handler for the channel is assigned to eh *)

PROCEDURE SetErrorHandler(cn: Channel.Numbers; eh: ErrorHandlers);
(* post: the current handler for the channel is set to eh *)

(*
The user can test if an error has been reported.
Used in cases where the handler has continued.
*)

PROCEDURE DeviceOK(cn: Channel.Numbers): BOOLEAN;
(* post : TRUE initially and if the associated device is ok *)

(*
The error number is remembered by the manager
*)

PROCEDURE DeviceError(cn: Channel.Numbers): INTEGER;
(* pre  : the numbered channel is not ok *)
(* post : returns the latest reported device-specific error number *)

(* note:
If the user wishes to have the error message remembered,
so that it may be shown after continuation and return from the calling
routine, she or he may install their own handler which does this -
on a global or per channel basis as appropriate.
*)

(*
Drivers must report changes in the error status:
*)

PROCEDURE ReportOK(cn: Channel.Numbers);
(* post : the error state of the Linked device is noted as OK *)

PROCEDURE ReportError(
      cn: Channel.Numbers;
      errNum: INTEGER;
  VAR source: ARRAY OF CHAR;
  VAR msg: ARRAY OF CHAR
);
(* post : the error condition has been reported by calling the handler *)
(*        for the channel. *)
(*         The error state and number have been noted *)

END IOErrors.
::::::::::::::
Drivers.def
::::::::::::::
DEFINITION MODULE Drivers;

(* Proposed BSI Standard Modula-2 I/O Library
 * Copyright Roger Henry, University of Nottingham
 * Version WG/2.0, August 17th 1987
 * Permission is given to copy this Definition Module, with the
 * copyright notice intact, for the purposes of evaluation and test.
 * At the stage of a formal draft standard, Copyright will be transferred
 * to BSI (and through BSI to other recognised standards bodies).
 * Status: For review by BSI/IST/5/13
*)


(*
Interface for device drivers and indirect callers of driver routines
*)

IMPORT
  Channel;
FROM SYSTEM IMPORT
  ADDRESS;

(*
EXPORT QUALIFIED
  Conditions, TestProc,
  ReadProc, WriteProc, ResetProc, FlushProc,
  CloseProc, FreeProc,
  DriverProcs, DriverRefs,
  MakeLink,
  ToTest, ToRead, ToWrite, ToReset, ToFlush,
  ToClose, ToFree,
  IsLinked, BreakLink;
*)

(* a table of driver procedures is linked to a channel when *)
(* the channel is open to a device or device instance *)
(* The precise semantics of the operations in particular cases *)
(* shall be documented with the corresponding device modules. *)

TYPE
  Conditions =
    (canRead,			(* input operations can be tried *)
     canWrite,			(* output operations can be tried *)
     textMap,			(* conforms to text mapping rules *)
     isInteractive,		(* a terminal for example *)
     readPosMoved		(* (by reset or seek) since last Read *)
    );
  
  TestProc =			(* test if condition applies *)
    PROCEDURE(
          Channel.Numbers,
	  Conditions
    ): BOOLEAN;
  
  ReadProc =			(* if canRead, read data else terminate *)
    PROCEDURE(
          Channel.Numbers,
          CARDINAL,		(* max storage units to read *)
          ADDRESS,		(* the address to read them to *)
     VAR  CARDINAL		(* the number read - 0 implies end *)
    );
  (* note: the read operation may produce device errors. *)
  (*       It is not a device error to attempt to read more data *)
  (*       than is available *)
    
  WriteProc =			(* if canWrite, write data else terminate *)
    PROCEDURE(
          Channel.Numbers,
          CARDINAL,		(* number of storage units to write *)
          ADDRESS		(* the address to write them from *)
    );
  (* note: the write operation may produce device errors *)
  
  ResetProc =			(* if open, *)
    PROCEDURE(			(* (re)initialise device instance *)
          Channel.Numbers	(* else terminate *)
    );
  (* note: the reset operation may produce device errors *)
  
  FlushProc =			(* if canWrite, *)
    PROCEDURE(			(* force buffered data to destination *)
          Channel.Numbers	(* else terminate *)
    );
  (* note: the flush operation may produce device errors *)
  
  CloseProc =			(* if open, *)
    PROCEDURE(			(* close connection to device *)
          Channel.Numbers	(* else terminate *)
    );  
  (* close connection from driver to device *)
  (* and break the link from the channel *)
  (* note: the close operation may produce device errors *)

  FreeProc =			(* Tell driver that the channel is no *)
    PROCEDURE(			(* longer linked to it. *)
          Channel.Numbers	
    );
  (* The driver shall carry out actions as CloseProc *)
  (* but shall not report any errors *)

  DriverProcs =
    RECORD
      doTest: TestProc;			(* always legal *)
      doRead: ReadProc;			(* terminates if not canRead *)
      doWrite: WriteProc;		(* terminates if not canWrite *)
      doReset: ResetProc;		(* terminates if not open *)
      doFlush: FlushProc;		(* terminates if not canWrite *)
      doClose: CloseProc;		(* terminates if not open *)
      doFree: FreeProc;			(* always legal *)
    END;

  DriverRefs = POINTER TO DriverProcs;

(* a device driver module sets up a link between a numbered channel *)
(* and a table of driver procedures *)

PROCEDURE MakeLink(cn: Channel.Numbers; dr: DriverRefs);
(* pre : dr points to an initialised table of driver procedures *)
(* do:   if the channel is Open then terminate *)
(* post: the channel is Linked with the referenced table of driver *)
(*       procedures. *)
(* note: the driver module may subsequently change the fields of the *)
(*       driver table.  The table itself must remain in existence for *)
(*       as long as the link exists *)

(* The following group of procedures allows the current drivers for a *)
(* channel to be obtained.  If the channel is not Linked then *)
(* a procedure which terminates when called shall be returned *)

PROCEDURE ToTest(cn: Channel.Numbers): TestProc;
PROCEDURE ToRead(cn: Channel.Numbers): ReadProc;
PROCEDURE ToWrite(cn: Channel.Numbers): WriteProc;
PROCEDURE ToReset(cn: Channel.Numbers): ResetProc;
PROCEDURE ToFlush(cn: Channel.Numbers): FlushProc;
PROCEDURE ToClose(cn: Channel.Numbers): CloseProc;
PROCEDURE ToFlush(cn: Channel.Numbers): FlushProc;

PROCEDURE IsLinked(cn: Channel.Numbers): BOOLEAN;
(* post: returns TRUE iff the channel is Linked to a table of drivers *)

(* When the device Close routine is called,
it is responsible for breaking the Link *)

PROCEDURE BreakLink(cn: Channel.Numbers);
(* post: the channel is not Linked with driver procedures. *)

(*
The module shall use IOTermination to establish a termination procedure
which will call  the Free procedure on all Linked channels.
If a device driver module needs to establish its own termination
procedure then this shall close its own open channels.
*)

END Drivers.