-- File: PupByteStreams.mesa, Last Edit: -- HGM January 5, 1980 4:13 PM -- MAS August 8, 1980 2:20 PM -- Copyright Xerox Corporation 1979, 1980 DIRECTORY ByteBltDefs: FROM "ByteBltDefs" USING [ByteBlt], Stream: FROM "Stream" USING [ Byte, Block, CompletionCode, defaultInputOptions, Handle, InputOptions, LongBlock, Object, ShortBlock, SSTChange, SubSequenceType, TimeOut], CommUtilDefs: FROM "CommUtilDefs" USING [SelfDestruct], DriverDefs: FROM "DriverDefs" USING [doDebug, Glitch], PupPktDefs: FROM "PupPktDefs" USING [PupPktStream, PupPktStreamDestroy, PupPktStreamMake], PupStream: FROM "PupStream" USING [PupOpenMode], PupDefs: FROM "PupDefs" USING [ GetFreePupBuffer, ReturnFreePupBuffer, GetPupContentsBytes, SetPupContentsBytes, Pair, PupAddress, PupBuffer, PupSocketID, Tocks], PupTypes: FROM "PupTypes" USING [fillInSocketID]; PupByteStreams: MONITOR IMPORTS ByteBltDefs, Stream, CommUtilDefs, DriverDefs, PupPktDefs, PupDefs EXPORTS PupStream = BEGIN OPEN DriverDefs, PupDefs; myPupByteStream: Stream.Object _ [ options: Stream.defaultInputOptions, get: GetBlock, put: PutBlock, setSST: SendMark, sendAttention: SendAttention, waitAttention: WaitAttention, delete: Destroy ]; myPs: PupPktDefs.PupPktStream; inputBuffer: PupBuffer _ NIL; inputFinger: CARDINAL; inputSST: Stream.SubSequenceType _ 0; outputBuffer: PupBuffer _ NIL; outputFinger: CARDINAL _ 0; -- 0 if aData/aMark sent outputBufferSize: CARDINAL _ 0; HandleLooksLikeGarbage: PUBLIC ERROR = CODE; PupByteStreamCreate: PUBLIC PROCEDURE [remote: PupAddress, ticks: Tocks] RETURNS [Stream.Handle] = BEGIN RETURN[PupByteStreamMake[PupTypes.fillInSocketID,remote,ticks,sendRfc,[0,0]]]; END; PupByteStreamMake: PUBLIC PROCEDURE [ local: PupSocketID, remote: PupAddress, ticks: Tocks, mode: PupStream.PupOpenMode, id: Pair] RETURNS [Stream.Handle] = BEGIN newPs: PupPktDefs.PupPktStream; him: POINTER TO FRAME[PupByteStreams]; -- It is ok to UNWIND here if PupPktStreamMake doesn't work. newPs _ PupPktDefs.PupPktStreamMake[local,remote,ticks,mode,id]; him _ NEW PupByteStreams; START him; -- Do initialization code him.myPs _ newPs; RETURN[@him.myPupByteStream]; END; Destroy: PUBLIC --ENTRY-- PROCEDURE [bs: Stream.Handle] = BEGIN ENABLE UNWIND => NULL; IF doDebug AND bs.delete#Destroy THEN Glitch[HandleLooksLikeGarbage]; bs.delete _ LOOPHOLE[3]; PupPktDefs.PupPktStreamDestroy[myPs]; IF inputBuffer#NIL THEN ReturnBuffer[@inputBuffer]; IF outputBuffer#NIL THEN ReturnBuffer[@outputBuffer]; CommUtilDefs.SelfDestruct[]; END; SendAttention: PROCEDURE [sH: Stream.Handle, byte: Stream.Byte] = BEGIN myPs.sendAttention[]; END; WaitAttention: PROCEDURE [sH: Stream.Handle] RETURNS [Stream.Byte] = BEGIN myPs.waitForAttention[]; RETURN[0]; END; GetBlock: --ENTRY-- PROCEDURE[sH: Stream.Handle, block: Stream.Block, options: Stream.InputOptions] RETURNS[bytesTransferred: CARDINAL, why: Stream.CompletionCode, sst: Stream.SubSequenceType] = -- NB: block has been passed by VALUE, so we are upadting our copy, not the clients BEGIN ENABLE UNWIND => NULL; input: Stream.Block; moved: CARDINAL; bytesTransferred _ 0; sst _ inputSST; why _ normal; WHILE block.startIndex NULL; output: Stream.Block; moved: CARDINAL; IF outputBufferSize=0 THEN outputBufferSize_myPs.getSenderSizeLimit[]; WHILE block.startIndex NULL; FlushOutputBuffer[]; outputFinger _ 0; myPs.putMark[sst]; END; FlushOutputBuffer: PROCEDURE = BEGIN b: PupBuffer; -- don't leave outputBuffer dangling in case of StreamClosing IF outputBuffer=NIL THEN RETURN; b _ outputBuffer; outputBuffer _ NIL; SetPupContentsBytes[b,outputFinger]; myPs.put[b]; END; ReturnBuffer: PROCEDURE [p: POINTER TO PupBuffer] = BEGIN b: PupBuffer; b _ p^; p^ _ NIL; ReturnFreePupBuffer[b]; END; END.