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.