TTYLearSiegler.mesa
Copyright Ó 1981, 1982, 1984, 1986, 1987 by Xerox Corporation. All rights reserved.
Last Edited: 13-Nov-81 15:18:10 By: CRF
Last Edited: 27-Oct-82 12:02:02 By: LXR
Tim Diebert: March 5, 1987 1:52:06 pm PST
DIRECTORY
Ascii USING [BS, ControlG, CR, LF, SP],
Basics USING [RawBytes],
IO USING [CreateStream, CreateStreamProcs, STREAM, StreamProcs, UnsafeBlock],
Process USING [GetPriority, Priority, priorityForeground, SetPriority],
Rope USING [ROPE],
TTY,
TTYConstants,
TTYPort USING [ChannelHandle, ChannelQuiesced, CharsAvailable, Create, Delete, Get, Quiesce, Put, SetParameter, TransferStatus],
TTYStream,
TTYEnvironment USING [LineSpeed];
TTYLearSiegler:
CEDAR
MONITOR
IMPORTS IO, Process, TTY, TTYPort
EXPORTS TTY, TTYStream = BEGIN
Types
STREAM: TYPE ~ IO.STREAM;
ControlG: CHAR = LOOPHOLE[Ascii.ControlG];
CR: CHAR = LOOPHOLE[Ascii.CR];
LF: CHAR = LOOPHOLE[Ascii.LF];
BS: CHAR = LOOPHOLE[Ascii.BS];
SP: CHAR = LOOPHOLE[Ascii.SP];
this might be expanded to multiple tty's by having several of thes buggers and refering to them (somehow) via handle, and having object monitors.
myTTY:
RECORD [
so: IO.STREAM ← NIL,
breakDetected: BOOLEAN ← NULL,
breakCount: INTEGER ← NULL,
channel: TTYPort.ChannelHandle ← NIL, -- also on/off flag
mode: BYTE ← TTYConstants.normal,
modeVal: CARDINAL ← 0];
receiveDeath: CONDITION;
controlStop: CHARACTER = 36C;
CreateStream:
PUBLIC
PROC []
RETURNS [stream:
IO.
STREAM] =
BEGIN
RETURN[CreateTTYInstance[NIL, NIL, NIL].ttyImpl];
END;
CreateTTYInstance:
PUBLIC
ENTRY
PROC [name: Rope.
ROPE, backingStream:
IO.
STREAM,
tty:
TTY.Handle]
RETURNS [ttyImpl, backing:
IO.
STREAM] = {
ENABLE UNWIND => NULL;
streamProcs: REF IO.StreamProcs ← IO.CreateStreamProcs[class: $TTY, variety: inputOutput, unsafeGetBlock: GetBlock, 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]]];
myTTY.so ← IO.CreateStream[streamProcs, NIL, backingStream];
RETURN[myTTY.so, NIL]};
Close:
ENTRY
PROC [self:
IO.
STREAM, abort:
BOOL ←
FALSE] ~
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;
};
CharsAvail:
PUBLIC
PROC [self:
IO.
STREAM, wait:
BOOL]
RETURNS [
INT] ~
TRUSTED
{
RETURN [TTYPort.CharsAvailable[myTTY.channel]];
};
PutChar:
ENTRY
PROC [self:
STREAM, char:
CHAR] = {
SELECT myTTY.mode
FROM
TTYConstants.normal => PutByteInternal[char];
TTYConstants.removeChars =>
myTTY.modeVal ← myTTY.modeVal*256 + LOOPHOLE[char, CARDINAL];
ENDCASE};
PutByteInternal:
INTERNAL
PROC [c:
CHAR] = {
PutIt:
PROCEDURE [c:
CHAR] =
INLINE {
[] ← TTYPort.Put[myTTY.channel, c ! TTYPort.ChannelQuiesced => CONTINUE]};
IF myTTY.channel = NIL THEN RETURN;
PutIt[c];
SELECT c
FROM
CR => PutIt[LF];
BS => {PutIt[SP]; PutIt[BS]};
ENDCASE};
WaitAttention:
PUBLIC
PROC[self:
IO.
STREAM]
RETURNS [
BYTE] = {
RETURN[
IF myTTY.breakDetected THEN TTYConstants.aborted ELSE TTYConstants.notAborted]};
SendAttention:
PUBLIC
PROC[self:
IO.
STREAM, byte:
BYTE] = {
SELECT byte
FROM
TTYConstants.aborted => {
myTTY.breakCount ← myTTY.breakCount + 1;
IF myTTY.breakCount > 0 THEN myTTY.breakDetected ← TRUE};
TTYConstants.notAborted => {
IF myTTY.breakCount > 0 THEN myTTY.breakCount ← myTTY.breakCount - 1;
IF myTTY.breakCount = 0 THEN myTTY.breakDetected ← FALSE};
ENDCASE};
SetSST:
PUBLIC
ENTRY
PROC [self:
IO.
STREAM, sst: TTYStream.SubSequenceType] = {
SELECT myTTY.mode
FROM
TTYConstants.removeChars =>
FOR i:
CARDINAL
IN [0..myTTY.modeVal)
DO
PutByteInternal[BS]; ENDLOOP;
TTYConstants.blinkDisplay => PutByteInternal[ControlG];
ENDCASE;
myTTY.mode ← sst;
myTTY.modeVal ← 0};
GetBlock:
UNSAFE
PROC [self:
STREAM, block:
IO.UnsafeBlock]
RETURNS [nBytesRead:
INT] = {
csmPriority: Process.Priority = Process.priorityForeground;
NotifyNextOfKin: ENTRY PROC = 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 {
base: LONG POINTER TO Basics.RawBytes;
UNTIL block.startIndex <
LAST[
CARDINAL]
DO
block.startIndex ← block.startIndex - LAST[CARDINAL];
base ← base + LAST[CARDINAL];
ENDLOOP;
base ← LOOPHOLE[block.base];
base[block.startIndex] ← LOOPHOLE[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[1];
ENDLOOP;
Process.SetPriority[oldPriority];
NotifyNextOfKin[];
RETURN[0];
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MAINLINE CODE --
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
END....
LOG
July 28, 1980 9:25 AM Mary MXA Created.
August 15, 1980 1:18 PM Mary MXA Many changes.
Time: August 27, 1980 7:01 PM Mary MXA Private errors on Create, BackingStream.
Time: September 12, 1980 11:41 PM SXY Added UserAbort and ResetUserAbort.
Time: September 19, 1980 3:24 PM SXY Line Speed is set to 9600bps.
Time: October 2, 1980 1:32 PM MXA Change tty init; remove Process.
October 3, 1980 5:32
PM
SXY Added tty.breakDetected, tty.breakCount and
controlStop. UserAbort, ResetUserAbort and Receive are modified to use them.
October 7, 1980 4:38
PM
SXY Priority of Receive process is raised and
Break detection is done using only tty.breakDetected.
February 23, 1981 1:24
PM
RXG Fixed bug in input stream processing;
replaced calls to Storage with Heap ops.
26-Aug-81 18:54:16 FXH Rolled into 8.0c
13-Nov-81 15:18:04 CRF Converted to new TTY interface for 8.0e.