]> granicus.if.org Git - procps-ng/commitdiff
free: Clean up scale_size and fix `free -h --si`
authorJan Alexander Steffens (heftig) <jan.steffens@gmail.com>
Tue, 15 Jun 2021 18:43:36 +0000 (20:43 +0200)
committerJan Alexander Steffens (heftig) <jan.steffens@gmail.com>
Tue, 15 Jun 2021 19:42:51 +0000 (21:42 +0200)
- Simplify control flow a bit. We don't need two loop variables, either.
- Consistently use %lld for bytes.
- Fix the base handling for human-readable output. The code used to
  calculate *mebibytes* first, then scale that to the required exponent
  with the selected base, which is patently wrong.

Fixes https://gitlab.com/procps-ng/procps/-/issues/133

free.c

diff --git a/free.c b/free.c
index ac706472738cf738d35de0ffb87cea9562b9f4bf..d07b05285b0763237741c7d64086639f940db8a5 100644 (file)
--- a/free.c
+++ b/free.c
@@ -107,73 +107,52 @@ double power(unsigned int base, unsigned int expo)
 /* idea of this function is copied from top size scaling */
 static const char *scale_size(unsigned long size, int flags, struct commandline_arguments args)
 {
-       static char nextup[] = { 'B', 'K', 'M', 'G', 'T', 'P', 0 };
+       static char up[] = { 'B', 'K', 'M', 'G', 'T', 'P', 0 };
        static char buf[BUFSIZ];
        int i;
-       char *up;
        float base;
+       long long bytes;
 
-       if (flags & FREE_SI)
-               base = 1000.0;
-       else
-               base = 1024.0;
-
-       /* default output */
-       if (args.exponent == 0 && !(flags & FREE_HUMANREADABLE)) {
-               snprintf(buf, sizeof(buf), "%ld", size);
-               return buf;
-       }
+       base = (flags & FREE_SI) ? 1000.0 : 1024.0;
+       bytes = size * 1024LL;
 
        if (!(flags & FREE_HUMANREADABLE)) {
-               if (args.exponent == 1) {
+               switch (args.exponent) {
+               case 0:
+                       /* default output */
+                       snprintf(buf, sizeof(buf), "%ld", size);
+                       return buf;
+               case 1:
                        /* in bytes, which can not be in SI */
-                       snprintf(buf, sizeof(buf), "%lld", ((long long int)size) * 1024);
+                       snprintf(buf, sizeof(buf), "%lld", bytes);
                        return buf;
-               }
-               if (args.exponent > 1) {
+               default:
                        /* In desired scale. */
                        snprintf(buf, sizeof(buf), "%ld",
-                 (long int)((size * 1024.0) / power(base, args.exponent-1))
-                           );
+                               (long)(bytes / power(base, args.exponent-1)));
                        return buf;
                }
        }
 
        /* human readable output */
-       up = nextup;
-       for (i = 1; up[0] != 0; i++, up++) {
-               switch (i) {
-               case 1:
-                       if (4 >= snprintf(buf, sizeof(buf), "%ld%c", (long)size * 1024, *up))
+       if (4 >= snprintf(buf, sizeof(buf), "%lld%c", bytes, up[0]))
+               return buf;
+
+       for (i = 1; up[i] != 0; i++) {
+               if (flags & FREE_SI) {
+                       if (4 >= snprintf(buf, sizeof(buf), "%.1f%c",
+                                         (float)(bytes / power(base, i)), up[i]))
+                               return buf;
+                       if (4 >= snprintf(buf, sizeof(buf), "%ld%c",
+                                         (long)(bytes / power(base, i)), up[i]))
+                               return buf;
+               } else {
+                       if (5 >= snprintf(buf, sizeof(buf), "%.1f%ci",
+                                         (float)(bytes / power(base, i)), up[i]))
+                               return buf;
+                       if (5 >= snprintf(buf, sizeof(buf), "%ld%ci",
+                                         (long)(bytes / power(base, i)), up[i]))
                                return buf;
-                       break;
-               case 2:
-               case 3:
-               case 4:
-               case 5:
-               case 6:
-                       if (!(flags & FREE_SI)) {
-                               if (5 >=
-                                   snprintf(buf, sizeof(buf), "%.1f%ci",
-                                            (float)((size / 1024) * base / power(base, i - 2)), *up))
-                                       return buf;
-                               if (5 >=
-                                   snprintf(buf, sizeof(buf), "%ld%ci",
-                                            (long)((size / 1024) * base / power(base, i - 2)), *up))
-                                       return buf;
-                       } else {
-                               if (4 >=
-                                   snprintf(buf, sizeof(buf), "%.1f%c",
-                                            (float)((size / 1024) * base / power(base, i - 2)), *up))
-                                       return buf;
-                               if (4 >=
-                                   snprintf(buf, sizeof(buf), "%ld%c",
-                                            (long)((size / 1024) * base / power(base, i - 2)), *up))
-                                       return buf;
-                       }
-                       break;
-               case 7:
-                       break;
                }
        }
        /*