-- StreamIO.Mesa Edited by Sandman on August 1, 1980 10:20 AM -- Copyright Xerox Corporation 1979, 1980 DIRECTORY IODefs USING [ ControlA, ControlH, ControlQ, ControlR, ControlV, ControlW, ControlX, CR, DEL, ESC, NumberFormat, SP], StreamDefs USING [GetDefaultDisplayStream, GetDefaultKey, StreamHandle], StringDefs USING [AppendChar, AppendNumber, StringToNumber, SubString]; StreamIO: PROGRAM IMPORTS StreamDefs, StringDefs EXPORTS IODefs SHARES IODefs, StreamDefs =PUBLIC BEGIN OPEN StreamDefs, IODefs, StringDefs; in, out: StreamHandle; beginLine, echo: PRIVATE BOOLEAN _ TRUE; GetInputStream: PROCEDURE RETURNS [StreamHandle] = BEGIN RETURN[in] END; GetOutputStream: PROCEDURE RETURNS [StreamHandle] = BEGIN RETURN[out] END; SetInputStream: PROCEDURE [s: StreamHandle] = BEGIN in _ s END; SetOutputStream: PROCEDURE [s: StreamHandle] = BEGIN out _ s; beginLine _ TRUE; END; SetEcho: PROCEDURE [new: BOOLEAN] RETURNS [old: BOOLEAN] = BEGIN old _ echo; echo _ new END; -- Character operations ReadChar: PROCEDURE RETURNS [CHARACTER] = BEGIN RETURN[in.get[in]]; END; WriteChar: PROCEDURE [c: CHARACTER] = BEGIN out.put[out, c]; beginLine _ c = CR; END; -- Reading Strings ReadString: PROCEDURE [s: STRING, t: PROCEDURE [CHARACTER] RETURNS [BOOLEAN]] = BEGIN WriteChar[ReadEditedString[s, t, TRUE]]; END; ReadID: PROCEDURE [s: STRING] = BEGIN [] _ ReadEditedString[s, IsAtom, TRUE]; END; ReadLine: PROCEDURE [s: STRING] = BEGIN [] _ ReadEditedString[s, IsCR, TRUE]; IF echo THEN WriteChar[CR]; END; IsCR: PRIVATE PROCEDURE [c: CHARACTER] RETURNS [BOOLEAN] = BEGIN RETURN[c = CR] END; IsAtom: PRIVATE PROCEDURE [c: CHARACTER] RETURNS [BOOLEAN] = BEGIN RETURN[IF c = SP OR c = CR THEN TRUE ELSE FALSE] END; Rubout: SIGNAL = CODE; LineOverflow: SIGNAL [s: STRING] RETURNS [ns: STRING] = CODE; ReadEditedString: PROCEDURE [ s: STRING, t: PROCEDURE [CHARACTER] RETURNS [BOOLEAN], newstring: BOOLEAN] RETURNS [CHARACTER] = BEGIN c: CHARACTER; i: CARDINAL; state: {ti, v, li}; c _ in.get[in]; IF newstring THEN IF c = ESC THEN BEGIN WriteString[s]; c _ in.get[in]; END ELSE s.length _ 0; UNTIL t[c] DO SELECT c FROM DEL => SIGNAL Rubout; ControlA, ControlH => BEGIN IF s.length > 0 THEN BEGIN IF echo THEN WITH out SELECT FROM Display => clearChar[out, s[s.length - 1]]; ENDCASE => out.put[out, c]; s.length _ s.length - 1; END; END; ControlW, ControlQ => BEGIN -- text to be backed up is of the form -- ...
  • ; the and are to be removed. state _ ti; FOR i DECREASING IN [0..s.length) DO SELECT s[i] FROM IN ['A..'Z], IN ['a..'z], IN ['0..'9] => IF state = ti THEN state _ v; ENDCASE => IF state = v THEN state _ li; IF state = li THEN GO TO Done; IF echo THEN WITH out SELECT FROM Display => clearChar[out, s[i]]; ENDCASE => out.put[out, ControlA]; REPEAT Done => s.length _ i + 1; FINISHED => s.length _ 0; ENDLOOP; END; ControlR => IF echo THEN BEGIN WriteChar[CR]; WriteString[s]; END; ControlX => BEGIN IF echo THEN WITH out SELECT FROM Display => clearCurrentLine[out]; ENDCASE => out.put[out, c]; s.length _ 0; END; ControlV => BEGIN WHILE s.length >= s.maxlength DO s _ SIGNAL LineOverflow[s]; ENDLOOP; s[s.length] _ c _ in.get[in]; s.length _ s.length + 1; IF echo THEN WriteChar[c]; END; ENDCASE => BEGIN WHILE s.length >= s.maxlength DO s _ SIGNAL LineOverflow[s]; ENDLOOP; s[s.length] _ c; s.length _ s.length + 1; IF echo THEN WriteChar[c]; END; c _ in.get[in]; ENDLOOP; RETURN[c]; END; -- Writing Strings WriteString: PROCEDURE [s: STRING] = BEGIN i: CARDINAL; FOR i IN [0..s.length) DO out.put[out, s[i]]; ENDLOOP; IF s.length # 0 THEN beginLine _ s[s.length - 1] = CR; END; WriteSubString: PROCEDURE [s: StringDefs.SubString] = BEGIN i: CARDINAL; FOR i IN [s.offset..s.offset + s.length) DO out.put[out, s.base[i]]; ENDLOOP; IF s.length # 0 THEN beginLine _ s.base[s.offset + s.length - 1] = CR; END; WriteLine: PROCEDURE [s: STRING] = BEGIN WriteString[s]; WriteChar[CR]; END; NewLine: PROCEDURE RETURNS [BOOLEAN] = BEGIN RETURN[beginLine] END; -- Numerical i/o ReadNumber: 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: PROCEDURE RETURNS [INTEGER] = BEGIN s: STRING _ [10]; [] _ ReadEditedString[s, IsAtom, TRUE]; RETURN[StringToNumber[s, 10]] END; ReadOctal: PROCEDURE RETURNS [UNSPECIFIED] = BEGIN s: STRING _ [10]; [] _ ReadEditedString[s, IsAtom, TRUE]; RETURN[StringToNumber[s, 8]] END; OutNumber: 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: PROCEDURE [v: UNSPECIFIED, f: NumberFormat] = BEGIN OutNumber[out, v, f]; beginLine _ FALSE; RETURN END; WriteDecimal: PROCEDURE [n: INTEGER] = BEGIN WriteNumber[n, NumberFormat[10, FALSE, FALSE, 0]]; RETURN END; WriteOctal: PROCEDURE [n: UNSPECIFIED] = BEGIN WriteNumber[n, NumberFormat[8, FALSE, TRUE, 0]]; IF n ~IN [0..7] THEN WriteChar['B]; RETURN END; in _ StreamDefs.GetDefaultKey[ ! ANY => CONTINUE]; out _ StreamDefs.GetDefaultDisplayStream[ ! ANY => CONTINUE]; END.