opt: functions to show integer values with kMGTPE suffixes
[ccan] / ccan / opt / usage.c
index d76c3b03ed317e3306f4ccad739ccdcac2fbdd9d..f321ed2949a8bfb7cd5cdbce5955780dba1cd233 100644 (file)
@@ -1,3 +1,4 @@
+/* Licensed under GPLv3+ - see LICENSE file for details */
 #include <ccan/opt/opt.h>
 #include <string.h>
 #include <stdlib.h>
@@ -6,21 +7,16 @@
 #include "private.h"
 
 /* We only use this for pointer comparisons. */
-const char opt_table_hidden[1];
+const char opt_hidden[1];
 
 static unsigned write_short_options(char *str)
 {
        unsigned int i, num = 0;
+       const char *p;
 
-       for (i = 0; i < opt_count; i++) {
-               if (opt_table[i].flags == OPT_SUBTABLE) {
-                       if (opt_table[i].desc == opt_table_hidden) {
-                               /* Skip these options. */
-                               i += (intptr_t)opt_table[i].arg - 1;
-                               continue;
-                       }
-               } else if (opt_table[i].shortopt)
-                       str[num++] = opt_table[i].shortopt;
+       for (p = first_sopt(&i); p; p = next_sopt(p, &i)) {
+               if (opt_table[i].desc != opt_hidden)
+                       str[num++] = *p;
        }
        return num;
 }
@@ -33,24 +29,31 @@ char *opt_usage(const char *argv0, const char *extra)
        unsigned int i, num, len;
        char *ret, *p;
 
+       if (!extra) {
+               extra = "";
+               for (i = 0; i < opt_count; i++) {
+                       if (opt_table[i].cb == (void *)opt_usage_and_exit
+                           && opt_table[i].u.carg) {
+                               extra = opt_table[i].u.carg;
+                               break;
+                       }
+               }
+       }
+
        /* An overestimate of our length. */
        len = strlen("Usage: %s ") + strlen(argv0)
-               + strlen("[-%.*s]") + opt_count + 1
+               + strlen("[-%.*s]") + opt_num_short + 1
                + strlen(" ") + strlen(extra)
                + strlen("\n");
 
        for (i = 0; i < opt_count; i++) {
-               if (opt_table[i].flags == OPT_SUBTABLE) {
+               if (opt_table[i].type == OPT_SUBTABLE) {
                        len += strlen("\n") + strlen(opt_table[i].desc)
                                + strlen(":\n");
-               } else {
-                       len += strlen("--%s/-%c") + strlen(" <arg>");
-                       if (opt_table[i].longopt)
-                               len += strlen(opt_table[i].longopt);
-                       if (opt_table[i].desc) {
-                               len += strlen(OPT_SPACE_PAD)
-                                       + strlen(opt_table[i].desc) + 1;
-                       }
+               } else if (opt_table[i].desc != opt_hidden) {
+                       len += strlen(opt_table[i].names) + strlen(" <arg>");
+                       len += strlen(OPT_SPACE_PAD)
+                               + strlen(opt_table[i].desc) + 1;
                        if (opt_table[i].show) {
                                len += strlen("(default: %s)")
                                        + OPT_SHOW_LEN + sizeof("...");
@@ -78,39 +81,28 @@ char *opt_usage(const char *argv0, const char *extra)
        p += sprintf(p, "\n");
 
        for (i = 0; i < opt_count; i++) {
-               if (opt_table[i].flags == OPT_SUBTABLE) {
-                       if (opt_table[i].desc == opt_table_hidden) {
-                               /* Skip these options. */
-                               i += (intptr_t)opt_table[i].arg - 1;
-                               continue;
-                       }
+               if (opt_table[i].desc == opt_hidden)
+                       continue;
+               if (opt_table[i].type == OPT_SUBTABLE) {
                        p += sprintf(p, "%s:\n", opt_table[i].desc);
                        continue;
                }
-               if (opt_table[i].shortopt && opt_table[i].longopt)
-                       len = sprintf(p, "--%s/-%c",
-                                    opt_table[i].longopt,
-                                     opt_table[i].shortopt);
-               else if (opt_table[i].shortopt)
-                       len = sprintf(p, "-%c", opt_table[i].shortopt);
-               else
-                       len = sprintf(p, "--%s", opt_table[i].longopt);
-               if (opt_table[i].flags == OPT_HASARG)
+               len = sprintf(p, "%s", opt_table[i].names);
+               if (opt_table[i].type == OPT_HASARG
+                   && !strchr(opt_table[i].names, ' ')
+                   && !strchr(opt_table[i].names, '='))
                        len += sprintf(p + len, " <arg>");
-               if (opt_table[i].desc || opt_table[i].show)
-                       len += sprintf(p + len, "%.*s",
-                                      len < strlen(OPT_SPACE_PAD)
-                                      ? strlen(OPT_SPACE_PAD) - len : 1,
-                                      OPT_SPACE_PAD);
+               len += sprintf(p + len, "%.*s",
+                              len < strlen(OPT_SPACE_PAD)
+                              ? (unsigned)strlen(OPT_SPACE_PAD) - len : 1,
+                              OPT_SPACE_PAD);
 
-               if (opt_table[i].desc)
-                       len += sprintf(p + len, "%s", opt_table[i].desc);
+               len += sprintf(p + len, "%s", opt_table[i].desc);
                if (opt_table[i].show) {
                        char buf[OPT_SHOW_LEN + sizeof("...")];
                        strcpy(buf + OPT_SHOW_LEN, "...");
-                       opt_table[i].show(buf, opt_table[i].arg);
-                       len += sprintf(p + len, "%s(default: %s)",
-                                      opt_table[i].desc ? " " : "", buf);
+                       opt_table[i].show(buf, opt_table[i].u.arg);
+                       len += sprintf(p + len, " (default: %s)", buf);
                }
                p += len;
                p += sprintf(p, "\n");