free: implement -h

function                                             old     new   delta
.rodata                                           103331  103363     +32
packed_usage                                       33652   33654      +2
free_main                                            657     588     -69
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/1 up/down: 34/-69)            Total: -35 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/procps/free.c b/procps/free.c
index 5683629..0b68e1b 100644
--- a/procps/free.c
+++ b/procps/free.c
@@ -19,9 +19,9 @@
 //kbuild:lib-$(CONFIG_FREE) += free.o
 
 //usage:#define free_trivial_usage
-//usage:       "" IF_DESKTOP("[-bkmg]")
+//usage:       "" IF_DESKTOP("[-bkmgh]")
 //usage:#define free_full_usage "\n\n"
-//usage:       "Display the amount of free and used system memory"
+//usage:       "Display free and used memory"
 //usage:
 //usage:#define free_example_usage
 //usage:       "$ free\n"
@@ -29,6 +29,27 @@
 //usage:       "  Mem:       257628       248724         8904        59644        93124\n"
 //usage:       " Swap:       128516         8404       120112\n"
 //usage:       "Total:       386144       257128       129016\n"
+//procps-ng 3.3.15:
+// -b, --bytes         show output in bytes
+//     --kilo          show output in kilobytes
+//     --mega          show output in megabytes
+//     --giga          show output in gigabytes
+//     --tera          show output in terabytes
+//     --peta          show output in petabytes
+// -k, --kibi          show output in kibibytes
+// -m, --mebi          show output in mebibytes
+// -g, --gibi          show output in gibibytes
+//     --tebi          show output in tebibytes
+//     --pebi          show output in pebibytes
+// -h, --human         show human-readable output
+//     --si            use powers of 1000 not 1024
+// -l, --lohi          show detailed low and high memory statistics
+// -t, --total         show total for RAM + swap
+// -s N, --seconds N   repeat printing every N seconds
+// -c N, --count N     repeat printing N times, then exit
+// -w, --wide          wide output
+//
+//NB: if we implement -s or -c, need to stop being NOFORK!
 
 #include "libbb.h"
 #ifdef __linux__
@@ -38,18 +59,22 @@
 struct globals {
 	unsigned mem_unit;
 #if ENABLE_DESKTOP
-	uint8_t unit_steps;
-# define G_unit_steps g->unit_steps
+	unsigned unit;
+# define G_unit g->unit
 #else
-# define G_unit_steps 10
+# define G_unit (1 << 10)
 #endif
 	unsigned long cached_kb, available_kb, reclaimable_kb;
 };
 /* Because of NOFORK, "globals" are not in global data */
 
-static unsigned long long scale(struct globals *g, unsigned long d)
+static const char *scale(struct globals *g, unsigned long d)
 {
-	return ((unsigned long long)d * g->mem_unit) >> G_unit_steps;
+	/* Display (size * block_size) with one decimal digit.
+	 * If display_unit == 0, show value no bigger than 1024 with suffix (K,M,G...),
+	 * else divide by display_unit and do not use suffix.
+	 * Returns "auto pointer" */
+	return make_human_readable_str(d, g->mem_unit, G_unit);
 }
 
 /* NOINLINE reduces main() stack usage, which makes code smaller (on x86 at least) */
@@ -88,20 +113,27 @@
 	int seen_available;
 
 #if ENABLE_DESKTOP
-	G.unit_steps = 10;
+	G.unit = 1 << 10;
 	if (argv[1] && argv[1][0] == '-') {
 		switch (argv[1][1]) {
 		case 'b':
-			G.unit_steps = 0;
+			G.unit = 1;
 			break;
 		case 'k': /* 2^10 */
-			/* G.unit_steps = 10; - already is */
+			/* G.unit = 1 << 10; - already is */
 			break;
 		case 'm': /* 2^20 */
-			G.unit_steps = 20;
+			G.unit = 1 << 20;
 			break;
 		case 'g': /* 2^30 */
-			G.unit_steps = 30;
+			G.unit = 1 << 30;
+			break;
+//		case 't':
+// -- WRONG, -t is not "terabytes" in procps-ng, it's --total
+//			G.unit = 1 << 40;
+//			break;
+		case 'h':
+			G.unit = 0; /* human readable */
 			break;
 		default:
 			bb_show_usage();
@@ -126,23 +158,13 @@
 	cached += ((unsigned long long) G.reclaimable_kb * 1024) / G.mem_unit;
 	cached_plus_free = cached + info.freeram;
 
-/* In case (long long * G.mem_unit) can overflow, this can be used to reduce the chances */
-#if 0 //ENABLE_DESKTOP
-	while (!(G.mem_unit & 1) && G.unit_steps != 0) {
-		G.mem_unit >>= 1;
-		G.unit_steps--;
-		//bb_error_msg("mem_unit:%d unit_steps:%d", G.mem_unit, G.unit_steps);
-	}
-#endif
-
-#define FIELDS_6 "%12llu %11llu %11llu %11llu %11llu %11llu\n"
-#define FIELDS_3 (FIELDS_6 + 6 + 7 + 7)
-#define FIELDS_2 (FIELDS_6 + 6 + 7 + 7 + 7)
-
-	printf(FIELDS_6,
+	printf("%12s%12s%12s",
 		scale(&G, info.totalram),                //total
 		scale(&G, info.totalram - cached_plus_free), //used
-		scale(&G, info.freeram),                 //free
+		scale(&G, info.freeram)                  //free
+	);
+	/* using two printf's: only 4 auto strings are supported, we need 6 */
+	printf("%12s%12s%12s\n",
 		scale(&G, info.sharedram),               //shared
 		scale(&G, cached),                       //buff/cache
 		scale(&G, available)                     //available
@@ -152,14 +174,14 @@
 	 * buffer cache as free memory. */
 	if (!seen_available) {
 		printf("-/+ buffers/cache: ");
-		printf(FIELDS_2,
+		printf("%12s%12s%12s\n" + 4,
 			scale(&G, info.totalram - cached_plus_free), //used
 			scale(&G, cached_plus_free)                  //free
 		);
 	}
 #if BB_MMU
 	printf("Swap:  ");
-	printf(FIELDS_3,
+	printf("%12s%12s%12s\n",
 		scale(&G, info.totalswap),                 //total
 		scale(&G, info.totalswap - info.freeswap), //used
 		scale(&G, info.freeswap)                   //free