file:  PascalInlineFiles.mesa
last modified by Ramshaw, December 25, 1982 11:00 am
written by McCreight, November 17, 1980  3:13 PM
a thin layer of Pascal files on top of IO.STREAM
just like the wizardFiles, except that common procs are herein INLINE
DIRECTORY
Basics USING [LowByte], 
IO,
PascalBasic,
PrincOpsUtils USING [LongCopy];
 
PascalInlineFiles: CEDAR DEFINITIONS IMPORTS Basics, IO, PrincOpsUtils =
BEGIN  OPEN PascalBasic;
T Y P E S
PascalFile: TYPE = LONG POINTER TO MesaFile ← NIL;
PascalFilePtr: TYPE = LONG POINTER TO PascalFile;  --  for passing files as VAR parameters
MesaFile: 
TYPE = 
RECORD [
str: IO.STREAM ← NIL,
eof: BOOLEAN ← FALSE,
openFileLink: MesaFilePtr ← NIL];
MesaFilePtr: TYPE = REF MesaFile;
PascalTextFile: 
TYPE = 
RECORD [
baseFile: PascalFile,  
eoln: BOOLEAN ← TRUE, -- TRUE if element is a blank representing CR
element: PascalChar ← '  -- last character read
];
PascalTextFilePtr: TYPE = LONG POINTER TO PascalTextFile;  --  for passing by VAR
Text: TYPE = PascalTextFile;
P R O C E D U R E S   Called by PasMesa
 
Text File Operations:
PascalTextBREAK: PROCEDURE [file: PascalTextFilePtr];
PascalTextGET: 
PROCEDURE [file: PascalTextFilePtr] = 
TRUSTED 
INLINE
BEGIN
file.element ← file.baseFile.str.GetChar[ !
IO.EndOfStream => GOTO EOF];
SELECT file.element 
FROM
'\N 
--CarriageReturn-- => {
file.eoln ← TRUE; file.element ← ' };
ENDCASE => file.eoln ← FALSE;
 
EXITS
EOF => {
file.baseFile.eof ← file.eoln ← TRUE;
file.element ← ' };
 
 
END;
 
PascalTextElement: 
PROCEDURE [file: PascalTextFilePtr]
RETURNS [PascalChar] = TRUSTED INLINE
BEGIN
RETURN[file.element];
END;
 
PascalTextPUT: 
PROCEDURE [file: PascalTextFilePtr] = 
TRUSTED 
INLINE
BEGIN
file.baseFile.str.PutChar[file.element];
END;
 
PascalTextRESET: PROCEDURE [file: PascalTextFilePtr];
PascalTextREWRITE: PROCEDURE [file: PascalTextFilePtr];
PascalTextPAGE: 
PROCEDURE [file: PascalTextFilePtr] = 
INLINE
BEGIN
PascalWriteLn[file: file];
PascalWriteChar[file: file, item: '\F  --form feed--];
PascalWriteLn[file: file]
END;
 
PascalTextEOF: 
PROCEDURE [file: PascalTextFilePtr] 
RETURNS [
BOOLEAN] = 
TRUSTED 
INLINE
BEGIN
RETURN[file.baseFile.eof];
END;
 
PascalTextEOLN: 
PROCEDURE [file: PascalTextFilePtr]
RETURNS [BOOLEAN] = TRUSTED INLINE
BEGIN
RETURN[file.eoln];
END;
 
 
Binary File Operations:
The "length" argument is in units of bytes rather than words, but the only odd
value that will ever arise is 1.  The Pascal program generates these arguments
by utilizing a little-known feature of the SIZE operator in Mesa:  if you say
SIZE[T, 2], you get back the size in words of a packed array of 2 T's.
PascalBREAK: 
PROCEDURE [
file: PascalFilePtr, length: CARDINAL,
element: LONG POINTER];
 
PascalGET: 
UNSAFE 
PROCEDURE [
file: PascalFilePtr, length: CARDINAL,
element: LONG POINTER -- TO ARRAY[0..length/2) OF UNSPECIFIED --] = UNCHECKED INLINE
BEGIN
IF length = 1 
THEN 
element^ ← file.str.GetChar[ ! IO.EndOfStream => {file.eof ← TRUE; CONTINUE}]
 
ELSE 
IF length # file.str.UnsafeGetBlock[[base: element, startIndex: 0,
count: length]] THEN file.eof ← TRUE;
 
END;
 
PascalPUT: 
PROCEDURE [
file: PascalFilePtr, length: CARDINAL,
element: LONG POINTER -- TO ARRAY[0..length/2) OF UNSPECIFIED --] = TRUSTED INLINE
BEGIN
IF length = 1 
THEN
file.str.PutChar[LOOPHOLE[Basics.LowByte[LOOPHOLE[element^]]]]
 
ELSE file.str.UnsafePutBlock[[base: element, startIndex: 0, count: length]];
END;
 
PascalRESET: 
UNSAFE 
PROCEDURE [
file: PascalFilePtr, length: CARDINAL,
element: LONG POINTER -- TO ARRAY[0..length/2) OF UNSPECIFIED --];
 
PascalREWRITE: 
PROCEDURE [
file: PascalFilePtr, length: CARDINAL ← 0,
element: LONG POINTER -- TO ARRAY[0..length/2) OF UNSPECIFIED -- ← NIL];
 
 
The latter two arguments don't mean anything, and are just included since PasMesa
prefers to generate them.
PascalRead, 
PascalReadLong: 
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 INLINE
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: 
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 INLINE
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: 
PROCEDURE [file: PascalFilePtr] 
RETURNS [
BOOLEAN] = 
TRUSTED 
INLINE
{RETURN[file.eof]};
 
 
formatted IO for text files
PascalReadLn, 
PascalWriteLn: 
PROCEDURE [file: PascalTextFilePtr]; 
reads up to or writes a CR
PascalReadInteger: PROCEDURE [file: PascalTextFilePtr] RETURNS [PascalInteger];
PascalWriteInteger: 
PROCEDURE [
file: PascalTextFilePtr, item: PascalInteger,
fieldMinLength: PascalInteger ← -1];
 
PascalReadReal: PROCEDURE [file: PascalTextFilePtr] RETURNS [PascalReal];
PascalWriteReal: 
PROCEDURE [
file: PascalTextFilePtr, item: PascalReal,
fieldMinLength, fracLength: PascalInteger ← -1];
 
PascalReadChar: PROCEDURE [file: PascalTextFilePtr] RETURNS [PascalChar];
PascalWriteChar: 
PROCEDURE [
file: PascalTextFilePtr, item: PascalChar, fieldMinLength: PascalInteger ← -1];
 
PascalReadBoolean: PROCEDURE [file: PascalTextFilePtr] RETURNS [PascalBoolean];
PascalWriteBoolean: 
PROCEDURE [
file: PascalTextFilePtr, item: PascalBoolean,
fieldMinLength: PascalInteger ← -1];
 
PascalReadArrayOfChar, 
PascalReadLongArrayOfChar: 
UNSAFE 
PROCEDURE [
file: PascalTextFilePtr,
item: CharArrayPtr,
arrayBound: PascalInteger];
PascalWriteArrayOfChar, 
PascalWriteLongArrayOfChar: 
PROCEDURE [
file: PascalTextFilePtr,
item: CharArrayPtr,
arrayBound: PascalInteger, fieldMinLength: PascalInteger ← -1];
 
At this point, McCreight included the following ReadString routines, but I don't see
how they could ever arise, nor do I see how to make them safe.
PascalReadString, PascalReadLongString:
PROCEDURE [file: PascalTextFilePtr, item: LONG POINTER TO ??ROPE??];
PascalWriteString, 
PascalWriteLongString: 
PROCEDURE [
file: PascalTextFilePtr, item: ROPE, fieldMinLength: PascalInteger ← -1];
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: 
UNSAFE 
PROCEDURE [
file: PascalTextFilePtr,
stream: IO.STREAM];  
Allocates a new MesaFile and installs the specified stream
 
PascalOpenTextFileTTYInput: 
UNSAFE 
PROCEDURE [
file: PascalTextFilePtr];  
Allocates a new MesaFile and sets up file to read from the terminal (no pre-read)
 
PascalOpenTextFileTTYOutput: 
UNSAFE 
PROCEDURE [
file: PascalTextFilePtr];  
Allocates a new MesaFile and sets up file to output to the terminal
 
PascalCloseTextFile: 
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. 
 
 
binary file operations
PascalOpenFileWithStream: 
UNSAFE 
PROCEDURE [
file: PascalFilePtr,
stream: IO.STREAM];  
Allocates a new MesaFile and installs the specified stream
 
PascalCloseFile: 
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. 
 
END. -- PascalInlineFiles