I'm not done with reviewing yet, but I'm running out of time for now.
Just a simple observation concerning this change:
> +/* convert uint64_t to base N string */
>
> char *
> -ulton(long unsigned int n, int base)
> +u64ton(uint64_t n, int base)
> {
> char *p;
> static char buf [20];
I don't think it's actually an issue since I don't see how n can ever be
that large, but 20 is too small to hold a NUL-terminated base 10 version
of UINT64_MAX, as 18446744073709551615 has 20 digits. Thus,
u64ton(UINT64_MAX, 10) will write to and return buf[-1].
With bases < 10 you'll have trouble with buf[21] (base 8 will need
buf[23] and base 2 will need buf[65]).
Since all three callers of u64ton() use base 10 anyway, doing buf[21]
would be enough for now. I wonder if we should get rid of the base
argument and simplify accordingly (that would be a separate diff).