TTYDLionImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Tim Diebert: November 16, 1985 8:29:01 pm PST
DIRECTORY
IO,
Process USING [GetPriority, Priority, priorityForeground, SetPriority],
TTY,
TTYPort USING [ChannelQuiesced, ChannelHandle, CharsAvailable, Create, Delete, Get, Put, Quiesce, SetParameter, TransferStatus];
~
BEGIN
OutOfInstances: PUBLIC ERROR = CODE;
Create:
PUBLIC
ENTRY
PROC []
RETURNS [stream:
IO.
STREAM] =
TRUSTED
BEGIN
streamProcs:
REF
IO.StreamProcs ←
IO.CreateStreamProcs[class: $TTY,
variety: inputOutput, getChar: GetChar, charsAvail: CharsAvail,
putChar: PutChar, close: Close];
IF myTTY.channel # NIL THEN RETURN WITH ERROR TTY.OutOfInstances;
myTTY.channel ← TTYPort.Create[0];
myTTY.breakDetected ← FALSE; myTTY.breakCount ← 0;
TTYPort.SetParameter[myTTY.channel, [dataSetReady[TRUE]]];
TTYPort.SetParameter[myTTY.channel, [clearToSend[TRUE]]];
TTYPort.SetParameter[myTTY.channel, [lineSpeed[bps9600]]];
stream ← IO.CreateStream[streamProcs, NIL];
END;
myTTY:
RECORD [
breakDetected: BOOLEAN ← NULL,
breakCount: INTEGER ← NULL,
channel: TTYPort.ChannelHandle ← NIL -- also on/off flag
] ← [NULL, NULL, NIL];
PutChar:
ENTRY
PROC [self:
IO.
STREAM, char:
CHAR] =
BEGIN
PutByteInternal[char];
END;
PutByteInternal:
INTERNAL
PROC [c:
CHAR] =
TRUSTED {
PutIt: PROCEDURE [c: CHAR] = TRUSTED INLINE {[] ← TTYPort.Put[myTTY.channel, c ! TTYPort.ChannelQuiesced => CONTINUE]};
IF myTTY.channel = NIL THEN RETURN;
PutIt[c];
SELECT c
FROM
IO.CR => PutIt[IO.LF];
IO.BS => {PutIt[IO.SP]; PutIt[IO.BS]};
ENDCASE;
};
GetChar:
PROC [self:
IO.
STREAM]
RETURNS [c:
CHAR ← ' ] =
TRUSTED {
csmPriority: Process.Priority = Process.priorityForeground;
NotifyNextOfKin: ENTRY PROC = TRUSTED INLINE {myTTY.channel ← NIL; NOTIFY receiveDeath};
oldPriority: Process.Priority = Process.GetPriority[];
ProcessChar:
ENTRY
PROC
RETURNS [done:
BOOLEAN ←
FALSE] =
TRUSTED
INLINE {
IF stat = breakDetected
OR ch = controlStop
THEN {
myTTY.breakDetected ← TRUE; myTTY.breakCount ← myTTY.breakCount + 1;
TTYPort.SetParameter[myTTY.channel, [breakDetectedClear[TRUE]] ! TTYPort.ChannelQuiesced => CONTINUE]}
ELSE {c ← ch; RETURN[TRUE]}};
ch: CHARACTER; stat: TTYPort.TransferStatus;
Process.SetPriority[csmPriority];
DO
[ch, stat] ← TTYPort.Get[myTTY.channel ! TTYPort.ChannelQuiesced => EXIT];
IF stat=aborted OR stat=abortedByDelete THEN EXIT;
IF ProcessChar[] THEN RETURN;
ENDLOOP;
Process.SetPriority[oldPriority];
NotifyNextOfKin[]
};
CharsAvail:
PUBLIC
PROC [self:
IO.
STREAM, wait:
BOOL]
RETURNS [
INT] =
TRUSTED
BEGIN
RETURN [TTYPort.CharsAvailable[myTTY.channel]];
END;
Close:
ENTRY
PROC[self:
IO.
STREAM, abort:
BOOL ←
FALSE] =
TRUSTED
BEGIN
channel: TTYPort.ChannelHandle = myTTY.channel;
IF channel=NIL THEN RETURN;
TTYPort.Quiesce[channel];
WHILE myTTY.channel#NIL DO WAIT receiveDeath [] ENDLOOP;
TTYPort.Delete[myTTY.channel];
myTTY.channel ← NIL;
END;
EndOf:
ENTRY
PROC[self:
IO.
STREAM]
RETURNS [
BOOL] =
BEGIN
RETURN [FALSE];
END;
controlStop: CHARACTER = 36C;
receiveDeath: CONDITION;