-- file: FormatImpl.mesa; last edit:
-- Mark: Apr 11, 1980 12:37 PM
-- Evans: May 19, 1980 10:28 AM
-- JGS: August 12, 1980 12:09 PM
-- Karlton: July 24, 1980 8:41 AM
-- Smokey: Aug 4, 1980 2:56 PM
-- Forrest: October 25, 1980 8:32 PM
DIRECTORY
Format USING [
DateFormat, LongSubString, LongSubStringDescriptor, NumberFormat, StringProc],
String USING [AppendLongNumber, AppendNumber, AppendChar, SubString],
Time USING [Append, Packed, Unpack];
FormatImpl: PROGRAM IMPORTS String, Time EXPORTS Format =
BEGIN OPEN Format, String;
-- Public procedures
Char: PUBLIC PROCEDURE [c: CHARACTER, proc: StringProc] =
BEGIN
s: STRING ← [2];
s[0] ← c; s.length ← 1;
proc[s]
END;
Date: PUBLIC PROCEDURE [
pt: Time.Packed, format: DateFormat ← noSeconds, proc: StringProc] =
BEGIN
s: STRING ← [22];
Time.Append[s, Time.Unpack[pt], TRUE];
s.length ← s.length-(SELECT format FROM
dateOnly => 13, noSeconds => 7, dateTime => 4, ENDCASE => 0);
proc[s]
END;
LongNumber: PUBLIC PROCEDURE [
n: LONG UNSPECIFIED, format: NumberFormat, proc: StringProc] =
BEGIN
s: STRING ← [34];
neg: BOOLEAN;
IF LOOPHOLE[n, LONG INTEGER] < 0 AND ~format.unsigned THEN
{n ← -LOOPHOLE[n, LONG INTEGER]; neg ← TRUE}
ELSE neg ← FALSE;
AppendLongNumber[s, n, format.base];
FormatNumber[s: s, format: format, neg: neg, proc: proc];
END;
LongOctal: PUBLIC PROCEDURE [n: LONG CARDINAL, proc: StringProc] =
BEGIN
s: STRING ← [12];
AppendLongNumber[s, n, 8];
IF n > 7 THEN AppendChar[s, 'B];
proc[s];
END;
LongString: PUBLIC PROCEDURE [s: LONG STRING, proc: StringProc] =
BEGIN
IF s#NIL THEN
BEGIN
lss: LongSubStringDescriptor ← [base: s, offset: 0, length: s.length];
LongSubStringItem[@lss, proc];
END;
END;
LongSubStringItem: PUBLIC PROCEDURE [ss: LongSubString, proc: StringProc] =
BEGIN -- Repeatedly calls proc with strings filled from ss
s: STRING ← [100];
sPos, ssPos: CARDINAL ← 0;
IF ss = NIL OR ss.base = NIL OR ss.base.length = 0 THEN RETURN[];
s.length ← 0;
FOR ssPos IN [ss.offset..MIN[ss.base.length, ss.offset+ss.length]) DO
IF sPos >= s.maxlength THEN {IF s.length # 0 THEN proc[s]; sPos ← 0; s.length ← 0};
s[sPos] ← ss.base[ssPos];
s.length ← s.length+1;
sPos ← sPos+1;
REPEAT
FINISHED => IF s.length # 0 THEN proc[s];
ENDLOOP;
RETURN[];
END;
Number: PUBLIC PROCEDURE [n: UNSPECIFIED, format: NumberFormat, proc: StringProc] =
BEGIN
s: STRING ← [18];
neg: BOOLEAN;
IF INTEGER[n] < 0 AND ~format.unsigned THEN {n ← -INTEGER[n]; neg ← TRUE}
ELSE neg ← FALSE;
AppendNumber[s, n, format.base];
FormatNumber[s: s, format: format, neg: neg, proc: proc];
END;
Octal: PUBLIC PROCEDURE [n: CARDINAL, proc: StringProc] =
BEGIN
s: STRING ← [10];
AppendNumber[s, n, 8];
IF n > 7 THEN AppendChar[s, 'B];
proc[s];
END;
SubString: PUBLIC PROCEDURE [ss: String.SubString, proc: StringProc] =
BEGIN
IF ss#NIL THEN
BEGIN
lss: LongSubStringDescriptor ← [base: ss.base, offset: ss.offset, length: ss.length];
LongSubStringItem[@lss, proc];
END;
END;
-- Private procedures
FormatNumber: PROCEDURE [
s: STRING, format: NumberFormat, neg: BOOLEAN, proc: StringProc] =
BEGIN
l: CARDINAL;
fill: STRING ←
(IF format.zerofill THEN "00000000"L ELSE " "L );
l ← s.length + (IF neg THEN 1 ELSE 0);
IF l < format.columns THEN
BEGIN
fillChars: CARDINAL ← format.columns - l;
IF neg AND format.zerofill THEN Char['-, proc];
THROUGH [0..fillChars/8) DO proc[fill]; ENDLOOP;
IF (fill.length ← fillChars MOD 8) # 0 THEN proc[fill];
IF neg AND ~format.zerofill THEN Char['-, proc];
END
ELSE
IF neg THEN Char['-, proc];
proc[s];
END;
-- Mainline Code
END.