Browse Source

opt: fix reporting of arguments when multiple arguments exist.

longidx is not updated in this case.  We should open-code option parsing.
Rusty Russell 15 years ago
parent
commit
b4cf10d83d
2 changed files with 49 additions and 10 deletions
  1. 4 10
      ccan/opt/opt.c
  2. 45 0
      ccan/opt/test/run-correct-reporting.c

+ 4 - 10
ccan/opt/opt.c

@@ -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

+ 45 - 0
ccan/opt/test/run-correct-reporting.c

@@ -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();
+}
+