DicentraRS232CAsyncImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Tim Diebert: June 12, 1986 4:22:36 pm PDT
DIRECTORY
DicentraRS232CAsync,
IO,
Process USING [CheckForAbort, MsecToTicks, Pause],
Pup USING [Address, Socket],
PupName USING [Error, NameLookup],
PupStream USING [Create, StreamClosing, CloseReason, Timeout, waitForever],
Rope USING [Find, ROPE, Substr]
;
DicentraRS232CAsyncImpl: CEDAR PROGRAM
IMPORTS IO, Process, PupName, PupStream, Rope
EXPORTS DicentraRS232CAsync
~ BEGIN OPEN DicentraRS232CAsync;
STREAM: TYPE ~ IO.STREAM;
ROPE: TYPE ~ Rope.ROPE;
StreamState: TYPE ~ REF StreamStateRep;
StreamStateRep: TYPE ~ RECORD [
pupStream: STREAMNIL
];
CommBusy: PUBLIC ERROR [currentUser: Rope.ROPE] = CODE;
CommError: PUBLIC ERROR [ec: Rope.ROPE] = CODE;
CreateStream: PUBLIC PROC
[host: Rope.ROPE, port: PortNumber ← 0, commParams: CommParams ← defaultParams]
RETURNS [stream: IO.STREAM] = BEGIN
ENABLE PupStream.StreamClosing => MakePupStreamError [host, why, text];
ok: CHAR;
socket: Pup.Socket ← [0, 0, 0, 32B];
commPortAddress: Pup.Address ← PupName.NameLookup[host, socket
! PupName.Error => {
codeRope: ROPEIO.PutFR[(SELECT code FROM
noRoute => "No route to %g from here",
noResponse => "No response from name lookup server for %g",
ENDCASE => "Name %g not found"), IO.rope[host]];
ERROR CommError[ec: codeRope];}];
s: StreamState = NEW [StreamStateRep];
streamProcs: REF IO.StreamProcs ← IO.CreateStreamProcs[class: $DicentraRS232CAsyncStream,
variety: inputOutput, getChar: GetChar, endOf: EndOf, putChar: PutChar, flush: Flush, close: Close, charsAvail: CharsAvail];
s.pupStream← PupStream.Create[commPortAddress, PupStream.waitForever, PupStream.waitForever];
stream ← IO.CreateStream[streamProcs, s];
IO.PutChar[s.pupStream, LOOPHOLE[port, CHAR]];
IO.PutChar[s.pupStream, LOOPHOLE[commParams.charLength, CHAR]];
IO.PutChar[s.pupStream, LOOPHOLE[commParams.speed, CHAR]];
IO.PutChar[s.pupStream, LOOPHOLE[commParams.parity, CHAR]];
IO.PutChar[s.pupStream, LOOPHOLE[commParams.stop, CHAR]];
IO.Flush[s.pupStream];
ok← IO.GetChar[s.pupStream ! IO.EndOfStream => RETRY];
IF ok = 'k THEN RETURN [stream]
ELSE ERROR CommError [IO.PutFR1["Bad return from %g", IO.rope[host]]];
END;
PutChar: PROC[self: IO.STREAM, char: CHAR] = BEGIN
ENABLE {PupStream.StreamClosing => ERROR IO.Error [ec: Failure, stream: self]; PupStream.Timeout => RETRY; IO.Error => ERROR IO.Error [ec: Failure, stream: self]; IO.EndOfStream => ERROR IO.EndOfStream[self]};
s: StreamState = NARROW [self.streamData];
IO.PutChar[s.pupStream, char];
END;
GetChar: PROC[self: IO.STREAM] RETURNS [char: CHAR] = BEGIN
ENABLE {PupStream.StreamClosing => ERROR IO.Error [ec: Failure, stream: self]; PupStream.Timeout => RETRY; IO.Error => ERROR IO.Error [ec: Failure, stream: self]; IO.EndOfStream => ERROR IO.EndOfStream[self]};
s: StreamState = NARROW [self.streamData];
DO
i: INTIO.CharsAvail[s.pupStream];
IF i # 0 THEN RETURN [IO.GetChar[s.pupStream]];
Process.Pause[Process.MsecToTicks[100]]; Process.CheckForAbort[];
ENDLOOP;
END;
Close: PROC[self: IO.STREAM, abort: BOOLFALSE] = BEGIN
ENABLE {PupStream.StreamClosing => ERROR IO.Error [ec: Failure, stream: self]; PupStream.Timeout => RETRY; IO.Error => ERROR IO.Error [ec: Failure, stream: self]; IO.EndOfStream => ERROR IO.EndOfStream[self]};
s: StreamState = NARROW [self.streamData];
IO.Close[s.pupStream];
END;
EndOf: PUBLIC PROC[self: IO.STREAM] RETURNS [BOOL] = BEGIN
ENABLE {PupStream.StreamClosing => ERROR IO.Error [ec: Failure, stream: self]; PupStream.Timeout => RETRY; IO.Error => ERROR IO.Error [ec: Failure, stream: self]; IO.EndOfStream => ERROR IO.EndOfStream[self]};
s: StreamState = NARROW [self.streamData];
RETURN [IO.EndOf[s.pupStream]];
END;
Flush: PUBLIC PROC [ self: IO.STREAM ] = BEGIN
ENABLE {PupStream.StreamClosing => ERROR IO.Error [ec: Failure, stream: self]; PupStream.Timeout => RETRY; IO.Error => ERROR IO.Error [ec: Failure, stream: self]; IO.EndOfStream => ERROR IO.EndOfStream[self]};
s: StreamState = NARROW [self.streamData];
IO.Flush[s.pupStream];
END;
CharsAvail: PUBLIC PROC [self: STREAM, wait: BOOL] RETURNS [INT] = BEGIN
ENABLE {PupStream.StreamClosing => ERROR IO.Error [ec: Failure, stream: self]; PupStream.Timeout => RETRY; IO.Error => ERROR IO.Error [ec: Failure, stream: self]; IO.EndOfStream => ERROR IO.EndOfStream[self]};
s: StreamState = NARROW [self.streamData];
RETURN [IO.CharsAvail[s.pupStream, wait]];
END;
MakePupStreamError: PROC
[ host: ROPE, why: PupStream.CloseReason, text: ROPE] = BEGIN
pos: INT ← Rope.Find[text, "+"];
codeRope: ROPEIO.PutFR["Error from %g; %s ",
IO.rope[host], IO.rope[SELECT why FROM
localClose => "Local Close",
localAbort => "Local Abort",
remoteClose => "Remote Close",
noRouteToNetwork => "No route",
transmissionTimeout => "Timeout",
ENDCASE => text]];
IF pos > 0 THEN text ← Rope.Substr[text, 0, pos];
IF why = remoteReject THEN ERROR CommBusy[currentUser: text]
ELSE ERROR CommError[ec: codeRope];
END;
END.