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
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;
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: BOOLEAN ← FALSE;
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 TEXT ← NEW[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).
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;
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