diff --git a/top/top.c b/top/top.c index 9d0e56a..34e2511 100644 --- a/top/top.c +++ b/top/top.c @@ -1552,15 +1552,46 @@ static const char *scale_mem (int target, unsigned long num, int width, int just if (Rc.zero_suppress && 0 >= num) goto end_justifies; + i = SK_Kb; + psfx = Scaled_sfxtab; scaled_num = num; - for (i = SK_Kb, psfx = Scaled_sfxtab; i < SK_Eb; psfx++, i++) { - if (i >= target - && (width >= snprintf(buf, sizeof(buf), fmttab[i], scaled_num, *psfx))) - goto end_justifies; + + // apply the minimum scaling + while (i < target) { + psfx++; + i++; scaled_num /= 1024.0; } - // well shoot, this outta' fit... + // get it to fit in the buffer + while (i <= SK_Eb) { + // first try lopping off digits + static char fmt[SMLBUFSIZ]; + int precision; + + switch(i) { + case 0: precision = 0; break; // k + case 1: precision = 1; break; // m + default: precision = 3; break; // g and up + } + + do { + snprintf(fmt, sizeof(fmt), "%%.%uf%%c", precision); + if (snprintf(buf, sizeof(buf), fmt, scaled_num, (i > 0 ? *psfx : '\0')) <= width) { + goto end_justifies; // it fits! + } + // drop a digit off the end and try again + precision--; + } while (precision > 0); + + // dropped all digits after decimal, still too big + // scale it and try again. + psfx++; + i++; + scaled_num /= 1024.0; + } + + // everything failed snprintf(buf, sizeof(buf), "?"); end_justifies: return justify_pad(buf, width, justr);