|
@@ -45,6 +45,23 @@ static int get_value(struct parse_opt_ctx_t *p,
|
|
if (opt->flags & PARSE_OPT_DISABLED)
|
|
if (opt->flags & PARSE_OPT_DISABLED)
|
|
return opterror(opt, "is not usable", flags);
|
|
return opterror(opt, "is not usable", flags);
|
|
|
|
|
|
|
|
+ if (opt->flags & PARSE_OPT_EXCLUSIVE) {
|
|
|
|
+ if (p->excl_opt) {
|
|
|
|
+ char msg[128];
|
|
|
|
+
|
|
|
|
+ if (((flags & OPT_SHORT) && p->excl_opt->short_name) ||
|
|
|
|
+ p->excl_opt->long_name == NULL) {
|
|
|
|
+ scnprintf(msg, sizeof(msg), "cannot be used with switch `%c'",
|
|
|
|
+ p->excl_opt->short_name);
|
|
|
|
+ } else {
|
|
|
|
+ scnprintf(msg, sizeof(msg), "cannot be used with %s",
|
|
|
|
+ p->excl_opt->long_name);
|
|
|
|
+ }
|
|
|
|
+ opterror(opt, msg, flags);
|
|
|
|
+ return -3;
|
|
|
|
+ }
|
|
|
|
+ p->excl_opt = opt;
|
|
|
|
+ }
|
|
if (!(flags & OPT_SHORT) && p->opt) {
|
|
if (!(flags & OPT_SHORT) && p->opt) {
|
|
switch (opt->type) {
|
|
switch (opt->type) {
|
|
case OPTION_CALLBACK:
|
|
case OPTION_CALLBACK:
|
|
@@ -345,13 +362,14 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
|
|
const char * const usagestr[])
|
|
const char * const usagestr[])
|
|
{
|
|
{
|
|
int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP);
|
|
int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP);
|
|
|
|
+ int excl_short_opt = 1;
|
|
|
|
+ const char *arg;
|
|
|
|
|
|
/* we must reset ->opt, unknown short option leave it dangling */
|
|
/* we must reset ->opt, unknown short option leave it dangling */
|
|
ctx->opt = NULL;
|
|
ctx->opt = NULL;
|
|
|
|
|
|
for (; ctx->argc; ctx->argc--, ctx->argv++) {
|
|
for (; ctx->argc; ctx->argc--, ctx->argv++) {
|
|
- const char *arg = ctx->argv[0];
|
|
|
|
-
|
|
|
|
|
|
+ arg = ctx->argv[0];
|
|
if (*arg != '-' || !arg[1]) {
|
|
if (*arg != '-' || !arg[1]) {
|
|
if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION)
|
|
if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION)
|
|
break;
|
|
break;
|
|
@@ -360,19 +378,21 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
|
|
}
|
|
}
|
|
|
|
|
|
if (arg[1] != '-') {
|
|
if (arg[1] != '-') {
|
|
- ctx->opt = arg + 1;
|
|
|
|
|
|
+ ctx->opt = ++arg;
|
|
if (internal_help && *ctx->opt == 'h')
|
|
if (internal_help && *ctx->opt == 'h')
|
|
return usage_with_options_internal(usagestr, options, 0);
|
|
return usage_with_options_internal(usagestr, options, 0);
|
|
switch (parse_short_opt(ctx, options)) {
|
|
switch (parse_short_opt(ctx, options)) {
|
|
case -1:
|
|
case -1:
|
|
- return parse_options_usage(usagestr, options, arg + 1, 1);
|
|
|
|
|
|
+ return parse_options_usage(usagestr, options, arg, 1);
|
|
case -2:
|
|
case -2:
|
|
goto unknown;
|
|
goto unknown;
|
|
|
|
+ case -3:
|
|
|
|
+ goto exclusive;
|
|
default:
|
|
default:
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
if (ctx->opt)
|
|
if (ctx->opt)
|
|
- check_typos(arg + 1, options);
|
|
|
|
|
|
+ check_typos(arg, options);
|
|
while (ctx->opt) {
|
|
while (ctx->opt) {
|
|
if (internal_help && *ctx->opt == 'h')
|
|
if (internal_help && *ctx->opt == 'h')
|
|
return usage_with_options_internal(usagestr, options, 0);
|
|
return usage_with_options_internal(usagestr, options, 0);
|
|
@@ -389,6 +409,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
|
|
ctx->argv[0] = strdup(ctx->opt - 1);
|
|
ctx->argv[0] = strdup(ctx->opt - 1);
|
|
*(char *)ctx->argv[0] = '-';
|
|
*(char *)ctx->argv[0] = '-';
|
|
goto unknown;
|
|
goto unknown;
|
|
|
|
+ case -3:
|
|
|
|
+ goto exclusive;
|
|
default:
|
|
default:
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
@@ -404,19 +426,23 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
- if (internal_help && !strcmp(arg + 2, "help-all"))
|
|
|
|
|
|
+ arg += 2;
|
|
|
|
+ if (internal_help && !strcmp(arg, "help-all"))
|
|
return usage_with_options_internal(usagestr, options, 1);
|
|
return usage_with_options_internal(usagestr, options, 1);
|
|
- if (internal_help && !strcmp(arg + 2, "help"))
|
|
|
|
|
|
+ if (internal_help && !strcmp(arg, "help"))
|
|
return usage_with_options_internal(usagestr, options, 0);
|
|
return usage_with_options_internal(usagestr, options, 0);
|
|
- if (!strcmp(arg + 2, "list-opts"))
|
|
|
|
|
|
+ if (!strcmp(arg, "list-opts"))
|
|
return PARSE_OPT_LIST_OPTS;
|
|
return PARSE_OPT_LIST_OPTS;
|
|
- if (!strcmp(arg + 2, "list-cmds"))
|
|
|
|
|
|
+ if (!strcmp(arg, "list-cmds"))
|
|
return PARSE_OPT_LIST_SUBCMDS;
|
|
return PARSE_OPT_LIST_SUBCMDS;
|
|
- switch (parse_long_opt(ctx, arg + 2, options)) {
|
|
|
|
|
|
+ switch (parse_long_opt(ctx, arg, options)) {
|
|
case -1:
|
|
case -1:
|
|
- return parse_options_usage(usagestr, options, arg + 2, 0);
|
|
|
|
|
|
+ return parse_options_usage(usagestr, options, arg, 0);
|
|
case -2:
|
|
case -2:
|
|
goto unknown;
|
|
goto unknown;
|
|
|
|
+ case -3:
|
|
|
|
+ excl_short_opt = 0;
|
|
|
|
+ goto exclusive;
|
|
default:
|
|
default:
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
@@ -428,6 +454,17 @@ unknown:
|
|
ctx->opt = NULL;
|
|
ctx->opt = NULL;
|
|
}
|
|
}
|
|
return PARSE_OPT_DONE;
|
|
return PARSE_OPT_DONE;
|
|
|
|
+
|
|
|
|
+exclusive:
|
|
|
|
+ parse_options_usage(usagestr, options, arg, excl_short_opt);
|
|
|
|
+ if ((excl_short_opt && ctx->excl_opt->short_name) ||
|
|
|
|
+ ctx->excl_opt->long_name == NULL) {
|
|
|
|
+ char opt = ctx->excl_opt->short_name;
|
|
|
|
+ parse_options_usage(NULL, options, &opt, 1);
|
|
|
|
+ } else {
|
|
|
|
+ parse_options_usage(NULL, options, ctx->excl_opt->long_name, 0);
|
|
|
|
+ }
|
|
|
|
+ return PARSE_OPT_HELP;
|
|
}
|
|
}
|
|
|
|
|
|
int parse_options_end(struct parse_opt_ctx_t *ctx)
|
|
int parse_options_end(struct parse_opt_ctx_t *ctx)
|