DIRECTORY Basics USING [LowByte], Convert USING [RealFromRope, RopeFromReal], IO, PascalBasic, PascalWizardFiles, PrincOpsUtils USING [LongCopy], Real USING [DefaultSinglePrecision], RefText USING [TrustTextAsRope], Rope USING [Cat, Fetch, FromChar, Length]; PascalWizardFilesImpl: CEDAR PROGRAM IMPORTS Basics, Convert, IO, PascalBasic, PrincOpsUtils, RefText, Rope EXPORTS PascalWizardFiles = BEGIN OPEN PascalBasic, PascalWizardFiles; openFiles: MesaFilePtr _ NIL; PascalTextBREAK: PUBLIC PROCEDURE [file: PascalTextFilePtr] = TRUSTED BEGIN file.baseFile.str.Flush[]; END; PascalTextGET: PUBLIC PROCEDURE [file: PascalTextFilePtr] = TRUSTED 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: PUBLIC PROCEDURE [file: PascalTextFilePtr] RETURNS [PascalChar] = TRUSTED BEGIN RETURN[file.element]; END; PascalTextPUT: PUBLIC PROCEDURE [file: PascalTextFilePtr] = TRUSTED BEGIN file.baseFile.str.PutChar[file.element]; 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; 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 RETURN[file.baseFile.eof]; END; PascalTextEOLN: PUBLIC PROCEDURE [file: PascalTextFilePtr] RETURNS [BOOLEAN] = TRUSTED BEGIN RETURN[file.eoln]; END; PascalBREAK: PUBLIC PROCEDURE [ file: PascalFilePtr, length: CARDINAL, element: LONG POINTER] = TRUSTED {file.str.Flush[]}; PascalGET: PUBLIC UNSAFE PROCEDURE [ file: PascalFilePtr, length: CARDINAL, element: LONG POINTER -- TO ARRAY[0..length) OF UNSPECIFIED --] = UNCHECKED 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: PUBLIC PROCEDURE [ file: PascalFilePtr, length: CARDINAL, element: LONG POINTER -- TO ARRAY[0..length) OF UNSPECIFIED --] = TRUSTED 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: 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; 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[file.eof]}; 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; PascalOpenTextFileWithStream: PUBLIC UNSAFE PROCEDURE [ file: PascalTextFilePtr, stream: IO.STREAM] = UNCHECKED BEGIN openFiles _ z.NEW[MesaFile _ [str: stream, openFileLink: openFiles]]; file.baseFile _ LOOPHOLE[openFiles]; END; PascalOpenTextFileTTYInput: PUBLIC UNSAFE PROCEDURE [ file: PascalTextFilePtr] = 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] = UNCHECKED BEGIN openFiles _ z.NEW[MesaFile _ [str: ttyOutputStream, eof: TRUE, openFileLink: openFiles]]; file.baseFile _ LOOPHOLE[openFiles]; END; PascalCloseTextFile: PUBLIC UNSAFE PROCEDURE [file: PascalTextFilePtr] = UNCHECKED BEGIN IF file.baseFile # NIL THEN file.baseFile.str.Close[]; file.baseFile _ NIL; END; PascalOpenFileWithStream: PUBLIC UNSAFE PROCEDURE [ file: PascalFilePtr, stream: IO.STREAM] = UNCHECKED BEGIN openFiles _ z.NEW[MesaFile _ [str: stream, openFileLink: openFiles]]; file^ _ LOOPHOLE[openFiles]; END; PascalCloseFile: PUBLIC UNSAFE PROCEDURE [file: PascalFilePtr] = UNCHECKED BEGIN IF file^ # NIL THEN file.str.Close[]; file^ _ NIL; END; END. -- PascalWizardFilesImpl 6file: PascalWizardFilesImpl.mesa last modified by Ramshaw, October 10, 1983 5:44 pm written by McCreight, December 19, 1980 10:44 AM a thin layer of Pascal files on top of IO.STREAM V A R I A B L E S (all private) P R O C E D U R E S Text File Operations: Binary File Operations: formatted input and output: 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 Allocates a new MesaFile and installs the specified stream Allocates a new MesaFile and sets up file to read from the terminal (no pre-read) Allocates a new MesaFile and sets up file to output to the terminal Closes the file, and sets the PascalFile to NIL; the MesaFile must continue to exist however, to avoid collecting non-garbage. binary file operations Allocates a new MesaFile and installs the specified stream Closes the file, and sets the PascalFile to NIL; the MesaFile must continue to exist however, to avoid collecting non-garbage. Ê˘Jšœ!™!Jšœ2™2Jšœ1™1J˜Jšœ0™0J˜šÏk ˜ Jšœœ ˜Jšœœ˜+Jšœ˜J˜ J˜Jšœœ ˜Jšœœ˜$Jšœœ˜ Jšœœ ˜*J˜—šœœ˜$Jšœœ+˜FJšœ˜J˜Jšœœ ˜*J˜J˜Jšœ ™ J˜Jšœœ˜J˜J˜Jšœ™J˜—Jšœ™˜šÏnœœ œ˜>Jšœ˜ J˜Jšœ˜J˜—šž œœ œ˜;Jšœ˜ ˜+Jšœœœ˜—šœ˜šœÏcœ˜Jšœ œ˜%—Jšœœ˜—š˜šœ˜Jšœ œ˜%J˜——Jšœ˜J˜—šžœœ œ˜=Jšœ˜Jšœ˜ Jšœ˜Jšœ˜J˜—šž œœ œ˜;Jšœ˜ J˜(Jšœ˜J˜—šžœœ œ˜=Jšœ˜ ˜Jšœ œ"œœ˜A—Jšœœ˜J˜Jšœ˜J˜—šžœœ œ˜?Jšœ˜ ˜Jšœ œ"œœ˜A—˜Jšœ œ"œœ˜A—Jšœœ˜Jšœ˜J˜—šžœœ œ˜=Jš˜J˜Jšœ'Ÿ œ˜6J˜Jšœ˜J˜—šž œœ œ˜:Jšœœ˜Jšœ˜ Jšœ˜Jšœ˜J˜—šžœœ œ˜:Jšœœ˜Jšœ˜ Jšœ ˜Jšœ˜J˜——Jšœ™˜šž œœ œ˜Jšœœ˜&Jšœ œœœ˜4J˜—šž œœœ œ˜$Jšœœ˜&Jšœ œœŸ(œ˜AJš œ˜šœ œ˜Jšœœœœ˜M—šœœ@˜GJšœœ œ˜%—Jšœ˜J˜—šž œœ œ˜Jšœœ˜&Jšœ œœŸ(œ˜AJšœ˜ šœ ˜Jšœœœ ˜>—šœ7˜;J˜—Jšœ˜J˜—šž œœœ œ˜&Jšœœ˜&Jšœ œœŸ*œ˜CJš œ˜J˜Jšœ œ˜J˜!Jšœ˜J˜—šž œœ œ˜!Jšœœ˜*Jš œ œœŸ*œœ˜IJšœ˜ J˜J˜Jšœ œ˜Jšœ˜J˜—š ž œžœœœ œ˜5Jšœœ˜&Jšœ œœŸ*œ˜AJšœœœŸ*œ˜@Jš œ˜šœ œ˜#JšœC˜G—J˜8Jšœ˜J˜—š ž œžœœœ œ˜7Jšœœ˜&Jš œ œœœŸœ œ˜AJš œœœœŸœ œ˜@Jš œ˜šœ œ˜#JšœC˜G—J˜8Jšœ˜J˜—š ž œœ œœœœ˜OJšœ ˜J˜——Jšœ™˜šž œœ œ˜:Jšœ˜ Jšœœœœ˜>J˜Jšœ˜J˜—šž œœ œ˜;Jšœ˜ JšœŸœ˜5Jšœ˜J˜—šžœœ œ˜=Jšœ˜Jšœ˜ J˜šœ˜Jšœœ˜:Jšœœ˜9Jšœœ˜'—Jšœ˜J˜—šž œ œ˜1Jšœ˜ šœœ˜š˜šœœ˜Jš œœœ œ œ˜;Jšœœœœ˜0———Jšœ˜J˜—šž œ œ˜0Jšœ!˜(Jšœ˜ J˜J˜š œœœœœ ˜@Jšœ˜—šœœ ˜!J˜J˜J˜Jšœ˜—Jšœ˜J˜—šžœœ œ˜&J˜-J˜%Jšœ˜ Jšœ œœ˜Jšœœ œ˜ J˜J˜Jšœœœ˜J˜Jšœœœœ˜8šœœ˜J˜3—Jšœ œ˜-š˜šœ ˜Jšœœ˜J˜J˜Jšœ˜——Jšœœœœ˜EJšœ œ˜$šœ œœ˜#Jšœœ˜'—Jšœ˜J˜—šžœœ œ˜:Jšœ˜Jšœ˜ Jš œœœœœ˜J˜ J˜š˜šœœ˜Jšœ œœ œ˜:Jšœœ˜—J˜J˜J˜Jšœ˜—Jšœ3˜9Jšœ˜J˜—šžœœ œ˜#J˜*J˜1Jšœ˜ Jšœœ˜&šœœœ˜$J˜—˜-J˜ J˜ Jšœœœ#˜Z—Jšœ˜J˜—šžœœ œ˜:Jšœ˜Jšœ˜ ˜J˜—J˜Jšœ˜ Jšœ˜J˜—šžœœ œ˜#J˜*J˜%Jšœ˜ J˜šœœ˜Jšœœ˜&—šœ˜Jš˜J˜ J˜Jšœ˜—Jšœ˜J˜—šžœœ œ˜=Jšœ˜Jšœ˜ J˜J˜šœ˜Jšœœ˜Jšœœ˜Jšœœœ˜1—š˜šœœ˜Jšœ œ œ˜!Jšœœœœ˜1——Jšœ˜ Jšœ˜J˜—šžœœ œ˜&J˜-J˜%Jšœ˜ šœœœ˜$J˜—Jšœœœœ˜JJšœ˜J˜—˜1Jšœœ œ˜J˜J˜0Jš œ˜J˜J˜šœœ˜Jšœ5œ˜=—Jšœ˜J˜—˜3Jšœ œ˜J˜J˜J˜@Jšœ˜ Jšœœ˜)J˜šœœ˜(Jšœœ˜&—˜ Jšœœ œœ˜K—šœœ˜Jšœ œ˜(—šœœœ˜CJšœœœ œ˜8—Jšœ˜J˜—š ž œœ œœœ˜KJšœ˜ J˜š œœœœ˜;J˜-J˜Jšœ˜—Jšœ˜J˜—šœžœœ œ˜