JaMStreamImpl.mesa
Doug Wyatt, 7-Oct-81 17:14:51
Russ Atkinson, July 22, 1983 7:18 pm
DIRECTORY
Ascii USING [CR],
Basics USING [BITAND, LowHalf],
JaMBasic USING [Object, Root, Tag],
JaMInternal USING [Frame],
JaMOps,
JaMStorage,
StreamDefs;
JaMStreamImpl: MONITOR
IMPORTS JaMOps, JaMStorage, Basics, 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 streamLen<streamMax THEN {
streamIndex ← streamIndex + 1; i ← streamIndex;
streams[streamLen] ← [i,s]; streamLen ← streamLen + 1 };
RETURN[i];
};
i: CARDINAL ← New[s];
IF i=0 THEN ERROR Error[limitchk]; -- *** fix this?
RETURN[[tag,stream[index: i, stamp: root.stamp]]];
};
GetStream: PUBLIC PROC[ob: stream Object] RETURNS[StreamHandle] = {
Get: ENTRY PROC[index: CARDINAL] RETURNS[StreamHandle] = INLINE {
FOR i: CARDINAL DECREASING IN[0..streamLen) DO
entry: StreamEntry ← streams[i];
IF entry.index=index THEN RETURN[entry.handle];
ENDLOOP;
RETURN[NIL];
};
s: StreamHandle ← NIL;
IF ob.stamp=root.stamp THEN s ← Get[ob.index];
IF s=NIL THEN ERROR Error[deadstream] ELSE RETURN[s];
};
KillStream: PUBLIC PROC[ob: stream Object] = {
Kill: ENTRY PROC[index: CARDINAL] RETURNS[StreamHandle] = {
FOR i: CARDINAL DECREASING IN[0..streamLen) DO
entry: StreamEntry ← streams[i];
IF entry.index=index THEN {
streamLen ← streamLen - 1;
FOR j: CARDINAL IN[i..streamLen) DO streams[j] ← streams[j+1] ENDLOOP;
streams[streamLen] ← [0,NIL]; RETURN[entry.handle] };
ENDLOOP;
RETURN[NIL];
};
s: StreamHandle ← NIL;
IF ob.stamp=root.stamp THEN s ← Kill[ob.index];
IF s#NIL THEN s.destroy[s];
};
PBData: TYPE = LONG POINTER TO PBDataRecord;
PBDataRecord: TYPE = RECORD[handle: StreamHandle, back: BOOLEAN, item: UNSPECIFIED];
MakeFileStream: PROC[string: string Object, access: AccessOptions,
items: {bytes,words}] RETURNS[stream Object] = {
name: STRING ← [100];
s: StreamHandle ← NIL;
IF string.length>name.maxlength THEN GOTO BadName;
StringText[string,name];
s ← (SELECT items FROM bytes => NewByteStream, words => NewWordStream,
ENDCASE => ERROR)[name,access ! FileNameError => GOTO BadName];
IF Basics.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: BOOLEANNOT 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,Basics.LowHalf[item]];
};
JReadLine: PROC[frame: Frame] = {
stream: stream Object ← PopStream[frame.opstk];
s: StreamHandle ← GetStream[stream];
localline: STRING ← [256];
line: TextObject ← TextNew[localline];
found: BOOLEANFALSE; 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];
}.