]> git.ozlabs.org Git - ccan/blobdiff - ccan/opt/opt.c
base64: fix for unsigned chars (e.g. ARM).
[ccan] / ccan / opt / opt.c
index 85de935a7d3b77fc2591b1435b1b38e79ff741cf..9149374cb001e6152eb46e03de6cc092ef6e4297 100644 (file)
@@ -1,4 +1,4 @@
-/* Licensed under GPLv3+ - see LICENSE file for details */
+/* Licensed under GPLv2+ - see LICENSE file for details */
 #include <ccan/opt/opt.h>
 #include <string.h>
 #include <errno.h>
@@ -34,7 +34,7 @@ static const char *next_name(const char *names, unsigned *len)
 static const char *first_opt(unsigned *i, unsigned *len)
 {
        for (*i = 0; *i < opt_count; (*i)++) {
-               if (opt_table[*i].type == OPT_SUBTABLE)
+               if (opt_table[*i].type & OPT_SUBTABLE)
                        continue;
                return first_name(opt_table[*i].names, len);
        }
@@ -44,7 +44,7 @@ static const char *first_opt(unsigned *i, unsigned *len)
 static const char *next_opt(const char *p, unsigned *i, unsigned *len)
 {
        for (; *i < opt_count; (*i)++) {
-               if (opt_table[*i].type == OPT_SUBTABLE)
+               if (opt_table[*i].type & OPT_SUBTABLE)
                        continue;
                if (!p)
                        return first_name(opt_table[*i].names, len);
@@ -114,10 +114,11 @@ static void check_opt(const struct opt_table *entry)
 {
        const char *p;
        unsigned len;
+       enum opt_type type = entry->type & (OPT_USER_MIN-1);
 
-       if (entry->type != OPT_HASARG && entry->type != OPT_NOARG
-           && entry->type != (OPT_EARLY|OPT_HASARG)
-           && entry->type != (OPT_EARLY|OPT_NOARG))
+       if (type != OPT_HASARG && type != OPT_NOARG
+           && type != (OPT_EARLY|OPT_HASARG)
+           && type != (OPT_EARLY|OPT_NOARG))
                failmsg("Option %s: unknown entry type %u",
                        entry->names, entry->type);
 
@@ -161,7 +162,7 @@ static void add_opt(const struct opt_table *entry)
 void _opt_register(const char *names, enum opt_type type,
                   char *(*cb)(void *arg),
                   char *(*cb_arg)(const char *optarg, void *arg),
-                  void (*show)(char buf[OPT_SHOW_LEN], const void *arg),
+                  bool (*show)(char *buf, size_t len, const void *arg),
                   const void *arg, const char *desc)
 {
        struct opt_table opt;
@@ -176,6 +177,24 @@ void _opt_register(const char *names, enum opt_type type,
        add_opt(&opt);
 }
 
+bool opt_unregister(const char *names)
+{
+       int found = -1, i;
+
+       for (i = 0; i < opt_count; i++) {
+               if (opt_table[i].type & OPT_SUBTABLE)
+                       continue;
+               if (strcmp(opt_table[i].names, names) == 0)
+                       found = i;
+       }
+       if (found == -1)
+               return false;
+       opt_count--;
+       memmove(&opt_table[found], &opt_table[found+1],
+               (opt_count - found) * sizeof(opt_table[found]));
+       return true;
+}
+
 void opt_register_table(const struct opt_table entry[], const char *desc)
 {
        unsigned int i, start = opt_count;
@@ -185,7 +204,7 @@ void opt_register_table(const struct opt_table entry[], const char *desc)
                add_opt(&heading);
        }
        for (i = 0; entry[i].type != OPT_END; i++) {
-               if (entry[i].type == OPT_SUBTABLE)
+               if (entry[i].type & OPT_SUBTABLE)
                        opt_register_table(subtable_of(&entry[i]),
                                           entry[i].desc);
                else {
@@ -207,14 +226,15 @@ bool opt_parse(int *argc, char *argv[], void (*errlog)(const char *fmt, ...))
        /* This helps opt_usage. */
        opt_argv0 = argv[0];
 
-       while ((ret = parse_one(argc, argv, 0, &offset, errlog)) == 1);
+       while ((ret = parse_one(argc, argv, 0, &offset, errlog, false)) == 1);
 
        /* parse_one returns 0 on finish, -1 on error */
        return (ret == 0);
 }
 
-bool opt_early_parse(int argc, char *argv[],
-                    void (*errlog)(const char *fmt, ...))
+static bool early_parse(int argc, char *argv[],
+                       void (*errlog)(const char *fmt, ...),
+                       bool ignore_unknown)
 {
        int ret;
        unsigned off = 0;
@@ -226,7 +246,7 @@ bool opt_early_parse(int argc, char *argv[],
        /* This helps opt_usage. */
        opt_argv0 = argv[0];
 
-       while ((ret = parse_one(&argc, tmpargv, OPT_EARLY, &off, errlog)) == 1);
+       while ((ret = parse_one(&argc, tmpargv, OPT_EARLY, &off, errlog, ignore_unknown)) == 1);
 
        opt_alloc.free(tmpargv);
 
@@ -234,6 +254,18 @@ bool opt_early_parse(int argc, char *argv[],
        return (ret == 0);
 }
 
+bool opt_early_parse(int argc, char *argv[],
+                    void (*errlog)(const char *fmt, ...))
+{
+       return early_parse(argc, argv, errlog, false);
+}
+
+bool opt_early_parse_incomplete(int argc, char *argv[],
+                               void (*errlog)(const char *fmt, ...))
+{
+       return early_parse(argc, argv, errlog, true);
+}
+
 void opt_free_table(void)
 {
        opt_alloc.free(opt_table);