<> <> DIRECTORY Convert USING [RopeFromCard], ConvertUnsafe USING [SubString], RESOut USING [Handle, MakeRoom, NumberFormat, PChar], Rope USING [Fetch, Length, ROPE]; RESIOPack: CEDAR PROGRAM IMPORTS Convert, RESOut, Rope EXPORTS RESOut = BEGIN OPEN RESOut; ROPE: TYPE = Rope.ROPE; Handle: TYPE = RESOut.Handle; Log10: PUBLIC PROCEDURE [num: CARDINAL] RETURNS [CARDINAL] = BEGIN IF num < 1000 THEN IF num < 10 THEN RETURN[1] ELSE IF num >= 100 THEN RETURN[3] ELSE RETURN[2] ELSE IF num >= 10000 THEN RETURN[5] ELSE RETURN[4]; END; LongLog10: PUBLIC PROCEDURE [num: LONG CARDINAL] RETURNS [CARDINAL] = BEGIN power: ARRAY [1..10] OF LONG CARDINAL = [0, 1D1, 1D2, 1D3, 1D4, 1D5, 1D6, 1D7, 1D8, 1D9]; u, l, i: CARDINAL; l _ 1; u _ 11; UNTIL u < l DO i _ (l+u)/2; SELECT power[i] FROM = num => RETURN [i]; > num => u _ i-1; ENDCASE => l _ i+1; ENDLOOP; RETURN [u]; -- see Knuth, 6.2.1 Exercise 1. END; Log8: PUBLIC PROCEDURE [num: CARDINAL] RETURNS [CARDINAL] = BEGIN IF num < 1000B THEN IF num < 10B THEN RETURN[1] ELSE IF num >= 100B THEN RETURN[3] ELSE RETURN[2] ELSE IF num >= 100000B THEN RETURN[6] ELSE IF num >= 10000B THEN RETURN[5] ELSE RETURN[4]; END; LongLog8: PUBLIC PROCEDURE [num: LONG CARDINAL] RETURNS [CARDINAL] = BEGIN power: ARRAY [1..11] OF LONG CARDINAL = [0, 1B1, 1B2, 1B3, 1B4, 1B5, 1B6, 1B7, 1B8, 1B9, 1B10]; u, l, i: CARDINAL; l _ 1; u _ 11; UNTIL u < l DO i _ (l+u)/2; SELECT power[i] FROM = num => RETURN [i]; > num => u _ i-1; ENDCASE => l _ i+1; ENDLOOP; RETURN [u]; END; PNextUnsigned: PUBLIC PROCEDURE [ h: Handle, s: ROPE, num: CARDINAL, indent: CARDINAL _ 2] = BEGIN extra: CARDINAL _ Log10[num]; PNext[h, s, extra+2, indent]; PRope[h, ": "]; PUnsigned[h, num]; END; PNextNull: PUBLIC PROCEDURE [ h: Handle, s: ROPE, val, null: UNSPECIFIED, indent: CARDINAL _ 2] = BEGIN extra: CARDINAL _ IF val = null THEN 4 ELSE Log10[val]; PNext[h, s, extra+2, indent]; PRope[h, ": "]; PNull[h, val, null]; END; PNextOctal: PUBLIC PROCEDURE [ h: Handle, s: ROPE, num: CARDINAL, indent: CARDINAL _ 2] = BEGIN extra: CARDINAL _ Log8[num]; IF num > 7 THEN extra _ extra+1; PNext[h, s, extra+2, indent]; PRope[h, ": "]; POctal[h, num]; END; PNextLong: PUBLIC PROCEDURE [ h: Handle, s: ROPE, num: LONG INTEGER, indent: CARDINAL _ 2] = BEGIN neg: BOOLEAN _ num < 0; extra: CARDINAL; extra _ IF neg THEN LongLog10[-num]+1 ELSE LongLog10[num]; PNext[h, s, extra+2, indent]; PRope[h, ": "]; PLongNumber[h, num, [base: 10, unsigned: FALSE, zerofill: FALSE, columns: 0]]; END; PDecimal: PUBLIC PROCEDURE [h: Handle, i: INTEGER] = BEGIN BEGIN PNumber[h, i, [10,FALSE,FALSE,1]] END; END; PNull: PUBLIC PROCEDURE [h: Handle, val, null: UNSPECIFIED] = BEGIN IF val = null THEN PRope[h, "Null"] ELSE PUnsigned[h, val]; END; PNext: PUBLIC PROCEDURE [h: Handle, s: ROPE, extra: CARDINAL _ 0, indent: CARDINAL _ 2] = BEGIN PChar[h, ',]; IF MakeRoom[h, Rope.Length[s]+1+extra, indent] THEN PChar[h, ' ]; PRope[h, s]; END; PUnsigned: PUBLIC PROCEDURE [h: Handle, i: CARDINAL] = BEGIN BEGIN PNumber[h, i, [10,FALSE,TRUE,1]] END; END; POctal: PUBLIC PROCEDURE [h: Handle, i: CARDINAL] = BEGIN PNumber[h, i, [8,FALSE,TRUE,1]]; IF i > 7 THEN PChar[h, 'B]; END; PNumber: PUBLIC PROCEDURE [h: Handle, num: UNSPECIFIED, format: NumberFormat] = BEGIN i: CARDINAL; neg: BOOLEAN _ FALSE; fill: CHARACTER _ (IF format.zerofill THEN '0 ELSE ' ); s: ROPE; IF ~format.unsigned AND INTEGER[num] < 0 THEN { num _ -INTEGER[num]; neg _ TRUE}; s _ Convert.RopeFromCard[from: LONG[CARDINAL[num]], base: format.base, showRadix: FALSE]; i _ Rope.Length[s]; IF neg THEN BEGIN i _ i + 1; IF fill = '0 THEN BEGIN PChar[h, '-]; neg _ FALSE END; END; THROUGH (i..format.columns] DO PChar[h, fill] ENDLOOP; IF neg THEN BEGIN PChar[h, '-]; END; PRope[h, s]; RETURN END; PLongNumber: PUBLIC PROCEDURE [ h: Handle, num: LONG UNSPECIFIED, format: NumberFormat] = BEGIN n: LONG CARDINAL _ num; i: CARDINAL; neg: BOOLEAN _ FALSE; fill: CHARACTER _ (IF format.zerofill THEN '0 ELSE ' ); s: ROPE; IF ~format.unsigned AND LOOPHOLE [num, LONG INTEGER] < 0 THEN BEGIN n _ -LOOPHOLE [num, LONG INTEGER]; neg _ TRUE END; s _ Convert.RopeFromCard[from: num, base: format.base, showRadix: FALSE]; i _ Rope.Length[s]; IF neg THEN BEGIN i _ i + 1; IF fill = '0 THEN BEGIN PChar[h, '-]; neg _ FALSE END; END; THROUGH (i..format.columns] DO PChar[h, fill] ENDLOOP; IF neg THEN BEGIN PChar[h, '-]; END; PRope[h, s]; RETURN END; PCr: PUBLIC PROCEDURE [h: Handle] = BEGIN PChar[h, '\n]; END; PRope: PUBLIC PROC [h: Handle, s: ROPE] = BEGIN i: INT; FOR i IN [0..Rope.Length[s]) DO PChar[h, Rope.Fetch[s, i]]; ENDLOOP; END; PSubString: PUBLIC PROC [h: Handle, ss: ConvertUnsafe.SubString] = TRUSTED BEGIN i: INT; FOR i IN [0..ss.length) DO PChar[h, ss.base[ss.offset + i]]; ENDLOOP; END; PLongOctal: PUBLIC PROC [h: Handle, lu: LONG UNSPECIFIED] = { PLongNumber[h, lu, [base: 8, zerofill: FALSE, unsigned: TRUE, columns: 0]]}; PNil: PUBLIC PROC [h: Handle, p: POINTER] = BEGIN IF p = NIL THEN PRope[h, "NIL"] ELSE POctal[h, LOOPHOLE[p]]; END; PLongNil: PUBLIC PROC [h: Handle, p: LONG POINTER] = BEGIN IF p = NIL THEN PRope[h, "NIL"] ELSE PLongOctal[h, p]; END; PNextNil: PUBLIC PROC [h: Handle, lbl: ROPE, p: POINTER, indent: CARDINAL _ 2] = BEGIN IF p = NIL THEN {PNext[h, lbl, 5, indent]; PRope[h, ": NIL"]} ELSE PNextOctal[h, lbl, LOOPHOLE[p], indent]; END; PNextLongNil: PUBLIC PROC [h: Handle, lbl: ROPE, p: LONG POINTER, indent: CARDINAL _ 2] = BEGIN IF p = NIL THEN {PNext[h, lbl, 5, indent]; PRope[h, ": NIL"]} ELSE PNextLongOctal[h, lbl, p, indent]; END; PNextLongOctal: PUBLIC PROC [ h: Handle, s: ROPE, num: LONG UNSPECIFIED, indent: CARDINAL _ 2] = BEGIN extra: CARDINAL _ LongLog8[num]; PNext[h, s, extra+2, indent]; PRope[h, ": "]; PLongOctal[h, num]; END; END.