]> git.ozlabs.org Git - ccan/blobdiff - ccan/opt/parse.c
opt: add new parse_early_args_incomplete.
[ccan] / ccan / opt / parse.c
index b92bcb14871eed40e4873e8473ac1c359e46d5e7..d227f7bca2ab679033dd920fe426983dc0ea9314 100644 (file)
@@ -1,4 +1,4 @@
-/* Licensed under GPLv3+ - see LICENSE file for details */
+/* Licensed under GPLv2+ - see LICENSE file for details */
 /* Actual code to parse commandline. */
 #include <ccan/opt/opt.h>
 #include <string.h>
@@ -29,12 +29,12 @@ static void consume_option(int *argc, char *argv[], unsigned optnum)
 }
 
 /* Returns 1 if argument consumed, 0 if all done, -1 on error. */
-int parse_one(int *argc, char *argv[], unsigned *offset,
-             void (*errlog)(const char *fmt, ...))
+int parse_one(int *argc, char *argv[], enum opt_type is_early, unsigned *offset,
+             void (*errlog)(const char *fmt, ...), bool unknown_ok)
 {
        unsigned i, arg, len;
        const char *o, *optarg = NULL;
-       char *problem;
+       char *problem = NULL;
 
        if (getenv("POSIXLY_CORRECT")) {
                /* Don't find options after non-options. */
@@ -67,10 +67,13 @@ int parse_one(int *argc, char *argv[], unsigned *offset,
                                continue;
                        break;
                }
-               if (!o)
+               if (!o) {
+                       if (unknown_ok)
+                               goto ok;
                        return parse_err(errlog, argv[0],
                                         argv[arg], strlen(argv[arg]),
                                         "unrecognized option");
+               }
                /* For error messages, we include the leading '--' */
                o -= 2;
                len += 2;
@@ -82,20 +85,26 @@ int parse_one(int *argc, char *argv[], unsigned *offset,
                        (*offset)++;
                        break;
                }
-               if (!o)
+               if (!o) {
+                       if (unknown_ok) {
+                               (*offset)++;
+                               goto ok;
+                       }
                        return parse_err(errlog, argv[0],
                                         argv[arg], strlen(argv[arg]),
                                         "unrecognized option");
+               }
                /* For error messages, we include the leading '-' */
                o--;
                len = 2;
        }
 
-       if (opt_table[i].type == OPT_NOARG) {
+       if ((opt_table[i].type & ~OPT_EARLY) == OPT_NOARG) {
                if (optarg)
                        return parse_err(errlog, argv[0], o, len,
                                         "doesn't allow an argument");
-               problem = opt_table[i].cb(opt_table[i].u.arg);
+               if ((opt_table[i].type & OPT_EARLY) == is_early)
+                       problem = opt_table[i].cb(opt_table[i].u.arg);
        } else {
                if (!optarg) {
                        /* Swallow any short options as optarg, eg -afile */
@@ -108,15 +117,18 @@ int parse_one(int *argc, char *argv[], unsigned *offset,
                if (!optarg)
                        return parse_err(errlog, argv[0], o, len,
                                         "requires an argument");
-               problem = opt_table[i].cb_arg(optarg, opt_table[i].u.arg);
+               if ((opt_table[i].type & OPT_EARLY) == is_early)
+                       problem = opt_table[i].cb_arg(optarg,
+                                                     opt_table[i].u.arg);
        }
 
        if (problem) {
                parse_err(errlog, argv[0], o, len, problem);
-               free(problem);
+               opt_alloc.free(problem);
                return -1;
        }
 
+ok:
        /* If no more letters in that short opt, reset offset. */
        if (*offset && !argv[arg][*offset + 1])
                *offset = 0;