scc@cl.cam.ac.uk (Stephen Crawley) (01/31/89)
I found that I needed a routine for unparsing integers in hexadecimal with
leading zero padding. The MIT libraries include a routine i_hunparse,
but it is too simple minded for the job in hand. So I've written a routine
i_unparse() that solves the general problem.
-- Steve
================
%% Unparse an integer into a string.
%% 'i' is the number to be unparsed.
%% 'base' is the base for the number which must be in the
%% range 2 <= base <= 36.
%% 'width' is the minimum width for the result string.
%% If 'zero_fill' is TRUE the result is padded with zeros to the left.
%% If 'left_adjust' is TRUE the result is padded with spaces to the right.
%% Otherwise the result is padded with spaces to the left hand.
i_unparse = PROC (i, base, width: int, zero_fill, left_adjust: bool)
RETURNS (string) SIGNALS (bad_args)
ac = array[char]
OWN digits: string := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
IF base <= 1 COR base > string$size(digits) COR
width < 0 COR width > 2**16 - 1 THEN
SIGNAL bad_args
END
hi: int := width
fill: char := ' '
IF width = 0 THEN
hi := 20
left_adjust := FALSE
zero_fill := FALSE
ELSEIF zero_fill THEN
fill := '0'
left_adjust := FALSE
END
chars: ac := ac$fill(1, hi, fill)
pos: int := hi
IF i = 0 THEN
chars[pos] := '0'
pos := pos - 1
ELSE
negative: bool := i < 0
IF negative THEN i := -i END
EXCEPT WHEN overflow:
%% Phooey!!! MIN_INT can't be negated!
%% Do the 1st loop iteration by steam.
i := -(i + 1)
d: int := i // base + 1
i := i / base
IF d = base THEN
d := 0
i := i + 1
END
chars[pos] := digits[d + 1]
pos := pos - 1
END
%% Build the digits
WHILE i > 0 DO
digit: char := digits[i // base + 1]
i := i / base
IF pos > 0 THEN
chars[pos] := digit
ELSE
ac$addl(chars, digit)
END
pos := pos - 1
END
%% Prepend the '-' sign before the 1st digit
IF negative THEN
IF pos <= 0 THEN
ac$addl(chars, '-')
pos := pos - 1
ELSEIF zero_fill THEN
chars[1] := '-'
pos := 0
ELSE
chars[pos] := '-'
pos := pos - 1
END
END
END
%% Left adjust by shuffling the chars down and filling with ' 's
IF left_adjust CAND pos > 0 THEN
FOR j: int IN int$from_to(1, hi - pos) DO
chars[j] := chars[j + pos]
END
FOR j: int IN int$from_to(hi - pos + 1, hi) DO
chars[j] := ' '
END
END
IF width = 0 CAND pos > 0 THEN ac$trim(chars, pos + 1, hi - pos) END
RETURN (string$ac2s(chars))
END i_unparse
================
%% Unparse an integer in hexadecimal
i_hunparse = PROC (i: int) RETURNS (string)
RETURN (i_unparse(i, 16, 0, FALSE, FALSE))
END i_hunparse
================
%% Unparse an integer in octal
i_ounparse = PROC (i: int) RETURNS (string)
RETURN (i_unparse(i, 8, 0, FALSE, FALSE))
END i_ounparse