MINOR: debug/memstats: automatically determine first column size

The first column's width may vary a lot depending on outputs, and it's
annoying to have large empty columns on small names and mangled large
columns that are not yet large enough. In order to overcome this, this
patch adds a width field to the memstats applet's context, and this
width is calculated the first time the function is entered, by estimating
the width of all lines that will be dumped. This is simple enough and
does the job well. If in the future some filtering criteria are added,
it will still be possible to perform a single pass on everything
depending on the desired output format.
diff --git a/src/debug.c b/src/debug.c
index 0431306..090b82c 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -1229,6 +1229,7 @@
 struct dev_mem_ctx {
 	struct mem_stats *start, *stop; /* begin/end of dump */
 	int show_all;                   /* show all entries if non-null */
+	int width;
 };
 
 /* CLI parser for the "debug dev memstats" command. Sets a dev_mem_ctx shown above. */
@@ -1261,6 +1262,7 @@
 	/* otherwise proceed with the dump from p0 to p1 */
 	ctx->start = &__start_mem_stats;
 	ctx->stop  = &__stop_mem_stats;
+	ctx->width = 0;
 	return 0;
 }
 
@@ -1273,16 +1275,44 @@
 {
 	struct dev_mem_ctx *ctx = appctx->svcctx;
 	struct stconn *sc = appctx_sc(appctx);
-	struct mem_stats *ptr = ctx->start;
+	struct mem_stats *ptr;
 	int ret = 1;
 
 	if (unlikely(sc_ic(sc)->flags & (CF_WRITE_ERROR|CF_SHUTW)))
 		goto end;
 
+	if (!ctx->width) {
+		/* we don't know the first column's width, let's compute it
+		 * now based on a first pass on printable entries and their
+		 * expected width (approximated).
+		 */
+		for (ptr = ctx->start; ptr != ctx->stop; ptr++) {
+			const char *p, *name;
+			int w = 0;
+			char tmp;
+
+			if (!ptr->size && !ptr->calls && !ctx->show_all)
+				continue;
+
+			for (p = name = ptr->file; *p; p++) {
+				if (*p == '/')
+					name = p + 1;
+			}
+
+			if (ctx->show_all)
+				w = snprintf(&tmp, 0, "%s(%s:%d) ", ptr->func, name, ptr->line);
+			else
+				w = snprintf(&tmp, 0, "%s:%d ", name, ptr->line);
+
+			if (w > ctx->width)
+				ctx->width = w;
+		}
+	}
+
 	/* we have two inner loops here, one for the proxy, the other one for
 	 * the buffer.
 	 */
-	for (; ptr != ctx->stop; ptr++) {
+	for (ptr = ctx->start; ptr != ctx->stop; ptr++) {
 		const char *type;
 		const char *name;
 		const char *p;
@@ -1326,7 +1356,7 @@
 		if (ctx->show_all)
 			chunk_appendf(&trash, ")");
 
-		while (trash.data < (ctx->show_all ? 45 : 25))
+		while (trash.data < ctx->width)
 			trash.area[trash.data++] = ' ';
 
 		chunk_appendf(&trash, "%7s  size: %12lu  calls: %9lu  size/call: %6lu %s\n",