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 ~ { controlStop: CHAR ~ 36C; myTTY: RECORD [ breakDetected: BOOLEAN _ NULL, breakCount: INTEGER _ NULL, channel: TTYPort.ChannelHandle _ NIL -- also on/off flag ] _ [NULL, NULL, NIL]; receiveDeath: CONDITION; OutOfInstances: PUBLIC ERROR ~ CODE; Close: ENTRY PROC [self: IO.STREAM, abort: BOOL _ FALSE] ~ TRUSTED { channel: TTYPort.ChannelHandle ~ myTTY.channel; IF channel=NIL THEN RETURN; TTYPort.Quiesce[channel]; 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: BOOLEAN _ FALSE] = 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 ] }; }... TTYDLionImpl.mesa Copyright c 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 Constants Global State Signals Procs WHILE myTTY.channel#NIL DO WAIT receiveDeath [] ENDLOOP; Κ~˜™Icodešœ Οmœ1™Kšœž˜%Kšœ˜—Kšœ˜—šžœ˜Kšœ˜Kšœžœ˜ Kšœ˜——Kšœ˜K˜—š Ÿœžœžœžœžœ˜4Kšžœžœžœžœ˜#K˜K˜ šžœž˜ Kšžœžœ žœžœ˜Kš žœžœ žœžœ žœžœ˜&Kšžœ˜—K˜K˜—šŸœž œžœžœ˜&šœ!˜!Kšœž˜%Kšœ˜—Kšœ˜——K˜Kšœ˜K˜—…— ¬>