diff options
Diffstat (limited to 'tools/perf/util/parse-options.c')
-rw-r--r-- | tools/perf/util/parse-options.c | 78 |
1 files changed, 66 insertions, 12 deletions
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c index bf48092983c6..f62dee7bd924 100644 --- a/tools/perf/util/parse-options.c +++ b/tools/perf/util/parse-options.c @@ -42,7 +42,26 @@ static int get_value(struct parse_opt_ctx_t *p, return opterror(opt, "takes no value", flags); if (unset && (opt->flags & PARSE_OPT_NONEG)) return opterror(opt, "isn't available", flags); - + 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: @@ -343,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; @@ -358,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); @@ -387,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; } @@ -402,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; } @@ -426,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) @@ -509,6 +548,8 @@ static void print_option_help(const struct option *opts, int full) } if (!full && (opts->flags & PARSE_OPT_HIDDEN)) return; + if (opts->flags & PARSE_OPT_DISABLED) + return; pos = fprintf(stderr, " "); if (opts->short_name) @@ -679,3 +720,16 @@ int parse_opt_verbosity_cb(const struct option *opt, } return 0; } + +void set_option_flag(struct option *opts, int shortopt, const char *longopt, + int flag) +{ + for (; opts->type != OPTION_END; opts++) { + if ((shortopt && opts->short_name == shortopt) || + (opts->long_name && longopt && + !strcmp(opts->long_name, longopt))) { + opts->flags |= flag; + break; + } + } +} |