DIRECTORY
Ascii USING [CR, TAB, SP],
Format USING [NumberFormat],
LongString USING [SubString],
OutputDefs USING [],
Segments USING [DefaultVersion, NewFile, Write],
Streams USING [CreateStream, Destroy, Handle, PutChar],
String USING [AppendNumber, AppendString, SubString, SubStringDescriptor],
Time USING [Append, Packed, Unpack];
Output:
PROGRAM
IMPORTS Segments, Streams, String, Time
EXPORTS OutputDefs =
BEGIN
outStream: PUBLIC Streams.Handle ← NIL;
GetOutputStream:
PUBLIC
PROC
RETURNS [Streams.Handle] =
{
RETURN[outStream]};
-- calling this start traps the module where
simply reading outStream does not
PutTab: PUBLIC PROC = {PutChar[Ascii.TAB]};
PutCR: PUBLIC PROC = {PutChar[Ascii.CR]};
PutChar: PUBLIC PROC [c: CHARACTER] = {Streams.PutChar[outStream, c]};
PutString:
PUBLIC
PROC [s:
STRING] =
{FOR i: CARDINAL IN [0..s.length) DO Streams.PutChar[outStream, s[i]]; ENDLOOP};
PutLongString:
PUBLIC
PROC [s:
LONG
STRING] =
{FOR i: CARDINAL IN [0..s.length) DO Streams.PutChar[outStream, s[i]]; ENDLOOP};
PutSubString:
PUBLIC
PROC [s: String.SubString] =
BEGIN
FOR i:
CARDINAL
IN [s.offset..s.offset + s.length)
DO
Streams.PutChar[outStream, s.base[i]];
ENDLOOP;
END;
PutLongSubString:
PUBLIC
PROC [s: LongString.SubString] =
BEGIN
FOR i:
CARDINAL
IN [s.offset..s.offset + s.length)
DO
Streams.PutChar[outStream, s.base[i]];
ENDLOOP;
END;
PutTime:
PUBLIC
PROC [t: Time.Packed] =
BEGIN
s: STRING ← [20];
Time.Append[s, Time.Unpack[t]];
IF s[0] = Ascii.
SP
THEN
BEGIN
desc: String.SubStringDescriptor ←
[base: s, offset: 1, length: (s.length - 1)];
PutSubString[@desc];
END
ELSE PutString[s];
END;
PutNumber:
PUBLIC
PROC [val:
CARDINAL, format: Format.NumberFormat] =
BEGIN
i: CARDINAL;
neg: BOOLEAN ← FALSE;
fill: CHARACTER ← (IF format.zerofill THEN '0 ELSE ' );
s: STRING ← [10];
IF
INTEGER[val] < 0
AND ~format.unsigned
THEN
{val ← -INTEGER[val]; neg ← TRUE};
String.AppendNumber[s, val, format.base];
i ← s.length;
IF neg
THEN
BEGIN
i ← i + 1;
IF format.zerofill THEN {Streams.PutChar[outStream, '-]; neg ← FALSE};
END;
THROUGH (i..format.columns] DO Streams.PutChar[outStream, fill] ENDLOOP;
IF neg THEN Streams.PutChar[outStream, '-];
PutString[s];
END;
PutDecimal:
PUBLIC
PROC [val:
CARDINAL] =
{PutNumber[val, [10, FALSE, FALSE, 1]]};
PutOctal:
PUBLIC
PROC [val:
UNSPECIFIED] =
BEGIN
PutNumber[val, [8, FALSE, TRUE, 1]];
IF val NOT IN [0..7] THEN Streams.PutChar[outStream, 'B];
END;
OpenOutput:
PUBLIC
PROC [root:
STRING, ext:
STRING] =
BEGIN
name: STRING ← [40];
String.AppendString[name, root];
FOR i:
CARDINAL
IN [0..name.length)
DO
IF name[i] = '. THEN {name.length ← i; EXIT};
ENDLOOP;
String.AppendString[name, ext];
outStream ← Streams.CreateStream[
file: Segments.NewFile[
name: name, access: Segments.Write, version: Segments.DefaultVersion],
access: Segments.Write];
END;
CloseOutput: PUBLIC PROC = {Streams.Destroy[outStream]; outStream ← NIL};
END.