file: PascalInlineFilesImpl.mesa
last modified by Ramshaw, December 25, 1982 11:01 am
written by McCreight, December 19, 1980 10:44 AM
a thin layer of Pascal files on top of IO.STREAM
DIRECTORY
Convert USING [RealFromRope, RopeFromReal],
IO,
PascalBasic,
PascalInlineFiles,
Real USING [DefaultSinglePrecision],
RefText USING [TrustTextAsRope],
Rope USING [Cat, Fetch, FromChar, Length];
PascalInlineFilesImpl: CEDAR PROGRAM
IMPORTS Convert, IO, PascalBasic, PascalInlineFiles, RefText, Rope
EXPORTS PascalInlineFiles =
BEGIN OPEN PascalBasic, PascalInlineFiles;
V A R I A B L E S (all private)
openFiles: MesaFilePtr ← NIL;
P R O C E D U R E S
Text File Operations:
PascalTextBREAK: PUBLIC PROCEDURE [file: PascalTextFilePtr] =
TRUSTED BEGIN
file.baseFile.str.Flush[];
END;
PascalTextRESET: PUBLIC PROCEDURE [file: PascalTextFilePtr] =
TRUSTED BEGIN
file.baseFile.str.SetIndex[0 !
IO.Error => {IF ec = NotImplementedForThisStream THEN CONTINUE}];
file.baseFile.eof ← FALSE;
PascalTextGET[file];
END;
PascalTextREWRITE: PUBLIC PROCEDURE [file: PascalTextFilePtr] =
TRUSTED BEGIN
file.baseFile.str.SetIndex[0 !
IO.Error => {IF ec = NotImplementedForThisStream THEN CONTINUE}];
file.baseFile.str.SetLength[0 !
IO.Error => {IF ec = NotImplementedForThisStream THEN CONTINUE}];
file.baseFile.eof ← TRUE;
END;
Binary File Operations:
PascalBREAK: PUBLIC PROCEDURE [
file: PascalFilePtr, length: CARDINAL,
element: LONG POINTER] = TRUSTED {file.str.Flush[]};
PascalRESET: PUBLIC UNSAFE PROCEDURE [
file: PascalFilePtr, length: CARDINAL,
element: LONG POINTER -- TO ARRAY[0..length/2) OF UNSPECIFIED --] =
UNCHECKED BEGIN
file.str.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
file.str.SetIndex[0];
file.str.SetLength[0];
file.eof ← TRUE;
END;
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
file.baseFile.str.PutChar['\N -- CarriageReturn -- ];
END;
PascalReadInteger: PUBLIC PROCEDURE [file: PascalTextFilePtr]
RETURNS [PascalInteger] =
TRUSTED BEGIN
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;
PascalTextGET[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;
stream ← file.baseFile.str;
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;
END;
PascalReadReal: PUBLIC PROCEDURE [file: PascalTextFilePtr]
RETURNS [PascalReal] =
TRUSTED BEGIN
s: REF TEXTNEW[TEXT[50]];
s.length ← 0;
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;
PascalTextGET[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;
IF NOT fieldMinLength IN [0..1] THEN
file.baseFile.str.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;
c ← PascalTextElement[file];
PascalTextGET[file];
RETURN[c];
END;
PascalWriteChar: PUBLIC PROCEDURE [
file: PascalTextFilePtr, item: PascalChar,
fieldMinLength: PascalInteger ← -1] =
TRUSTED BEGIN
i: PascalInteger;
FOR i IN [1..fieldMinLength) DO
file.baseFile.str.PutChar[' ] ENDLOOP;
IF fieldMinLength#0 THEN
BEGIN
file.baseFile.str.PutChar[item];
file.element ← item;
END;
END;
PascalReadBoolean: PUBLIC PROCEDURE [file: PascalTextFilePtr]
RETURNS [PascalBoolean] =
TRUSTED BEGIN
b: PascalBoolean;
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 PascalTextGET[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;
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;
FOR i IN [arrayBound..fieldMinLength) DO
file.baseFile.str.PutChar[' ] ENDLOOP;
arrayLim ←
IF fieldMinLength < 0 THEN arrayBound ELSE MIN[fieldMinLength, arrayBound];
FOR i IN [1..arrayLim] DO
file.baseFile.str.PutChar[v[i]] ENDLOOP;
IF ((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
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;
len ← item.Length[];
FOR i IN [len..fieldMinLength) DO
file.baseFile.str.PutChar[' ] ENDLOOP;
stringLim ← IF fieldMinLength < 0 THEN len ELSE MIN[fieldMinLength, len];
FOR i IN [0..stringLim) DO
file.baseFile.str.PutChar[Rope.Fetch[item, i]] ENDLOOP;
IF ((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
PascalOpenTextFileWithStream: PUBLIC UNSAFE PROCEDURE [
file: PascalTextFilePtr,
stream: IO.STREAM] =
Allocates a new MesaFile and installs the specified stream
UNCHECKED BEGIN
openFiles ← z.NEW[MesaFile ← [str: stream, openFileLink: openFiles]];
file.baseFile ← LOOPHOLE[openFiles];
END;
PascalOpenTextFileTTYInput: PUBLIC UNSAFE PROCEDURE [
file: PascalTextFilePtr] =
Allocates a new MesaFile and sets up file to read from the terminal (no pre-read)
UNCHECKED BEGIN
openFiles ← z.NEW[MesaFile ← [str: ttyInputStream, eof: FALSE, openFileLink: openFiles]];
file.baseFile ← LOOPHOLE[openFiles];
file.element ← ' ;
file.eoln ← TRUE;
END;
PascalOpenTextFileTTYOutput: PUBLIC UNSAFE PROCEDURE [
file: PascalTextFilePtr] =
Allocates a new MesaFile and sets up file to output to the terminal
UNCHECKED BEGIN
openFiles ← z.NEW[MesaFile ← [str: ttyOutputStream, eof: TRUE, openFileLink: openFiles]];
file.baseFile ← LOOPHOLE[openFiles];
END;
PascalCloseTextFile: PUBLIC UNSAFE PROCEDURE [file: PascalTextFilePtr] =
Closes the file, and sets the PascalFile to NIL; the MesaFile must
continue to exist however, to avoid collecting non-garbage.
UNCHECKED BEGIN
IF file.baseFile # NIL THEN file.baseFile.str.Close[];
file.baseFile ← NIL;
END;
binary file operations
PascalOpenFileWithStream: PUBLIC UNSAFE PROCEDURE [
file: PascalFilePtr,
stream: IO.STREAM] =
Allocates a new MesaFile and installs the specified stream
UNCHECKED BEGIN
openFiles ← z.NEW[MesaFile ← [str: stream, openFileLink: openFiles]];
file^ ← LOOPHOLE[openFiles];
END;
PascalCloseFile: PUBLIC UNSAFE PROCEDURE [file: PascalFilePtr] =
Closes the file, and sets the PascalFile to NIL; the MesaFile must
continue to exist however, to avoid collecting non-garbage.
UNCHECKED BEGIN
IF file^ # NIL THEN file.str.Close[];
file^ ← NIL;
END;
END. -- PascalInlineFilesImpl