-- StreamIO.Mesa Edited by Sandman on August 1, 1980 10:20 AM -- Updated for Pilot Martin Newell 23-Jul-81 14:02:05 DIRECTORY DCSFileTypes USING [tLeaderPage], Directory USING [CreateFile, Lookup, UpdateDates, Error], File USING [Permissions, Capability, read, write, grow, shrink, delete], FileStream USING [Create, EndOf], IODefs USING [SP, CR, NumberFormat], TTY USING[Handle, SetEcho, GetChar, PutChar, GetEditedString, NewLine, Create, PutBackChar], Storage USING [Node, Free], Stream USING [Handle, GetChar, PutChar, GetWord, PutWord, Delete], StreamDefs USING [AccessOptions, StreamHandle, StreamObject, Read, Write, Append], String USING [SubString, StringToNumber, AppendChar, AppendNumber]; StreamIO: PROGRAM IMPORTS Directory, FileStream, TTY, Storage, Stream, String EXPORTS IODefs, StreamDefs = BEGIN OPEN Directory, File, FileStream, IODefs, Storage, StreamDefs, String; in, out: StreamHandle; inStreamRecord,outStreamRecord: StreamObject; NILTTY: TTY.Handle _ LOOPHOLE[NIL]; --EXPORTS to IODefs GetInputStream: PUBLIC PROCEDURE RETURNS [StreamHandle] = BEGIN RETURN[in] END; GetOutputStream: PUBLIC PROCEDURE RETURNS [StreamHandle] = BEGIN RETURN[out] END; SetInputStream: PUBLIC PROCEDURE [s: StreamHandle] = BEGIN in _ s; END; SetOutputStream: PUBLIC PROCEDURE [s: StreamHandle] = BEGIN out _ s; END; SetEcho: PUBLIC PROCEDURE [new: BOOLEAN] RETURNS [old: BOOLEAN] = BEGIN IF in.tty#NILTTY THEN RETURN[TTY.SetEcho[in.tty, new]] ELSE RETURN[FALSE]; END; -- Character operations ReadChar: PUBLIC PROCEDURE RETURNS [CHARACTER] = BEGIN RETURN[in.get[in]]; END; WriteChar: PUBLIC PROCEDURE [c: CHARACTER] = BEGIN out.put[out,c]; END; -- Reading Strings GetString: PROCEDURE [s: STRING, t: PROCEDURE [CHARACTER] RETURNS [BOOLEAN]] RETURNS[CHARACTER] = BEGIN IF in.tty#NILTTY THEN RETURN[TTY.GetEditedString[in.tty,s,t,TRUE]] ELSE { s.length _ 0; DO c: CHARACTER _ ReadChar[]; IF t[c] THEN RETURN[c]; AppendChar[s,c]; ENDLOOP; }; END; ReadString: PUBLIC PROCEDURE [s: STRING, t: PROCEDURE [CHARACTER] RETURNS [BOOLEAN]] = BEGIN [] _ GetString[s,t]; END; ReadID: PUBLIC PROCEDURE [s: STRING] = BEGIN ReadString[s, IsAtom]; END; ReadLine: PUBLIC PROCEDURE [s: STRING] = BEGIN ReadString[s, IsCR]; END; IsCR: PRIVATE PROCEDURE [c: CHARACTER] RETURNS [BOOLEAN] = BEGIN RETURN[c = CR] END; IsAtom: PRIVATE PROCEDURE [c: CHARACTER] RETURNS [BOOLEAN] = BEGIN RETURN[c=SP OR c=CR] END; Rubout: PUBLIC SIGNAL = CODE; LineOverflow: PUBLIC SIGNAL [s: STRING] RETURNS [ns: STRING] = CODE; ReadEditedString: PUBLIC PROCEDURE [ s: STRING, t: PROCEDURE [CHARACTER] RETURNS [BOOLEAN], newstring: BOOLEAN] RETURNS [CHARACTER] = BEGIN IF in.tty#NILTTY THEN RETURN[TTY.GetEditedString[in.tty,s,t,newstring]] ELSE RETURN[GetString[s,t]]; END; -- Writing Strings WriteString: PUBLIC PROCEDURE [s: STRING] = BEGIN i: CARDINAL; FOR i IN [0..s.length) DO out.put[out, s[i]]; ENDLOOP; END; WriteSubString: PUBLIC PROCEDURE [s: String.SubString] = BEGIN i: CARDINAL; FOR i IN [s.offset..s.offset + s.length) DO out.put[out, s.base[i]]; ENDLOOP; END; WriteLine: PUBLIC PROCEDURE [s: STRING] = BEGIN WriteString[s]; WriteChar[CR]; END; NewLine: PUBLIC PROCEDURE RETURNS [BOOLEAN] = BEGIN IF out.tty#NILTTY THEN RETURN[TTY.NewLine[out.tty]] ELSE RETURN[FALSE]; END; -- Numerical i/o ReadNumber: PUBLIC PROCEDURE [default: UNSPECIFIED, radix: CARDINAL] RETURNS [UNSPECIFIED] = BEGIN s: STRING _ [10]; IF radix = 10 AND LOOPHOLE[default, INTEGER] < 0 THEN BEGIN default _ -default; s[0] _ '-; s.length _ 1 END; AppendNumber[s, default, radix]; IF radix = 8 THEN AppendChar[s, 'B]; [] _ ReadEditedString[s, IsAtom, TRUE]; RETURN[StringToNumber[s, radix]]; END; ReadDecimal: PUBLIC PROCEDURE RETURNS [INTEGER] = BEGIN s: STRING _ [10]; [] _ ReadEditedString[s, IsAtom, TRUE]; RETURN[StringToNumber[s, 10]] END; ReadOctal: PUBLIC PROCEDURE RETURNS [UNSPECIFIED] = BEGIN s: STRING _ [10]; [] _ ReadEditedString[s, IsAtom, TRUE]; RETURN[StringToNumber[s, 8]] END; OutNumber: PUBLIC PROCEDURE [ stream: StreamHandle, val: INTEGER, format: NumberFormat] = BEGIN i: CARDINAL; neg: BOOLEAN _ FALSE; fill: CHARACTER _ (IF format.zerofill THEN '0 ELSE ' ); s: STRING _ [17]; IF val < 0 AND ~format.unsigned THEN BEGIN val _ -val; neg _ TRUE END; AppendNumber[s, val, format.base]; i _ s.length; IF neg THEN BEGIN i _ i + 1; IF format.zerofill THEN BEGIN stream.put[stream, '-]; neg _ FALSE END; END; THROUGH (i..format.columns] DO stream.put[stream, fill] ENDLOOP; IF neg THEN stream.put[stream, '-]; FOR i IN [0..s.length) DO stream.put[stream, s[i]] ENDLOOP; RETURN END; WriteNumber: PUBLIC PROCEDURE [v: UNSPECIFIED, f: NumberFormat] = BEGIN OutNumber[out, v, f]; RETURN END; WriteDecimal: PUBLIC PROCEDURE [n: INTEGER] = BEGIN WriteNumber[n, NumberFormat[10, FALSE, FALSE, 0]]; RETURN END; WriteOctal: PUBLIC PROCEDURE [n: UNSPECIFIED] = BEGIN WriteNumber[n, NumberFormat[8, FALSE, TRUE, 0]]; IF n ~IN [0..7] THEN WriteChar['B]; RETURN END; --TTY Stream Procedures TTYReset: PROCEDURE [s: StreamHandle] = BEGIN END; TTYGet: PROCEDURE [s: StreamHandle] RETURNS [CHARACTER] = BEGIN RETURN[TTY.GetChar[s.tty]]; END; TTYPutback: PROCEDURE [s: StreamHandle, c: CHARACTER] = BEGIN TTY.PutBackChar[s.tty, c]; END; TTYPut: PROCEDURE [s: StreamHandle, c: CHARACTER] = BEGIN TTY.PutChar[s.tty, c]; END; TTYEndof: PROCEDURE [s: StreamHandle] RETURNS [BOOLEAN] = BEGIN RETURN[FALSE]; END; TTYDestroy: PROCEDURE [s: StreamHandle] = BEGIN END; --EXPORTS to StreamDefs NewByteStream: PUBLIC PROCEDURE [name: STRING, access: AccessOptions] RETURNS [StreamHandle] = BEGIN s: StreamHandle _ Node[SIZE[StreamObject]]; permissions: File.Permissions _ SELECT access FROM Read => read, Write => write+grow+shrink+delete, Append => grow+shrink+delete, Read+Write => read+write+grow+shrink+delete, Write+Append => write+grow+shrink+delete, Read+Append => read+grow+shrink+delete, Read+Write+Append => read+write+grow+shrink+delete, ENDCASE => 0; s^ _ [ reset: FileReset, get: FileGetChar, putback: FilePutback, put: FilePutChar, endof: FileEndof, destroy: FileDestroy, link: NIL, file: NewStream[name, permissions], tty: NILTTY ]; RETURN[s]; END; NewWordStream: PUBLIC PROCEDURE [name: STRING, access: AccessOptions] RETURNS [StreamHandle] = BEGIN s: StreamHandle _ NewByteStream[name,access]; s.get _ FileGetWord; s.put _ FilePutWord; RETURN[s]; END; NewStream: PROC [name: LONG STRING, access: File.Permissions] RETURNS [Stream.Handle] = { cap: File.Capability; old: BOOLEAN _ FALSE; IF access ~= File.read THEN cap _ Directory.CreateFile[name, DCSFileTypes.tLeaderPage, 0 ! Directory.Error => { IF type = fileAlreadyExists THEN old _ TRUE ELSE ERROR; CONTINUE }] ELSE old _ TRUE; IF old THEN cap _ Directory.Lookup[fileName: name, permissions: access ! Directory.Error => ERROR]; cap _ Directory.UpdateDates[cap, access]; RETURN[FileStream.Create[cap]]; }; --File Stream Procedures FileReset: PROCEDURE [s: StreamHandle] = BEGIN END; FileGetChar: PROCEDURE [s: StreamHandle] RETURNS [CHARACTER] = BEGIN RETURN[Stream.GetChar[s.file]]; END; FileGetWord: PROCEDURE [s: StreamHandle] RETURNS [WORD] = BEGIN RETURN[Stream.GetWord[s.file]]; END; FilePutback: PROCEDURE [s: StreamHandle, c: CHARACTER] = BEGIN END; FilePutChar: PROCEDURE [s: StreamHandle, c: CHARACTER] = BEGIN Stream.PutChar[s.file, c]; END; FilePutWord: PROCEDURE [s: StreamHandle, w: WORD] = BEGIN Stream.PutWord[s.file, w]; END; FileEndof: PROCEDURE [s: StreamHandle] RETURNS [BOOLEAN] = BEGIN RETURN[FileStream.EndOf[s.file]]; END; FileDestroy: PROCEDURE [s: StreamHandle] = BEGIN Stream.Delete[s.file]; Free[s]; END; --START code-- inStreamRecord _ [ reset: TTYReset, get: TTYGet, putback: TTYPutback, put: TTYPut, endof: TTYEndof, destroy: TTYDestroy, link: NIL, file: NIL, tty: TTY.Create[""] ]; in _ @inStreamRecord; outStreamRecord _ [ reset: TTYReset, get: TTYGet, putback: TTYPutback, put: TTYPut, endof: TTYEndof, destroy: TTYDestroy, link: NIL, file: NIL, tty: in.tty ]; out _ @outStreamRecord; END.