file: PascalNoviceFilesImpl.mesa
last modified by McCreight, October 4, 1984 5:29:18 pm PDT
last modified by Ramshaw, December 25, 1982 12:06 pm
written by McCreight, December 19, 1980 10:44 AM
Pascal files for the novice user: slow, but anything works
Last Edited by: Starkweather, October 4, 1984 6:05:27 pm PDT
DIRECTORY
Atom USING [MakeAtom, PutProp],
Basics USING [LowByte],
Convert USING [RealFromRope, RopeFromReal],
FS USING [Error, StreamOpen],
IO,
PascalBasic,
PascalNoviceFiles,
PrincOpsUtils USING [LongCopy],
Real USING [DefaultSinglePrecision],
RefText USING [TrustTextAsRope],
Rope USING [Cat, Equal, Fetch, FromChar, Length],
ViewerIO USING [CreateViewerStreams];
PascalNoviceFilesImpl: CEDAR PROGRAM
IMPORTS Atom, Basics, Convert, FS, IO, PascalBasic, PrincOpsUtils, RefText, Rope, ViewerIO
EXPORTS PascalNoviceFiles =
BEGIN OPEN PascalBasic, PascalNoviceFiles;
V A R I A B L E S (all private)
Control: PascalTextFile;
Input: PUBLIC PascalTextFile;
Output: PUBLIC PascalTextFile;
Tty: PUBLIC PascalTextFile;
openFiles: MesaFilePtr ← NIL;
nilStream: IO.STREAMIO.CreateStream[
streamProcs: IO.CreateStreamProcs[
variety: inputOutput,
class: $NilStream,
getChar: NilGetChar, putChar: NilPutChar, endOf: NilEndOf,
unsafeGetBlock: NilUnsafeGetBlock,
unsafePutBlock: NilUnsafePutBlock,
close: NilClose],
streamData: NIL];
anonNo, ttyNo: PascalInteger ← 0;
P R O C E D U R E S
Text File Operations:
PrepareForTextRead: UNSAFE PROCEDURE [file: PascalTextFilePtr] =
TRUSTED BEGIN
IF file.baseFile = NIL OR file.baseFile.in = NIL THEN
PascalAttachFile[file: @file.baseFile, dir: in, type: text];
END;
PrepareForTextWrite: UNSAFE PROCEDURE [file: PascalTextFilePtr] =
TRUSTED BEGIN
IF file.baseFile = NIL OR file.baseFile.out = NIL THEN
PascalAttachFile[file: @file.baseFile, dir: out, type: text];
END;
PascalTextBREAK: PUBLIC PROCEDURE [file: PascalTextFilePtr] =
TRUSTED BEGIN
NULL; -- !! Should do some sort of flush
END;
PascalTextGET: PUBLIC PROCEDURE [file: PascalTextFilePtr] =
TRUSTED BEGIN
IF NOT file.validElement THEN PascalTextFinishGet[file];
file.validElement ← FALSE;
END;
PascalTextElement: PUBLIC PROCEDURE [file: PascalTextFilePtr]
RETURNS [PascalChar] =
TRUSTED BEGIN
IF NOT file.validElement THEN PascalTextFinishGet[file];
RETURN[file.element];
END;
PascalTextFinishGet: PUBLIC PROCEDURE [file: PascalTextFilePtr] =
TRUSTED BEGIN
PrepareForTextRead[file];
file.element ← file.baseFile.in.GetChar[ !
IO.EndOfStream => GOTO EOF];
file.eoln ← FALSE;
SELECT file.element FROM
IN ['A..'Z] =>
IF NOT file.control.readUpperCase THEN
file.element ← file.element - 'A + 'a;
IN ['a..'z] =>
IF NOT file.control.readLowerCase THEN
file.element ← file.element - 'a + 'A;
'\N --CR-- => {
file.eoln ← TRUE; file.lineNo ← file.lineNo + 1; file.element ← ' };
IN [0C..' ) =>
IF NOT file.control.readAllControlChars THEN file.element ← ' ;
'Z - 100B --Ctrl-Z-- => GOTO EOF;
ENDCASE => NULL;
file.validElement ← TRUE;
EXITS
EOF => {
file.baseFile.eof ← file.eoln ← file.validElement ← TRUE;
file.element ← ' };
END;
PascalTextPUT: PUBLIC PROCEDURE [file: PascalTextFilePtr] =
TRUSTED BEGIN
c: PascalChar;
PrepareForTextWrite[file];
SELECT file.element FROM
IN ['A..'Z] =>
IF NOT file.control.writeUpperCase THEN c ← file.element - 'A + 'a;
IN ['a..'z] =>
IF NOT file.control.writeLowerCase THEN c ← file.element - 'a + 'A;
'\N --CR-- => c ← file.element;
IN [0C..' ) =>
IF NOT file.control.writeAllControlChars THEN file.element ← ' ;
ENDCASE => c ← file.element;
file.baseFile.out.PutChar[c];
END;
PascalTextRESET: PUBLIC PROCEDURE [file: PascalTextFilePtr] =
TRUSTED BEGIN
PrepareForTextRead[file];
file.baseFile.in.Reset[];
file.baseFile.eof ← FALSE;
file.eoln ← TRUE;
file.lineNo ← 1;
file.element ← ' ;
file.validElement ← FALSE;
END;
PascalTextREWRITE: PUBLIC PROCEDURE [file: PascalTextFilePtr] =
TRUSTED BEGIN
PrepareForTextWrite[file];
file.baseFile.out.Reset[];
file.baseFile.out.SetLength[0 ! IO.Error =>
{IF ec = NotImplementedForThisStream THEN CONTINUE}];
file.baseFile.eof ← file.baseFile.in # nilStream;
END;
PascalTextPAGE: PUBLIC PROCEDURE [file: PascalTextFilePtr] =
BEGIN
PascalWriteLn[file: file];
PascalWriteChar[file: file, item: '\F --form feed--];
PascalWriteLn[file: file]
END;
PascalTextEOF: PUBLIC PROCEDURE [file: PascalTextFilePtr] RETURNS [BOOLEAN] =
TRUSTED BEGIN
IF NOT file.validElement THEN PascalTextFinishGet[file];
RETURN[file.baseFile.eof]
END;
PascalTextEOLN: PUBLIC PROCEDURE [file: PascalTextFilePtr] RETURNS [BOOLEAN] =
TRUSTED BEGIN
IF NOT file.validElement THEN PascalTextFinishGet[file];
RETURN[file.eoln]
END;
Binary File Operations:
PascalBREAK: PUBLIC PROCEDURE [
file: PascalFilePtr, length: CARDINAL,
element: LONG POINTER] = {NULL}; -- !! Should be some form of Flush
PascalGET: PUBLIC UNSAFE PROCEDURE [
file: PascalFilePtr, length: CARDINAL,
element: LONG POINTER -- TO ARRAY[0..length/2) OF UNSPECIFIED --] =
UNCHECKED BEGIN
PrepareForRead[file];
IF length = 1 THEN
element^ ← file.in.GetChar[ ! IO.EndOfStream => {file.eof ← TRUE; CONTINUE}]
ELSE IF length # file.in.UnsafeGetBlock[[base: element, startIndex: 0,
count: length]] THEN file.eof ← TRUE;
END;
PascalPUT: PUBLIC PROCEDURE [
file: PascalFilePtr, length: CARDINAL,
element: LONG POINTER -- TO ARRAY[0..length/2) OF UNSPECIFIED --] =
TRUSTED BEGIN
PrepareForWrite[file];
IF length = 1 THEN
file.out.PutChar[LOOPHOLE[Basics.LowByte[LOOPHOLE[element^]]]]
ELSE file.out.UnsafePutBlock[[base: element, startIndex: 0, count: length]];
END;
PascalRESET: PUBLIC UNSAFE PROCEDURE [
file: PascalFilePtr, length: CARDINAL,
element: LONG POINTER -- TO ARRAY[0..length) OF UNSPECIFIED --] =
UNCHECKED BEGIN
PrepareForRead[file];
file.in.SetIndex[0];
file.eof ← FALSE;
PascalGET[file, length, element];
END;
PascalREWRITE: PUBLIC PROCEDURE [
file: PascalFilePtr, length: CARDINAL ← 0,
element: LONG POINTER -- TO ARRAY[0..length/2) OF UNSPECIFIED --NIL] =
TRUSTED BEGIN
PrepareForWrite[file];
file.out.Reset[];
file.out.SetLength[0 ! IO.Error =>
{IF ec = NotImplementedForThisStream THEN CONTINUE}];
file.eof ← TRUE;
END;
PascalRead, PascalReadLong: PUBLIC UNSAFE PROCEDURE [
file: PascalFilePtr, length: CARDINAL,
element: LONG POINTER -- TO ARRAY[0..length/2) OF UNSPECIFIED --,
item: LONG POINTER -- TO ARRAY[0..length/2) OF UNSPECIFIED --] =
UNCHECKED BEGIN
IF length = 1 THEN item^ ← element^
ELSE PrincOpsUtils.LongCopy[from: element, nwords: length/2, to: item];
PascalGET[file: file, length: length, element: element];
END;
PascalWrite, PascalWriteLong: PUBLIC UNSAFE PROCEDURE [
file: PascalFilePtr, length: CARDINAL,
element: LONG POINTER TO -- ARRAY[0..length/2) OF -- UNSPECIFIED,
item: LONG POINTER TO -- ARRAY[0..length/2) OF -- UNSPECIFIED] =
UNCHECKED BEGIN
IF length = 1 THEN element^ ← item^
ELSE PrincOpsUtils.LongCopy[from: item, nwords: length/2, to: element];
PascalPUT[file: file, length: length, element: element];
END;
PascalEOF: PUBLIC PROCEDURE [file: PascalFilePtr] RETURNS [BOOLEAN] = TRUSTED {
RETURN[IF file^ = NIL THEN TRUE ELSE file.eof]};
formatted input and output:
PascalReadLn: PUBLIC PROCEDURE [file: PascalTextFilePtr] =
TRUSTED BEGIN
WHILE NOT PascalTextEOLN[file] DO PascalTextGET[file] ENDLOOP;
PascalTextGET[file];
END;
PascalWriteLn: PUBLIC PROCEDURE [file: PascalTextFilePtr] =
TRUSTED BEGIN
PrepareForTextWrite[file];
file.baseFile.out.PutChar[('\N -- CR -- )];
IF file.baseFile.in = nilStream THEN file.element ← ' ;
END;
PascalReadInteger: PUBLIC PROCEDURE [file: PascalTextFilePtr]
RETURNS [PascalInteger] =
TRUSTED BEGIN
PrepareForTextRead[file];
SkipBlanks[file];
SELECT file.element FROM
'- => {PascalTextGET[file]; RETURN[-ReadDecimal[file].n]};
'+ => {PascalTextGET[file]; RETURN[ReadDecimal[file].n]};
ENDCASE => RETURN[ReadDecimal[file].n];
END;
SkipBlanks: PROCEDURE [file: PascalTextFilePtr] =
TRUSTED BEGIN
WHILE NOT PascalTextEOF[file]
AND
(SELECT file.element FROM
'-, '+, IN ['0..'9], '., IN ['a..'z], IN ['A..'Z] => FALSE,
ENDCASE => TRUE) DO PascalTextGET[file] ENDLOOP;
END;
ReadDecimal: PROCEDURE [file: PascalTextFilePtr]
RETURNS [n, digitCount: PascalInteger] =
TRUSTED BEGIN
n ← 0;
digitCount ← 0;
IF NOT PascalTextEOF[file] AND file.element NOT IN ['0..'9] THEN
SIGNAL NumericInputError;
WHILE file.element IN ['0..'9] DO
n ← 10*n + (file.element - '0);
digitCount ← digitCount + 1;
PascalTextFinishGet[file];
ENDLOOP;
END;
PascalWriteInteger: PUBLIC PROCEDURE [
file: PascalTextFilePtr, item: PascalInteger,
fieldMinLength: PascalInteger ← -1] =
TRUSTED BEGIN
sayMinus: BOOLEANFALSE;
digits: ARRAY [0..15] OF [0..9];
nDigits: [0..15] ← 0;
i: PascalInteger;
stream: IO.STREAM;
PrepareForTextWrite[file];
stream ← file.baseFile.out;
IF NOT fieldMinLength IN [0..1] THEN stream.PutChar[' ];
IF sayMinus ← item < 0 THEN {
item ← -item; fieldMinLength ← fieldMinLength - 1};
IF item = 0 THEN {digits[0] ← 0; nDigits ← 1}
ELSE
WHILE item # 0 DO
digits[nDigits] ← item MOD 10;
nDigits ← nDigits + 1;
item ← item/10;
ENDLOOP;
FOR i IN [1..fieldMinLength - nDigits] DO stream.PutChar[' ] ENDLOOP;
IF sayMinus THEN stream.PutChar['-];
FOR i DECREASING IN [0..nDigits) DO
stream.PutChar['0 + digits[i]] ENDLOOP;
IF file.baseFile.in = nilStream THEN file.element ← '0 + digits[0];
END;
PascalReadReal: PUBLIC PROCEDURE [file: PascalTextFilePtr]
RETURNS [PascalReal] =
TRUSTED BEGIN
s: REF TEXTNEW[TEXT[50]];
s.length ← 0;
PrepareForTextRead[file];
SkipBlanks[file];
WHILE
(SELECT file.element FROM
IN ['a..'z], IN ['A..'Z], '+, '-, '., IN ['0..'9] => TRUE,
ENDCASE => FALSE) DO
s[s.length] ← file.element;
s.length ← s.length + 1;
PascalTextFinishGet[file];
ENDLOOP;
RETURN[Convert.RealFromRope[RefText.TrustTextAsRope[s]]];
END;
PascalWriteReal: PUBLIC PROCEDURE [
file: PascalTextFilePtr, item: PascalReal,
fieldMinLength, fracLength: PascalInteger ← -1] =
TRUSTED BEGIN
shortFracLength: INTEGER ← fracLength;
PrepareForTextWrite[file];
IF NOT fieldMinLength IN [0..1] THEN
file.baseFile.out.PutChar[' ];
PascalWriteString[file, Convert.RopeFromReal[
from: item,
precision:
IF fracLength < 0 THEN Real.DefaultSinglePrecision ELSE shortFracLength], fieldMinLength];
END;
PascalReadChar: PUBLIC PROCEDURE [file: PascalTextFilePtr]
RETURNS [PascalChar] =
TRUSTED BEGIN
c: PascalChar;
PrepareForTextRead[file];
c ← PascalTextElement[file];
PascalTextGET[file];
RETURN[c];
END;
PascalWriteChar: PUBLIC PROCEDURE [
file: PascalTextFilePtr, item: PascalChar,
fieldMinLength: PascalInteger ← -1] =
TRUSTED BEGIN
i: PascalInteger;
PrepareForTextWrite[file];
FOR i IN [1..fieldMinLength) DO
file.baseFile.out.PutChar[' ] ENDLOOP;
IF fieldMinLength#0 THEN
BEGIN
IF file.baseFile.in = nilStream THEN file.baseFile.out.PutChar[item];
file.element ← item;
END;
END;
PascalReadBoolean: PUBLIC PROCEDURE [file: PascalTextFilePtr]
RETURNS [PascalBoolean] =
TRUSTED BEGIN
b: PascalBoolean;
PrepareForTextRead[file];
SkipBlanks[file];
SELECT file.element FROM
'T, 't => b ← TRUE;
'F, 'f => b ← FALSE;
ENDCASE => {SIGNAL NumericInputError; b ← FALSE};
WHILE
(SELECT file.element FROM
IN ['a..'z], IN ['A..'Z] => TRUE,
ENDCASE => FALSE) DO PascalTextFinishGet[file] ENDLOOP;
RETURN[b];
END;
PascalWriteBoolean: PUBLIC PROCEDURE [
file: PascalTextFilePtr, item: PascalBoolean,
fieldMinLength: PascalInteger ← -1] =
TRUSTED BEGIN
IF NOT fieldMinLength IN [0..1] THEN
PascalWriteChar[file, ' ];
PascalWriteString[file, IF item THEN "TRUE" ELSE "FALSE", fieldMinLength];
END;
PascalReadArrayOfChar, PascalReadLongArrayOfChar:
PUBLIC UNSAFE PROCEDURE [
file: PascalTextFilePtr,
item: CharArrayPtr, arrayBound: PascalInteger] =
UNCHECKED BEGIN
v: CharArrayConcretePtr ← item;
i: PascalInteger;
PrepareForTextRead[file];
FOR i IN [1..arrayBound] DO
v[i] ← PascalTextElement[file]; PascalTextGET[file]; ENDLOOP;
END;
PascalWriteArrayOfChar, PascalWriteLongArrayOfChar:
PUBLIC PROCEDURE [
file: PascalTextFilePtr,
item: CharArrayPtr,
arrayBound: PascalInteger, fieldMinLength: PascalInteger ← -1] =
TRUSTED BEGIN
v: CharArrayConcretePtr ← LOOPHOLE[item];
i, arrayLim: PascalInteger;
PrepareForTextWrite[file];
FOR i IN [arrayBound..fieldMinLength) DO
file.baseFile.out.PutChar[' ] ENDLOOP;
arrayLim ←
IF fieldMinLength < 0 THEN arrayBound ELSE MIN[fieldMinLength, arrayBound];
FOR i IN [1..arrayLim] DO
file.baseFile.out.PutChar[v[i]] ENDLOOP;
IF file.baseFile.in = NIL AND
((fieldMinLength < 0 AND arrayLim > 0) OR fieldMinLength>0) THEN
file.element ← IF arrayLim > 0 THEN v[arrayLim] ELSE ' ;
END;
ReadString: PRIVATE PROCEDURE [file: PascalTextFilePtr] RETURNS [r: ROPE]=
TRUSTED BEGIN
PrepareForTextRead[file];
IF file.baseFile.in = NIL THEN PascalTextRESET[file];
r ← "";
WHILE NOT PascalTextEOLN[file] AND NOT file.baseFile.eof DO
r ← Rope.Cat[r, Rope.FromChar[file.element]];
PascalTextGET[file];
ENDLOOP;
END;
PascalWriteString, PascalWriteLongString: PUBLIC PROCEDURE [
file: PascalTextFilePtr, item: ROPE, fieldMinLength: PascalInteger ← -1] =
TRUSTED BEGIN
i, len, stringLim: PascalInteger;
PrepareForTextWrite[file];
len ← item.Length[];
FOR i IN [len..fieldMinLength) DO
file.baseFile.out.PutChar[' ] ENDLOOP;
stringLim ← IF fieldMinLength < 0 THEN len ELSE MIN[fieldMinLength, len];
FOR i IN [0..stringLim) DO
file.baseFile.out.PutChar[Rope.Fetch[item, i]] ENDLOOP;
IF file.baseFile.in = NIL AND
((fieldMinLength < 0 AND stringLim > 0) OR fieldMinLength>0) THEN
file.element ← IF stringLim > 0 THEN Rope.Fetch[item, stringLim-1] ELSE ' ;
END;
P R O C E D U R E S NOT Called by PasMesa
(and hence, intended to be called as external procedures by the Pascal
program, or else from Mesa code that implements such external procedures).
text file operations
PascalCleanupFiles: PUBLIC PROCEDURE [] =
BEGIN ENABLE IO.Error =>
{IF ec = NotImplementedForThisStream THEN CONTINUE};
FOR f: MesaFilePtr ← openFiles, f.openFileLink WHILE f#NIL DO
IF f.in # NIL THEN f.in.Flush[];
IF f.out # NIL THEN f.out.Flush[];
IF f.inSource # NIL THEN f.inSource.Flush[];
IF f.inSource2 # NIL THEN f.inSource2.Flush[];
IF f.outDest # NIL THEN f.outDest.Flush[];
IF f.outDest2 # NIL THEN f.outDest2.Flush[];
ENDLOOP;
END;
CloseMesaFile: PROCEDURE [f: MesaFilePtr] =
BEGIN
IF f.in # NIL THEN {f.in.Close[]; f.in ← NIL};
IF f.out # NIL THEN {f.out.Close[]; f.out ← NIL};
IF f.inSource # NIL THEN {f.inSource.Close[]; f.inSource ← NIL};
IF f.inSource2 # NIL THEN {f.inSource2.Close[]; f.inSource2 ← NIL};
IF f.outDest # NIL THEN {f.outDest.Close[]; f.outDest ← NIL};
IF f.outDest2 # NIL THEN {f.outDest2.Close[]; f.outDest2 ← NIL};
END;
PascalInventFileName: PUBLIC PROCEDURE [name: ROPENIL] RETURNS [PascalFile] =
BEGIN
openFiles ← z.NEW[MesaFile ← [name: name, openFileLink: openFiles]];
RETURN[LOOPHOLE[openFiles]];
END; -- end of PascalInventFileName
PascalAttachFile: PUBLIC PROCEDURE [
file: PascalFilePtr, dir: PascalFileDirection ← in,
type: PascalFileType ← text] =
TRUSTED BEGIN
name: ROPENIL;
mFile: MesaFilePtr;
RequestFileName: PROCEDURE[] =
TRUSTED BEGIN
PascalWriteLn[file: @Control];
PascalWriteString[file: @Control, item: "** File name = "];
name ← ReadString[file: @Control];
PascalReadLn[file: @Control];
END;
BEGIN -- for EXITS
IF file^ = NIL THEN {RequestFileName[]; file^ ← PascalInventFileName[name]}
ELSE name ← file.name;
As of this moment, file^ is a vaild non-NIL PascalFile. Unfortunately, we need
a REF to a MesaFile rather than a LONG POINTER, so that reference counting
will be turned on as we change the fields of this heap object. So, here we go. . .
mFile ← LOOPHOLE[file^];
Atom.PutProp[Atom.MakeAtom[name], $PascalFile, mFile];
CloseMesaFile[mFile];
SELECT TRUE FROM
Rope.Equal[s1: name, s2: "Tty", case: FALSE] =>
BEGIN
h: IO.STREAMIO.ROS[];
h.Put[[rope["PascalTty"]], [integer[ttyNo]]];
name ← h.RopeFromROS[];
h.Close[];
ttyNo ← ttyNo+1;
GOTO UseWindow;
END;
Rope.Equal[s1: name, s2: "Nil", case: FALSE] =>
{mFile.in ← mFile.out ← nilStream};
ENDCASE =>
BEGIN
IF Rope.Length[name]=0 THEN
BEGIN
h: IO.STREAMIO.ROS[];
h.Put[[rope["PascalAnonymous"]], [integer[anonNo]]];
name ← h.RopeFromROS[];
h.Close[];
anonNo ← anonNo+1;
GOTO UseWindow;
END;
SELECT dir FROM
in, both =>
BEGIN
mFile.in ← FS.StreamOpen[name, $write !
FS.Error => IF error.group=user THEN GOTO UseWindow];
mFile.out ← nilStream;
--following code commented out due to laziness of Cedar 5.0 converter:
IF type = text THEN
BEGIN
mFile.inSource2 ← mFile.in;
[in: mFile.inSource, out: mFile.outDest] ←
ViewerIO.CreateViewerStreams[name];
mFile.in ← IO.CreateDribbleStream[stream: mFile.inSource2,
dribbleTo: mFile.outDest];
END;
END;
ENDCASE => -- out --
BEGIN
mFile.out ← FS.StreamOpen[name, $create !
FS.Error => IF error.group=user THEN GOTO UseWindow];
mFile.in ← nilStream;
--following code commented out due to laziness of Cedar 5.0 converter:
IF type = text THEN
BEGIN
mFile.outDest2 ← mFile.out;
[in: mFile.inSource, out: mFile.outDest] ←
ViewerIO.CreateViewerStreams[name];
mFile.out ← IO.CreateDribbleStream[stream: mFile.outDest2,
dribbleTo: mFile.outDest];
END;
END;
END;
EXITS
UseWindow =>
BEGIN
[in: mFile.in, out: mFile.out] ← ViewerIO.CreateViewerStreams[name: name];
END;
END;
END; -- of PascalAttachFile
PrepareForRead: UNSAFE PROCEDURE [file: PascalFilePtr] =
TRUSTED BEGIN
IF file^ = NIL OR file^.in = NIL THEN
PascalAttachFile[file: file, dir: in, type: binary];
END;
PrepareForWrite: UNSAFE PROCEDURE [file: PascalFilePtr] =
TRUSTED BEGIN
IF file^ = NIL OR file^.out = NIL THEN
PascalAttachFile[file: file, dir: out, type: binary];
END;
Stream operations
NilGetChar: PROCEDURE [self: IO.STREAM] RETURNS [CHARACTER] =
BEGIN
ERROR IO.EndOfStream[self];
END;
NilPutChar: PROCEDURE [self: IO.STREAM, char: CHARACTER] = {NULL};
NilEndOf: PROCEDURE [self: IO.STREAM] RETURNS [BOOLEAN] =
{RETURN[TRUE]};
NilUnsafeGetBlock: PROCEDURE [self: IO.STREAM,
block: IO.UnsafeBlock] RETURNS [INT] = {RETURN[0]};
NilUnsafePutBlock: PROCEDURE [self: IO.STREAM,
block: IO.UnsafeBlock] = {NULL};
NilClose: PROCEDURE[self: IO.STREAM, abort: BOOLEANFALSE] =
{NULL};
Initialization
Input ← PascalTextFile[baseFile: PascalInventFileName[name: "PascalInput"]];
Output ← PascalTextFile[baseFile: PascalInventFileName[name: "PascalOutput"]];
Tty ← PascalTextFile[baseFile: PascalInventFileName[name: "Tty"]];
Control ← PascalTextFile[baseFile: PascalInventFileName[name: "PascalControl"]];
TRUSTED {[in: Control.baseFile.in, out: Control.baseFile.out] ←
ViewerIO.CreateViewerStreams[name: "PascalControl"]};
anonNo ← ttyNo ← 0;
TRUSTED {
PascalWriteString[file: @Control,
item: "Pascal Cedar Runtime of May 9, 1985"];
PascalWriteLn[file: @Control]};
END. -- PascalNoviceFilesImpl