-- File CIFExtIO.mesa
-- Written by Dan Fitzpatrick and Martin Newell, June 1980
-- Last updated: December 21, 1981 4:09 PM

DIRECTORY

CIFExtIODefs: FROM "CIFExtIODefs",
IODefs: FROM "IODefs" USING [SP, TAB, FF, LF, CR, NUL, WriteString, WriteLine, GetOutputStream, SetOutputStream],
MiscDefs: FROM "MiscDefs" USING[CallDebugger],
SegmentDefs: FROM "SegmentDefs" USING[Read, Append, Write, OldFileOnly, FileNameError, FileError, FileHandle, NewFile, DestroyFile],
StreamDefs: FROM "StreamDefs" USING[GetDefaultDisplayStream, DiskHandle, NewByteStream, StreamHandle],
StringDefs: FROM "StringDefs" USING[AppendLongDecimal, StringToLongNumber, StringToNumber, AppendDecimal],
InlineDefs: FROM "InlineDefs" USING [DIVMOD];

CIFExtIO: PROGRAM
IMPORTS IODefs, MiscDefs, SegmentDefs, StreamDefs, StringDefs, InlineDefs
EXPORTS CIFExtIODefs =

BEGIN OPEN IODefs, MiscDefs, SegmentDefs, StreamDefs, StringDefs, StringDefs, InlineDefs;

ReadStringDirect: PUBLIC PROCEDURE [t: STRING, s: StreamHandle] =
BEGIN
i:CARDINAL;
t.length ← 0;
WHILE TRUE DO
SELECT (t.text[0] ← s.get[s]) FROM
SP, TAB, FF, LF, CR, ’, , NUL => BEGIN
IF s.endof[s] THEN RETURN;
LOOP;
END;
ENDCASE => EXIT;
ENDLOOP;
FOR i ← 1,i+1 DO
IF i = t.maxlength THEN BEGIN
t.length ← t.maxlength;
WriteLine["STRING OVERFLOW IN READSTRING (CIFExtIO)"];
WriteLine[t];
EXIT;
END;
SELECT (t.text[i] ← s.get[s]) FROM
SP, TAB, FF, LF, CR, ’,, NUL => BEGIN
EXIT;
END;
ENDCASE => IF s.endof[s] THEN RETURN;
ENDLOOP;
t.length ← i;
END;

ReadLineDirect: PUBLIC PROCEDURE [t: STRING, s: StreamHandle] =
BEGIN
i:CARDINAL;
WHILE TRUE DO
SELECT (t.text[0] ← s.get[s]) FROM
SP, TAB, FF, LF, ’, , NUL => LOOP;
CR => BEGIN
t ← "";
RETURN;
END;
ENDCASE => EXIT;
ENDLOOP;
FOR i ← 1,i+1 DO
IF i = t.maxlength THEN BEGIN
t.length ← t.maxlength;
WriteLine["STRING OVERFLOW IN READSTRING (CIFExtIO)"];
WriteLine[t];
EXIT;
END;
SELECT (t.text[i] ← s.get[s]) FROM
CR => EXIT;
ENDCASE;
ENDLOOP;
t.length ← i;
END;

WriteStringDirect: PUBLIC PROCEDURE [t: STRING, s: StreamHandle] =
BEGIN
i:CARDINAL;
FOR i ← 0,i+1 WHILE i < t.length DO
s.put[s,t.text[i]];
ENDLOOP;
END;

WriteLineDirect: PUBLIC PROCEDURE [t: STRING, s: StreamHandle] =
BEGIN
WriteStringDirect[t,s];
s.put[s,CR];
END;

ReadLong: PUBLIC PROCEDURE [s: StreamHandle] RETURNS [LONG UNSPECIFIED] =
BEGIN
t: STRING ← [50];
ReadStringDirect[t,s];
RETURN[StringToLongNumber[t,10]];
END;

ReadShort: PUBLIC PROCEDURE [s: StreamHandle] RETURNS [UNSPECIFIED] =
BEGIN
t: STRING ← [50];
ReadStringDirect[t,s];
RETURN[StringToNumber[t,10]];
END;

WriteLong: PUBLIC PROCEDURE [n:LONG UNSPECIFIED, s: StreamHandle] =
BEGIN
t: STRING ← [50];
AppendLongDecimal[t,n];
WriteStringDirect[t,s];
END;

WriteShort: PUBLIC PROCEDURE [n:UNSPECIFIED, s: StreamHandle] =
BEGIN
t: STRING ← [50];
AppendDecimal[t,n];
WriteStringDirect[t,s];
END;

PutLong: PUBLIC PROCEDURE [i: LONG UNSPECIFIED, s: StreamHandle] =
BEGIN
low,high: CARDINAL;
byteHigh, byteLow : CARDINAL;
[low,high] ← BreakLongPointer[i];
[byteHigh,byteLow] ← DIVMOD[low,256];
s.put[s,byteHigh];
s.put[s,byteLow];
[byteHigh,byteLow] ← DIVMOD[high,256];
s.put[s,byteHigh];
s.put[s,byteLow];
END;

GetLong: PUBLIC PROCEDURE [s:StreamHandle] RETURNS [LONG UNSPECIFIED] =
BEGIN
low,high: CARDINAL;
low ← s.get[s] * 256;
low ← low + s.get[s];
high ← s.get[s] * 256;
high ← high + s.get[s];
RETURN[MakeLongPointer[low,high]];
END;

PutReal: PUBLIC PROCEDURE [r: REAL, s:StreamHandle] =
BEGIN
PutLong[LOOPHOLE[r , LONG CARDINAL],s];
END;

GetReal: PUBLIC PROCEDURE [s:StreamHandle] RETURNS [r: REAL] =
BEGIN
r ← LOOPHOLE[GetLong[s],REAL];
END;

OpenFile
: PUBLIC PROCEDURE [str:STRING, ch:CHARACTER] RETURNS[stream:DiskHandle] =
-- Given a string return a stream handle
-- w means open for writing
-- r means open for reading
BEGIN
SELECT ch FROM
’w => BEGIN
DeleteFile[str];
stream ← NewByteStream[str, Write + Append];
stream.reset[stream];
END;
’r => BEGIN
stream ← NewByteStream[str, Read];
stream.reset[stream];
END;
ENDCASE => CallDebugger["Uniplemented Type in OpenFile"];
END;

CloseStream
: PUBLIC PROCEDURE [stream:DiskHandle] =
-- flushes & closes disk handle
BEGIN
stream.destroy[stream];
END;

DeleteFile: PUBLIC PROCEDURE [str:STRING] =
-- Given a string find file with that name and remove it from directory
BEGIN
ENABLE BEGIN
FileNameError => CONTINUE;--Signal generated because file didn’t exist: ignore
FileError => BEGIN
save:StreamHandle ← GetOutputStream[];
SetOutputStream[GetDefaultDisplayStream[]];
WriteString[str];
WriteLine[": Can’t Delete"];
SetOutputStream[save];
CONTINUE
END;
END;
DestroyFile[NewFile[str,Write,OldFileOnly]];
END;

MakeLongPointer: PROCEDURE[low,high: UNSPECIFIED]
RETURNS[LONG POINTER] = MACHINE CODE
BEGIN --nothing to do-- END;

BreakLongPointer: PROCEDURE[lptr: LONG POINTER]
RETURNS[low,high: UNSPECIFIED] = MACHINE CODE
BEGIN --nothing to do-- END;

END.