1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
(* Library module defined by the International Standard
Information technology - programming languages
BS ISO/IEC 10514-1:1996E Part 1: Modula-2, Base Language.
Copyright ISO/IEC (International Organization for Standardization
and International Electrotechnical Commission) 1996-2021.
It may be freely copied for the purpose of implementation (see page
707 of the Information technology - Programming languages Part 1:
Modula-2, Base Language. BS ISO/IEC 10514-1:1996). *)
DEFINITION MODULE IOLink;
(* Types and procedures for the standard implementation of channels *)
IMPORT IOChan, IOConsts, ChanConsts, SYSTEM;
TYPE
DeviceId;
(* Values of this type are used to identify new device modules,
and are normally obtained by them during their initialization.
*)
PROCEDURE AllocateDeviceId (VAR did: DeviceId);
(* Allocates a unique value of type DeviceId, and assigns this
value to did. *)
PROCEDURE MakeChan (did: DeviceId; VAR cid: IOChan.ChanId);
(* Attempts to make a new channel for the device module identified
by did. If no more channels can be made, the identity of
the invalid channel is assigned to cid. Otherwise, the identity
of a new channel is assigned to cid.
*)
PROCEDURE UnMakeChan (did: DeviceId; VAR cid: IOChan.ChanId);
(* If the device module identified by did is not the module that
made the channel identified by cid, the exception wrongDevice is
raised; otherwise the channel is deallocated, and the value
identifying the invalid channel is assigned to cid.
*)
TYPE
DeviceTablePtr = POINTER TO DeviceTable;
(* Values of this type are used to refer to device tables *)
TYPE
LookProc = PROCEDURE (DeviceTablePtr, VAR CHAR, VAR IOConsts.ReadResults) ;
SkipProc = PROCEDURE (DeviceTablePtr) ;
SkipLookProc = PROCEDURE (DeviceTablePtr, VAR CHAR, VAR IOConsts.ReadResults) ;
WriteLnProc = PROCEDURE (DeviceTablePtr) ;
TextReadProc = PROCEDURE (DeviceTablePtr, SYSTEM.ADDRESS, CARDINAL, VAR CARDINAL) ;
TextWriteProc = PROCEDURE (DeviceTablePtr, SYSTEM.ADDRESS, CARDINAL) ;
RawReadProc = PROCEDURE (DeviceTablePtr, SYSTEM.ADDRESS, CARDINAL, VAR CARDINAL) ;
RawWriteProc = PROCEDURE (DeviceTablePtr, SYSTEM.ADDRESS, CARDINAL) ;
GetNameProc = PROCEDURE (DeviceTablePtr, VAR ARRAY OF CHAR) ;
ResetProc = PROCEDURE (DeviceTablePtr) ;
FlushProc = PROCEDURE (DeviceTablePtr) ;
FreeProc = PROCEDURE (DeviceTablePtr) ;
(* Carry out the operations involved in closing the corresponding
channel, including flushing buffers, but do not unmake the
channel.
*)
TYPE
DeviceData = SYSTEM.ADDRESS;
DeviceTable =
RECORD (* Initialized by MakeChan to: *)
cd: DeviceData; (* the value NIL *)
did: DeviceId; (* the value given in the call of MakeChan *)
cid: IOChan.ChanId; (* the identity of the channel *)
result: IOConsts.ReadResults;(* the value notKnown *)
errNum: IOChan.DeviceErrNum; (* undefined *)
flags: ChanConsts.FlagSet; (* ChanConsts.FlagSet{} *)
doLook: LookProc; (* raise exception notAvailable *)
doSkip: SkipProc; (* raise exception notAvailable *)
doSkipLook: SkipLookProc; (* raise exception notAvailable *)
doLnWrite: WriteLnProc; (* raise exception notAvailable *)
doTextRead: TextReadProc; (* raise exception notAvailable *)
doTextWrite: TextWriteProc; (* raise exception notAvailable *)
doRawRead: RawReadProc; (* raise exception notAvailable *)
doRawWrite: RawWriteProc; (* raise exception notAvailable *)
doGetName: GetNameProc; (* return the empty string *)
doReset: ResetProc; (* do nothing *)
doFlush: FlushProc; (* do nothing *)
doFree: FreeProc; (* do nothing *)
END;
(* The pointer to the device table for a channel is obtained using the
following procedure: *)
(*
If the device module identified by did is not the module that made
the channel identified by cid, the exception wrongDevice is raised.
*)
PROCEDURE DeviceTablePtrValue (cid: IOChan.ChanId; did: DeviceId): DeviceTablePtr;
(*
Tests if the device module identified by did is the module
that made the channel identified by cid.
*)
PROCEDURE IsDevice (cid: IOChan.ChanId; did: DeviceId) : BOOLEAN;
TYPE
DevExceptionRange = IOChan.ChanExceptions;
(*
ISO standard states defines
DevExceptionRange = [IOChan.notAvailable .. IOChan.textParseError];
however this must be a bug as other modules need to raise
IOChan.wrongDevice exceptions.
*)
PROCEDURE RAISEdevException (cid: IOChan.ChanId; did: DeviceId;
x: DevExceptionRange; s: ARRAY OF CHAR) <* noreturn *> ;
(* If the device module identified by did is not the module that made the channel
identified by cid, the exception wrongDevice is raised; otherwise the given exception
is raised, and the string value in s is included in the exception message.
*)
PROCEDURE IsIOException () : BOOLEAN;
(* Returns TRUE if the current coroutine is in the exceptional execution state
because of the raising af an exception from ChanExceptions;
otherwise FALSE.
*)
PROCEDURE IOException () : IOChan.ChanExceptions;
(* If the current coroutine is in the exceptional execution state because of the
raising af an exception from ChanExceptions, returns the corresponding
enumeration value, and otherwise raises an exception.
*)
END IOLink.
|