opt: fix reporting of arguments when multiple arguments exist.
authorRusty Russell <rusty@rustcorp.com.au>
Tue, 5 Oct 2010 05:26:19 +0000 (15:56 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Tue, 5 Oct 2010 05:26:19 +0000 (15:56 +1030)
longidx is not updated in this case.  We should open-code option parsing.

ccan/opt/opt.c
ccan/opt/test/run-correct-reporting.c [new file with mode: 0644]

index 155d7aaf46b64c93ca712f550521f6e4e6aa423f..ea27dfa7679f2c8a6e8353558ceec5eff3297e49 100644 (file)
@@ -280,7 +280,6 @@ bool opt_parse(int *argc, char *argv[], void (*errlog)(const char *fmt, ...))
               != -1) {
                char *problem;
                const char *name;
-               bool missing = false;
 
                /* optopt is 0 if it's an unknown long option, *or* if
                 * -? is a valid short option. */
@@ -291,8 +290,10 @@ bool opt_parse(int *argc, char *argv[], void (*errlog)(const char *fmt, ...))
                                break;
                        }
                } else if (ret == ':') {
-                       missing = true;
-                       ret = optopt;
+                       /* Missing argument: longidx not updated :( */
+                       parse_fail(errlog, optopt, argv[optind-1]+2,
+                                  "option requires an argument");
+                       break;
                }
 
                if (ret != 0)
@@ -300,13 +301,6 @@ bool opt_parse(int *argc, char *argv[], void (*errlog)(const char *fmt, ...))
                else
                        e = find_long(longidx, &name);
 
-               /* Missing argument */
-               if (missing) {
-                       parse_fail(errlog, ret, name,
-                                  "option requires an argument");
-                       break;
-               }
-
                if (e->flags == OPT_HASARG)
                        problem = e->cb_arg(optarg, e->arg);
                else
diff --git a/ccan/opt/test/run-correct-reporting.c b/ccan/opt/test/run-correct-reporting.c
new file mode 100644 (file)
index 0000000..44f68ae
--- /dev/null
@@ -0,0 +1,45 @@
+/* Make sure when multiple equivalent options, correct one is used for errors */
+
+#include <ccan/tap/tap.h>
+#include <stdlib.h>
+#include <ccan/opt/opt.c>
+#include <ccan/opt/usage.c>
+#include "utils.h"
+
+int main(int argc, char *argv[])
+{
+       plan_tests(12);
+
+       /* --aaa without args. */
+       opt_register_arg("-a/--aaa", test_arg, NULL, "aaa", NULL);
+       ok1(!parse_args(&argc, &argv, "--aaa", NULL));
+       ok1(strstr(err_output, ": --aaa: option requires an argument"));
+       free(err_output);
+       err_output = NULL;
+       ok1(!parse_args(&argc, &argv, "-a", NULL));
+       ok1(strstr(err_output, ": -a: option requires an argument"));
+       free(err_output);
+       err_output = NULL;
+
+       /* Multiple */
+       opt_register_arg("--bbb/-b/-c/--ccc", test_arg, NULL, "aaa", NULL);
+       ok1(!parse_args(&argc, &argv, "--bbb", NULL));
+       ok1(strstr(err_output, ": --bbb: option requires an argument"));
+       free(err_output);
+       err_output = NULL;
+       ok1(!parse_args(&argc, &argv, "-b", NULL));
+       ok1(strstr(err_output, ": -b: option requires an argument"));
+       free(err_output);
+       err_output = NULL;
+       ok1(!parse_args(&argc, &argv, "-c", NULL));
+       ok1(strstr(err_output, ": -c: option requires an argument"));
+       free(err_output);
+       err_output = NULL;
+       ok1(!parse_args(&argc, &argv, "--ccc", NULL));
+       ok1(strstr(err_output, ": --ccc: option requires an argument"));
+       free(err_output);
+       err_output = NULL;
+
+       return exit_status();
+}
+