DIRECTORY IO USING [Backup, CharsAvail, Close, CreateStream, CreateStreamProcs, EndOf, EndOfStream, EraseChar, Flush, GetBlock, GetChar, PeekChar, PutBlock, PutChar, Reset, SP, STREAM, StreamProcs, UnsafeBlock, UnsafeGetBlock, UnsafePutBlock], IOClasses USING [], IOUtils USING [closedStreamProcs], RefText USING [ObtainScratch, ReleaseScratch]; IOClassesImpl: CEDAR PROGRAM IMPORTS IO, IOUtils, RefText EXPORTS IOClasses SHARES IO --for representation of StreamProcs = BEGIN STREAM: TYPE = IO.STREAM; StreamProcs: TYPE = IO.StreamProcs; UnsafeBlock: TYPE = IO.UnsafeBlock; Copy: PUBLIC PROC [from, to: STREAM, closeFrom, closeTo: BOOL, bufferByteCount: NAT] = { scratchLen: NAT = 128; buffer: REF TEXT _ RefText.ObtainScratch[scratchLen]; DO nBytes: NAT _ IO.GetBlock[from, buffer, 0, scratchLen ! IO.EndOfStream => EXIT]; IO.PutBlock[to, buffer, 0, nBytes]; IF nBytes # scratchLen THEN EXIT; ENDLOOP; IF closeFrom THEN IO.Close[from]; IF closeTo THEN IO.Close[to]; RefText.ReleaseScratch[buffer]; }; FilterCommentsStreamData: TYPE = REF FilterCommentsStreamRecord; FilterCommentsStreamRecord: TYPE = RECORD [ inStringLiteral: BOOL _ FALSE, inCharLiteral: BOOL _ FALSE, inExtendedChar: BOOL _ FALSE ]; FilterCommentsStreamProcs: REF IO.StreamProcs = IO.CreateStreamProcs[ variety: $input, class: $CommentFilter, getChar: FilterCommentsStreamGetChar ]; CreateCommentFilterStream: PUBLIC PROC [input: STREAM] RETURNS [IO.STREAM] = { RETURN[IO.CreateStream[ streamProcs: FilterCommentsStreamProcs, backingStream: input, streamData: NEW[FilterCommentsStreamRecord _ []]]]; }; FilterCommentsStreamGetChar: PROC [self: STREAM] RETURNS [char: CHAR] = { data: FilterCommentsStreamData = NARROW[self.streamData]; char _ self.backingStream.GetChar[]; SELECT TRUE FROM data.inExtendedChar => { data.inExtendedChar _ FALSE; -- not really, but rest of extended char can't contain '" RETURN }; data.inCharLiteral => { data.inCharLiteral _ FALSE; IF char = '\\ THEN data.inExtendedChar _ TRUE; RETURN }; data.inStringLiteral => { SELECT char FROM '\\ => data.inExtendedChar _ TRUE; '\" => data.inStringLiteral _ FALSE; -- not really, but if following char is '" it will look like a new string literal, which is ok ENDCASE; RETURN }; ENDCASE => SELECT char FROM '\" => data.inStringLiteral _ TRUE; '\' => data.inCharLiteral _ TRUE; '- => IF NOT self.backingStream.EndOf[] AND self.backingStream.PeekChar[] = '- THEN { [] _ self.backingStream.GetChar[]; DO SELECT (char _ self.backingStream.GetChar[]) FROM '\n => EXIT; '- => IF self.backingStream.GetChar[] = '- THEN { char _ IO.SP; EXIT }; ENDCASE; ENDLOOP; } ENDCASE; }; CatInputStreamData: TYPE = REF CatInputStreamRecord; CatInputStreamRecord: TYPE = RECORD [ input1, input2: STREAM, state: CatInputStreamState]; CatInputStreamState: TYPE = { initial, swapped, closed }; CatInputStreamProcs: REF IO.StreamProcs = IO.CreateStreamProcs[ variety: $input, class: $Concatenated, getChar: CatInputStreamGetChar, getBlock: CatInputStreamGetBlock, unsafeGetBlock: CatInputStreamUnsafeGetBlock, charsAvail: CatInputStreamCharsAvail, backup: CatInputStreamBackup, endOf: CatInputStreamEndOf, reset: CatInputStreamReset, close: CatInputStreamClose ]; CreateCatInputStream: PUBLIC PROC [input1, input2: STREAM] RETURNS [STREAM] = { RETURN[IO.CreateStream[streamProcs: CatInputStreamProcs, streamData: NEW[CatInputStreamRecord _ [input1: input1, input2: input2, state: $initial]]]]; }; CatInputStreamGetChar: PROC [self: STREAM] RETURNS [CHAR] = { data: CatInputStreamData = NARROW[self.streamData]; { ENABLE IO.EndOfStream => IF data.state = $initial THEN GOTO nextStream; RETURN[data.input1.GetChar[]]; EXITS nextStream => { SwapStreams[data]; RETURN[data.input1.GetChar[]]; } } }; SwapStreams: PROC [data: CatInputStreamData] = { temp: STREAM _ data.input1; IF data.state # $initial THEN ERROR; data.input1 _ data.input2; data.input2 _ temp; data.state _ $swapped; }; CatInputStreamGetBlock: PROC [self: STREAM, block: REF TEXT, startIndex: NAT, count: NAT] RETURNS [nBytesRead: NAT] = { data: CatInputStreamData = NARROW[self.streamData]; nBytesRead _ data.input1.GetBlock[block, startIndex, count]; IF nBytesRead > 0 OR data.state = $swapped THEN RETURN [nBytesRead]; SwapStreams[data]; RETURN[data.input1.GetBlock[block, startIndex, count]]; }; CatInputStreamUnsafeGetBlock: PROC [self: STREAM, block: UnsafeBlock] RETURNS [nBytesRead: INT] = TRUSTED { data: CatInputStreamData = NARROW[self.streamData]; nBytesRead _ data.input1.UnsafeGetBlock[block]; IF nBytesRead > 0 OR data.state = $swapped THEN RETURN [nBytesRead]; SwapStreams[data]; RETURN[data.input1.UnsafeGetBlock[block]]; }; CatInputStreamEndOf: PROC [self: STREAM] RETURNS [BOOL] = { data: CatInputStreamData = NARROW[self.streamData]; IF NOT data.input1.EndOf[] THEN RETURN [FALSE]; IF data.state = $swapped THEN RETURN [TRUE]; SwapStreams[data]; RETURN [data.input1.EndOf[]]; }; CatInputStreamCharsAvail: PROC [self: STREAM, wait: BOOL] RETURNS [INT] = { data: CatInputStreamData = NARROW[self.streamData]; RETURN[data.input1.CharsAvail[wait]]; }; CatInputStreamBackup: PROC [self: STREAM, char: CHAR] = { data: CatInputStreamData = NARROW[self.streamData]; data.input1.Backup[char]; }; CatInputStreamReset: PROC [self: STREAM] = { data: CatInputStreamData = NARROW[self.streamData]; data.input1.Reset[]; data.input2.Reset[]; }; CatInputStreamClose: PROC [self: STREAM, abort: BOOL] = { data: CatInputStreamData = NARROW[self.streamData]; data.input1.Close[]; data.input2.Close[]; data.state _ $closed; self.streamProcs _ IOUtils.closedStreamProcs; }; DribbleStreamData: TYPE = REF DribbleStreamRecord; DribbleStreamRecord: TYPE = RECORD [outputStream: STREAM]; DribbleStreamProcs: REF StreamProcs _ IO.CreateStreamProcs[ variety: $output, class: $Dribble, putChar: DribbleStreamPutChar, putBlock: DribbleStreamPutBlock, unsafePutBlock: DribbleStreamUnsafePutBlock, flush: DribbleStreamFlush, eraseChar: DribbleStreamEraseChar, reset: DribbleStreamReset, close: DribbleStreamClose ]; CreateDribbleOutputStream: PUBLIC PROC [output1, output2: STREAM] RETURNS [STREAM] = { RETURN[IO.CreateStream[ streamProcs: DribbleStreamProcs, streamData: NEW[DribbleStreamRecord _ [outputStream: output2]], backingStream: output1]]; }; DribbleStreamPutChar: PROC [self: STREAM, char: CHAR] = { data: DribbleStreamData = NARROW[self.streamData]; self.backingStream.PutChar[char]; data.outputStream.PutChar[char]; }; DribbleStreamPutBlock: PROC [self: STREAM, block: REF READONLY TEXT, startIndex: NAT, count: NAT] = { data: DribbleStreamData = NARROW[self.streamData]; self.backingStream.PutBlock[block, startIndex, count]; data.outputStream.PutBlock[block, startIndex, count]; }; DribbleStreamUnsafePutBlock: PROC [self: STREAM, block: IO.UnsafeBlock] = { data: DribbleStreamData = NARROW[self.streamData]; self.backingStream.UnsafePutBlock[block]; data.outputStream.UnsafePutBlock[block]; }; DribbleStreamFlush: PROC [self: STREAM] = { data: DribbleStreamData = NARROW[self.streamData]; self.backingStream.Flush[]; data.outputStream.Flush[]; }; DribbleStreamEraseChar: PROC [self: STREAM, char: CHAR] = { data: DribbleStreamData = NARROW[self.streamData]; self.backingStream.EraseChar[char]; data.outputStream.EraseChar[char]; }; DribbleStreamReset: PROC [self: STREAM] = { data: DribbleStreamData = NARROW[self.streamData]; self.backingStream.Reset[]; data.outputStream.Reset[]; }; DribbleStreamClose: PROC [self: STREAM, abort: BOOL] = { data: DribbleStreamData = NARROW[self.streamData]; self.backingStream.Close[abort]; data.outputStream.Close[abort]; }; END. ΚIOClassesImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. MBrown on January 13, 1984 1:32 pm Russ Atkinson (RRA) May 10, 1985 4:24:56 pm PDT Copy Comment-filtered Input Stream May raise IO.EndOfStream. Skip over the comment. Return ending CR, or SP if ends without CR, or raise IO.EndOfStream if comment ends with end of input. Concatenated Input Stream we preserve the information for debugging purposes Dribble Output Stream Κ – "Cedar" style˜codešœ™Kšœ Οmœ1™