Commit 42bd71d0 authored by Namhyung Kim's avatar Namhyung Kim Committed by Arnaldo Carvalho de Melo

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: default avatarNamhyung Kim <namhyung@kernel.org>
Reviewed-by: default avatarMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Acked-by: default avatarHemant 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.orgSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent f45d20ff
...@@ -45,6 +45,23 @@ static int get_value(struct parse_opt_ctx_t *p, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, ...@@ -428,6 +454,17 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
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)
......
...@@ -39,6 +39,7 @@ enum parse_opt_option_flags { ...@@ -39,6 +39,7 @@ enum parse_opt_option_flags {
PARSE_OPT_HIDDEN = 8, PARSE_OPT_HIDDEN = 8,
PARSE_OPT_LASTARG_DEFAULT = 16, PARSE_OPT_LASTARG_DEFAULT = 16,
PARSE_OPT_DISABLED = 32, PARSE_OPT_DISABLED = 32,
PARSE_OPT_EXCLUSIVE = 64,
}; };
struct option; struct option;
...@@ -174,6 +175,7 @@ struct parse_opt_ctx_t { ...@@ -174,6 +175,7 @@ struct parse_opt_ctx_t {
const char **out; const char **out;
int argc, cpidx; int argc, cpidx;
const char *opt; const char *opt;
const struct option *excl_opt;
int flags; int flags;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment