TTYDLionImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Tim Diebert: November 16, 1985 8:29:01 pm PST
Bill Jackson (bj) July 31, 1986 2:13:40 am PDT
DIRECTORY
IO,
Process USING [GetPriority, Priority, priorityForeground, SetPriority],
TTY,
TTYPort USING [ChannelQuiesced, ChannelHandle, CharsAvailable, Create, Delete, Get, Put, Quiesce, SetParameter, TransferStatus];
TTYDLionImpl: CEDAR MONITOR
IMPORTS IO, Process, TTY, TTYPort
EXPORTS TTY ~ {
Constants
controlStop: CHAR ~ 36C;
Global State
myTTY: RECORD [
breakDetected: BOOLEANNULL,
breakCount: INTEGERNULL,
channel: TTYPort.ChannelHandle ← NIL -- also on/off flag
] ← [NULL, NULL, NIL];
receiveDeath: CONDITION;
Signals
OutOfInstances: PUBLIC ERROR ~ CODE;
Procs
Close: ENTRY PROC [self: IO.STREAM, abort: BOOLFALSE] ~ TRUSTED {
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;
};
Create: PUBLIC ENTRY PROC [] RETURNS [stream: IO.STREAM] ~ TRUSTED {
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];
};
EndOf: ENTRY PROC [self: IO.STREAM] RETURNS [BOOL] ~ {
RETURN [FALSE];
};
PutChar: ENTRY PROC [self: IO.STREAM, char: CHAR] ~ {
PutByteInternal[char];
};
CharsAvail: PUBLIC PROC [self: IO.STREAM, wait: BOOL] RETURNS [INT] ~ TRUSTED {
RETURN [TTYPort.CharsAvailable[myTTY.channel]];
};
GetChar: PROC [self: IO.STREAM] RETURNS [c: CHAR ← ' ] ~ TRUSTED {
csmPriority: Process.Priority ~ Process.priorityForeground;
oldPriority: Process.Priority ~ Process.GetPriority[];
ch: CHAR;
done: BOOLEAN;
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 ([c, done] ← ProcessChar[ch, stat]).done THEN RETURN;
ENDLOOP;
Process.SetPriority[oldPriority];
NotifyNextOfKin[]
};
NotifyNextOfKin: ENTRY PROC = TRUSTED {
myTTY.channel ← NIL;
NOTIFY receiveDeath;
};
ProcessChar: ENTRY PROC [ch: CHAR, stat: TTYPort.TransferStatus] RETURNS [c: CHAR, done: BOOLEANFALSE] = TRUSTED {
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;
done ← TRUE;
};
};
PutByteInternal: INTERNAL PROC [c: CHAR] ~ TRUSTED {
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;
};
PutIt: PROCEDURE [c: CHAR] = TRUSTED {
[] ← TTYPort.Put[myTTY.channel, c
! TTYPort.ChannelQuiesced => CONTINUE
]
};
}...