-- JaMStreamImpl.mesa -- Last changed by Doug Wyatt, 7-Oct-81 17:14:51 DIRECTORY JaMBasic USING [Object, Root, Tag], JaMInternal USING [Frame], JaMOps, JaMStorage, Ascii USING [CR], Inline USING [BITAND, LowHalf], StreamDefs; JaMStreamImpl: MONITOR IMPORTS JaMOps, JaMStorage, Inline, StreamDefs EXPORTS JaMOps = { OPEN StreamDefs, JaMStorage, JaMOps, JaMInternal, JaMBasic; -- Types and Constants streamMax: CARDINAL = 10; StreamEntry: TYPE = RECORD[index: CARDINAL, handle: StreamHandle]; StreamTable: TYPE = ARRAY[0..streamMax) OF StreamEntry; -- Globals zone: UNCOUNTED ZONE = JaMStorage.Zone[]; streamLen: CARDINAL _ 0; streamIndex: CARDINAL _ 0; -- next stream index streams: LONG POINTER TO StreamTable; deadstream,badname: name Object; -- Streams MakeStream: PUBLIC PROC[s: StreamHandle, tag: Tag] RETURNS[stream Object] = { New: ENTRY PROC[s: StreamHandle] RETURNS[CARDINAL] = INLINE { i: CARDINAL _ 0; IF streamLenname.maxlength THEN GOTO BadName; StringText[string,name]; s _ (SELECT items FROM bytes => NewByteStream, words => NewWordStream, ENDCASE => ERROR)[name,access ! FileNameError => GOTO BadName]; IF Inline.BITAND[access,Read]#0 THEN s _ NewStreamWithPutback[s]; RETURN[MakeStream[s,L]]; EXITS BadName => ERROR Error[badname]; }; NewStreamWithPutback: PROC[f: StreamHandle] RETURNS[StreamHandle] = { d: PBData _ zone.NEW[PBDataRecord _ [handle: f, back: FALSE, item: 0]]; s: StreamHandle _ zone.NEW[StreamObject _ [reset: PBReset, get: PBGet, putback: PBPutback, endof: PBEndof, put: PBPut, destroy: PBDestroy, data: d]]; RETURN[s]; }; PBReset: PROC[s: StreamHandle] = { d: PBData _ s.data; f: StreamHandle _ d.handle; f.reset[f]; }; PBGet: PROC[s: StreamHandle] RETURNS[UNSPECIFIED] = { d: PBData _ s.data; item: UNSPECIFIED; IF d.back THEN { item _ d.item; d.back _ FALSE } ELSE { f: StreamHandle _ d.handle; item _ f.get[f] }; RETURN[item]; }; PBPutback: PROC[s: StreamHandle, item: UNSPECIFIED] = { d: PBData _ s.data; d.item _ item; d.back _ TRUE; }; PBEndof: PROC[s: StreamHandle] RETURNS[BOOLEAN] = { d: PBData _ s.data; IF d.back THEN RETURN[FALSE] ELSE { f: StreamHandle _ d.handle; RETURN[f.endof[f]] }; }; PBPut: PROC[s: StreamHandle, item: UNSPECIFIED] = { d: PBData _ s.data; f: StreamHandle _ d.handle; f.put[f,item]; }; PBDestroy: PROC[s: StreamHandle] = { d: PBData _ s.data; f: StreamHandle _ d.handle; f.destroy[f]; zone.FREE[@d]; zone.FREE[@s]; }; -- Intrinsics JRun: PROC[frame: Frame] = { string: string Object _ PopString[frame.opstk]; stream: stream Object _ MakeFileStream[string,Read,bytes]; stream.tag _ X; Execute[frame,stream]; }; JByteStream: PROC[frame: Frame] = { access: AccessOptions _ PopCardinal[frame.opstk]; string: string Object _ PopString[frame.opstk]; stream: stream Object _ MakeFileStream[string,access,bytes]; Push[frame.opstk,stream]; }; JWordStream: PROC[frame: Frame] = { access: AccessOptions _ PopCardinal[frame.opstk]; string: string Object _ PopString[frame.opstk]; stream: stream Object _ MakeFileStream[string,access,words]; Push[frame.opstk,stream]; }; JReadItem: PROC[frame: Frame] = { stream: stream Object _ PopStream[frame.opstk]; s: StreamHandle _ GetStream[stream]; ok: BOOLEAN _ NOT s.endof[s]; IF ok THEN { item: INTEGER _ s.get[s]; PushInteger[frame.opstk,item] } ELSE KillStream[stream]; PushBoolean[frame.opstk,ok]; }; JWriteItem: PROC[frame: Frame] = { item: LONG INTEGER _ PopInteger[frame.opstk]; stream: stream Object _ PopStream[frame.opstk]; s: StreamHandle _ GetStream[stream]; s.put[s,Inline.LowHalf[item]]; }; JReadLine: PROC[frame: Frame] = { stream: stream Object _ PopStream[frame.opstk]; s: StreamHandle _ GetStream[stream]; localline: STRING _ [256]; line: TextObject _ TextNew[localline]; found: BOOLEAN _ FALSE; string: string Object; { ENABLE UNWIND => TextFree[@line]; UNTIL s.endof[s] DO c: CHARACTER _ s.get[s]; TextPut[@line,c]; found _ TRUE; IF c=Ascii.CR THEN EXIT; ENDLOOP; IF found THEN string _ MakeString[TextRead[@line]]; }; TextFree[@line]; IF found THEN Push[frame.opstk,string] ELSE KillStream[stream]; PushBoolean[frame.opstk,found]; }; JWriteBytes: PROC[frame: Frame] = { string: string Object _ PopString[frame.opstk]; stream: stream Object _ PopStream[frame.opstk]; s: StreamHandle _ GetStream[stream]; Put: PROC[c: CHARACTER] RETURNS[BOOLEAN] = { s.put[s,c]; RETURN[FALSE] }; StringForAll[string,Put]; }; JKillStream: PROC[frame: Frame] = { stream: stream Object _ PopStream[frame.opstk]; KillStream[stream]; }; -- Initialization InstallStream: PROC[why: InstallReason, frame: Frame] = { SELECT why FROM init => { streams _ zone.NEW[StreamTable _ ALL[[0,NIL]]]; streamLen _ 0; streamIndex _ 0; }; free => { zone.FREE[@streams]; }; register => { deadstream _ MakeName[".deadstream"L]; badname _ MakeName[".badname"L]; RegisterExplicit[frame,".run"L,JRun]; RegisterExplicit[frame,".bytestream"L,JByteStream]; RegisterExplicit[frame,".wordstream"L,JWordStream]; RegisterExplicit[frame,".readitem"L,JReadItem]; RegisterExplicit[frame,".writeitem"L,JWriteItem]; RegisterExplicit[frame,".readline"L,JReadLine]; RegisterExplicit[frame,".writebytes"L,JWriteBytes]; RegisterExplicit[frame,".killstream"L,JKillStream]; }; ENDCASE; }; Install[InstallStream]; }.