+static char *add_str_len(char *base, size_t *len, size_t *max,
+ const char *str, size_t slen)
+{
+ if (slen >= *max - *len)
+ base = opt_alloc.realloc(base, *max = (*max * 2 + slen + 1));
+ memcpy(base + *len, str, slen);
+ *len += slen;
+ return base;
+}
+
+static char *add_str(char *base, size_t *len, size_t *max, const char *str)
+{
+ return add_str_len(base, len, max, str, strlen(str));
+}
+
+static char *add_indent(char *base, size_t *len, size_t *max, size_t indent)
+{
+ if (indent >= *max - *len)
+ base = opt_alloc.realloc(base, *max = (*max * 2 + indent + 1));
+ memset(base + *len, ' ', indent);
+ *len += indent;
+ return base;
+}
+
+static char *add_desc(char *base, size_t *len, size_t *max,
+ unsigned int indent, unsigned int width,
+ const struct opt_table *opt)
+{
+ size_t off, prefix, l;
+ const char *p;
+ bool same_line = false, start = true;
+
+ base = add_str(base, len, max, opt->names);
+ off = strlen(opt->names);
+ if ((opt->type & OPT_HASARG)
+ && !strchr(opt->names, ' ')
+ && !strchr(opt->names, '=')) {
+ base = add_str(base, len, max, " <arg>");
+ off += strlen(" <arg>");
+ }
+
+ /* Do we start description on next line? */
+ if (off + 2 > indent) {
+ base = add_str(base, len, max, "\n");
+ off = 0;