return 0;
}
+struct parsed_option {
+ const struct option *option;
+ enum opt_parsed flags;
+};
+
+static void register_abbrev(struct parse_opt_ctx_t *p,
+ const struct option *option, enum opt_parsed flags,
+ struct parsed_option *abbrev,
+ struct parsed_option *ambiguous)
+{
+ if (p->flags & PARSE_OPT_KEEP_UNKNOWN_OPT)
+ return;
+ if (abbrev->option &&
+ !is_alias(p, abbrev->option, option)) {
+ /*
+ * If this is abbreviated, it is
+ * ambiguous. So when there is no
+ * exact match later, we need to
+ * error out.
+ */
+ ambiguous->option = abbrev->option;
+ ambiguous->flags = abbrev->flags;
+ }
+ abbrev->option = option;
+ abbrev->flags = flags;
+}
+
static enum parse_opt_result parse_long_opt(
struct parse_opt_ctx_t *p, const char *arg,
const struct option *options)
{
const char *arg_end = strchrnul(arg, '=');
- const struct option *abbrev_option = NULL, *ambiguous_option = NULL;
- enum opt_parsed abbrev_flags = OPT_LONG, ambiguous_flags = OPT_LONG;
- int allow_abbrev = !(p->flags & PARSE_OPT_KEEP_UNKNOWN_OPT);
+ struct parsed_option abbrev = { .option = NULL, .flags = OPT_LONG };
+ struct parsed_option ambiguous = { .option = NULL, .flags = OPT_LONG };
for (; options->type != OPTION_END; options++) {
const char *rest, *long_name = options->long_name;
rest = NULL;
if (!rest) {
/* abbreviated? */
- if (allow_abbrev &&
- !strncmp(long_name, arg, arg_end - arg)) {
-is_abbreviated:
- if (abbrev_option &&
- !is_alias(p, abbrev_option, options)) {
- /*
- * If this is abbreviated, it is
- * ambiguous. So when there is no
- * exact match later, we need to
- * error out.
- */
- ambiguous_option = abbrev_option;
- ambiguous_flags = abbrev_flags;
- }
- abbrev_option = options;
- abbrev_flags = flags ^ opt_flags;
+ if (!strncmp(long_name, arg, arg_end - arg)) {
+ register_abbrev(p, options, flags ^ opt_flags,
+ &abbrev, &ambiguous);
continue;
}
/* negation allowed? */
if (options->flags & PARSE_OPT_NONEG)
continue;
/* negated and abbreviated very much? */
- if (allow_abbrev && starts_with("no-", arg)) {
+ if (starts_with("no-", arg)) {
flags |= OPT_UNSET;
- goto is_abbreviated;
+ register_abbrev(p, options, flags ^ opt_flags,
+ &abbrev, &ambiguous);
+ continue;
}
/* negated? */
if (!starts_with(arg, "no-"))
flags |= OPT_UNSET;
if (!skip_prefix(arg + 3, long_name, &rest)) {
/* abbreviated and negated? */
- if (allow_abbrev &&
- !strncmp(long_name, arg + 3,
+ if (!strncmp(long_name, arg + 3,
arg_end - arg - 3))
- goto is_abbreviated;
- else
- continue;
+ register_abbrev(p, options,
+ flags ^ opt_flags,
+ &abbrev, &ambiguous);
+ continue;
}
}
if (*rest) {
return get_value(p, options, flags ^ opt_flags);
}
- if (disallow_abbreviated_options && (ambiguous_option || abbrev_option))
+ if (disallow_abbreviated_options && (ambiguous.option || abbrev.option))
die("disallowed abbreviated or ambiguous option '%.*s'",
(int)(arg_end - arg), arg);
- if (ambiguous_option) {
+ if (ambiguous.option) {
error(_("ambiguous option: %s "
"(could be --%s%s or --%s%s)"),
arg,
- (ambiguous_flags & OPT_UNSET) ? "no-" : "",
- ambiguous_option->long_name,
- (abbrev_flags & OPT_UNSET) ? "no-" : "",
- abbrev_option->long_name);
+ (ambiguous.flags & OPT_UNSET) ? "no-" : "",
+ ambiguous.option->long_name,
+ (abbrev.flags & OPT_UNSET) ? "no-" : "",
+ abbrev.option->long_name);
return PARSE_OPT_HELP;
}
- if (abbrev_option) {
+ if (abbrev.option) {
if (*arg_end)
p->opt = arg_end + 1;
- return get_value(p, abbrev_option, abbrev_flags);
+ return get_value(p, abbrev.option, abbrev.flags);
}
return PARSE_OPT_UNKNOWN;
}