perf tools: Add support for exclusive option
Some options cannot be used at the same time. To handle such options add a new PARSE_OPT_EXCLUSIVE flag and show error message if more than one of them is used. Signed-off-by: Namhyung Kim <namhyung@kernel.org> Reviewed-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Acked-by: Hemant Kumar <hemant@linux.vnet.ibm.com> Cc: David Ahern <dsahern@gmail.com> Cc: Hemant Kumar <hemant@linux.vnet.ibm.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/1413990949-13953-5-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
f45d20ffb6
commit
42bd71d081
|
@ -45,6 +45,23 @@ static int get_value(struct parse_opt_ctx_t *p,
|
|||
if (opt->flags & PARSE_OPT_DISABLED)
|
||||
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) {
|
||||
switch (opt->type) {
|
||||
case OPTION_CALLBACK:
|
||||
|
@ -345,13 +362,14 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
|
|||
const char * const usagestr[])
|
||||
{
|
||||
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 */
|
||||
ctx->opt = NULL;
|
||||
|
||||
for (; ctx->argc; ctx->argc--, ctx->argv++) {
|
||||
const char *arg = ctx->argv[0];
|
||||
|
||||
arg = ctx->argv[0];
|
||||
if (*arg != '-' || !arg[1]) {
|
||||
if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION)
|
||||
break;
|
||||
|
@ -360,19 +378,21 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
|
|||
}
|
||||
|
||||
if (arg[1] != '-') {
|
||||
ctx->opt = arg + 1;
|
||||
ctx->opt = ++arg;
|
||||
if (internal_help && *ctx->opt == 'h')
|
||||
return usage_with_options_internal(usagestr, options, 0);
|
||||
switch (parse_short_opt(ctx, options)) {
|
||||
case -1:
|
||||
return parse_options_usage(usagestr, options, arg + 1, 1);
|
||||
return parse_options_usage(usagestr, options, arg, 1);
|
||||
case -2:
|
||||
goto unknown;
|
||||
case -3:
|
||||
goto exclusive;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (ctx->opt)
|
||||
check_typos(arg + 1, options);
|
||||
check_typos(arg, options);
|
||||
while (ctx->opt) {
|
||||
if (internal_help && *ctx->opt == 'h')
|
||||
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);
|
||||
*(char *)ctx->argv[0] = '-';
|
||||
goto unknown;
|
||||
case -3:
|
||||
goto exclusive;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -404,19 +426,23 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
|
|||
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);
|
||||
if (internal_help && !strcmp(arg + 2, "help"))
|
||||
if (internal_help && !strcmp(arg, "help"))
|
||||
return usage_with_options_internal(usagestr, options, 0);
|
||||
if (!strcmp(arg + 2, "list-opts"))
|
||||
if (!strcmp(arg, "list-opts"))
|
||||
return PARSE_OPT_LIST_OPTS;
|
||||
if (!strcmp(arg + 2, "list-cmds"))
|
||||
if (!strcmp(arg, "list-cmds"))
|
||||
return PARSE_OPT_LIST_SUBCMDS;
|
||||
switch (parse_long_opt(ctx, arg + 2, options)) {
|
||||
switch (parse_long_opt(ctx, arg, options)) {
|
||||
case -1:
|
||||
return parse_options_usage(usagestr, options, arg + 2, 0);
|
||||
return parse_options_usage(usagestr, options, arg, 0);
|
||||
case -2:
|
||||
goto unknown;
|
||||
case -3:
|
||||
excl_short_opt = 0;
|
||||
goto exclusive;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -428,6 +454,17 @@ unknown:
|
|||
ctx->opt = NULL;
|
||||
}
|
||||
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)
|
||||
|
|
|
@ -39,6 +39,7 @@ enum parse_opt_option_flags {
|
|||
PARSE_OPT_HIDDEN = 8,
|
||||
PARSE_OPT_LASTARG_DEFAULT = 16,
|
||||
PARSE_OPT_DISABLED = 32,
|
||||
PARSE_OPT_EXCLUSIVE = 64,
|
||||
};
|
||||
|
||||
struct option;
|
||||
|
@ -174,6 +175,7 @@ struct parse_opt_ctx_t {
|
|||
const char **out;
|
||||
int argc, cpidx;
|
||||
const char *opt;
|
||||
const struct option *excl_opt;
|
||||
int flags;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue