-- 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.