diff options
-rw-r--r-- | tools/perf/builtin-kvm.c | 12 | ||||
-rw-r--r-- | tools/perf/perf-completion.sh | 2 | ||||
-rw-r--r-- | tools/perf/util/parse-options.c | 37 | ||||
-rw-r--r-- | tools/perf/util/parse-options.h | 8 |
4 files changed, 46 insertions, 13 deletions
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index a7350519c63f..21c164b8f9db 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c | |||
@@ -1691,17 +1691,15 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1691 | OPT_END() | 1691 | OPT_END() |
1692 | }; | 1692 | }; |
1693 | 1693 | ||
1694 | 1694 | const char *const kvm_subcommands[] = { "top", "record", "report", "diff", | |
1695 | const char * const kvm_usage[] = { | 1695 | "buildid-list", "stat", NULL }; |
1696 | "perf kvm [<options>] {top|record|report|diff|buildid-list|stat}", | 1696 | const char *kvm_usage[] = { NULL, NULL }; |
1697 | NULL | ||
1698 | }; | ||
1699 | 1697 | ||
1700 | perf_host = 0; | 1698 | perf_host = 0; |
1701 | perf_guest = 1; | 1699 | perf_guest = 1; |
1702 | 1700 | ||
1703 | argc = parse_options(argc, argv, kvm_options, kvm_usage, | 1701 | argc = parse_options_subcommand(argc, argv, kvm_options, kvm_subcommands, kvm_usage, |
1704 | PARSE_OPT_STOP_AT_NON_OPTION); | 1702 | PARSE_OPT_STOP_AT_NON_OPTION); |
1705 | if (!argc) | 1703 | if (!argc) |
1706 | usage_with_options(kvm_usage, kvm_options); | 1704 | usage_with_options(kvm_usage, kvm_options); |
1707 | 1705 | ||
diff --git a/tools/perf/perf-completion.sh b/tools/perf/perf-completion.sh index 496e2abb5482..ae3a57694b6b 100644 --- a/tools/perf/perf-completion.sh +++ b/tools/perf/perf-completion.sh | |||
@@ -123,7 +123,7 @@ __perf_main () | |||
123 | __perfcomp_colon "$evts" "$cur" | 123 | __perfcomp_colon "$evts" "$cur" |
124 | # List subcommands for 'perf kvm' | 124 | # List subcommands for 'perf kvm' |
125 | elif [[ $prev == "kvm" ]]; then | 125 | elif [[ $prev == "kvm" ]]; then |
126 | subcmds="top record report diff buildid-list stat" | 126 | subcmds=$($cmd $prev --list-cmds) |
127 | __perfcomp_colon "$subcmds" "$cur" | 127 | __perfcomp_colon "$subcmds" "$cur" |
128 | # List long option names | 128 | # List long option names |
129 | elif [[ $cur == --* ]]; then | 129 | elif [[ $cur == --* ]]; then |
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c index d22e3f8017dc..bf48092983c6 100644 --- a/tools/perf/util/parse-options.c +++ b/tools/perf/util/parse-options.c | |||
@@ -407,7 +407,9 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, | |||
407 | if (internal_help && !strcmp(arg + 2, "help")) | 407 | if (internal_help && !strcmp(arg + 2, "help")) |
408 | return usage_with_options_internal(usagestr, options, 0); | 408 | return usage_with_options_internal(usagestr, options, 0); |
409 | if (!strcmp(arg + 2, "list-opts")) | 409 | if (!strcmp(arg + 2, "list-opts")) |
410 | return PARSE_OPT_LIST; | 410 | return PARSE_OPT_LIST_OPTS; |
411 | if (!strcmp(arg + 2, "list-cmds")) | ||
412 | return PARSE_OPT_LIST_SUBCMDS; | ||
411 | switch (parse_long_opt(ctx, arg + 2, options)) { | 413 | switch (parse_long_opt(ctx, arg + 2, options)) { |
412 | case -1: | 414 | case -1: |
413 | return parse_options_usage(usagestr, options, arg + 2, 0); | 415 | return parse_options_usage(usagestr, options, arg + 2, 0); |
@@ -433,25 +435,45 @@ int parse_options_end(struct parse_opt_ctx_t *ctx) | |||
433 | return ctx->cpidx + ctx->argc; | 435 | return ctx->cpidx + ctx->argc; |
434 | } | 436 | } |
435 | 437 | ||
436 | int parse_options(int argc, const char **argv, const struct option *options, | 438 | int parse_options_subcommand(int argc, const char **argv, const struct option *options, |
437 | const char * const usagestr[], int flags) | 439 | const char *const subcommands[], const char *usagestr[], int flags) |
438 | { | 440 | { |
439 | struct parse_opt_ctx_t ctx; | 441 | struct parse_opt_ctx_t ctx; |
440 | 442 | ||
441 | perf_header__set_cmdline(argc, argv); | 443 | perf_header__set_cmdline(argc, argv); |
442 | 444 | ||
445 | /* build usage string if it's not provided */ | ||
446 | if (subcommands && !usagestr[0]) { | ||
447 | struct strbuf buf = STRBUF_INIT; | ||
448 | |||
449 | strbuf_addf(&buf, "perf %s [<options>] {", argv[0]); | ||
450 | for (int i = 0; subcommands[i]; i++) { | ||
451 | if (i) | ||
452 | strbuf_addstr(&buf, "|"); | ||
453 | strbuf_addstr(&buf, subcommands[i]); | ||
454 | } | ||
455 | strbuf_addstr(&buf, "}"); | ||
456 | |||
457 | usagestr[0] = strdup(buf.buf); | ||
458 | strbuf_release(&buf); | ||
459 | } | ||
460 | |||
443 | parse_options_start(&ctx, argc, argv, flags); | 461 | parse_options_start(&ctx, argc, argv, flags); |
444 | switch (parse_options_step(&ctx, options, usagestr)) { | 462 | switch (parse_options_step(&ctx, options, usagestr)) { |
445 | case PARSE_OPT_HELP: | 463 | case PARSE_OPT_HELP: |
446 | exit(129); | 464 | exit(129); |
447 | case PARSE_OPT_DONE: | 465 | case PARSE_OPT_DONE: |
448 | break; | 466 | break; |
449 | case PARSE_OPT_LIST: | 467 | case PARSE_OPT_LIST_OPTS: |
450 | while (options->type != OPTION_END) { | 468 | while (options->type != OPTION_END) { |
451 | printf("--%s ", options->long_name); | 469 | printf("--%s ", options->long_name); |
452 | options++; | 470 | options++; |
453 | } | 471 | } |
454 | exit(130); | 472 | exit(130); |
473 | case PARSE_OPT_LIST_SUBCMDS: | ||
474 | for (int i = 0; subcommands[i]; i++) | ||
475 | printf("%s ", subcommands[i]); | ||
476 | exit(130); | ||
455 | default: /* PARSE_OPT_UNKNOWN */ | 477 | default: /* PARSE_OPT_UNKNOWN */ |
456 | if (ctx.argv[0][1] == '-') { | 478 | if (ctx.argv[0][1] == '-') { |
457 | error("unknown option `%s'", ctx.argv[0] + 2); | 479 | error("unknown option `%s'", ctx.argv[0] + 2); |
@@ -464,6 +486,13 @@ int parse_options(int argc, const char **argv, const struct option *options, | |||
464 | return parse_options_end(&ctx); | 486 | return parse_options_end(&ctx); |
465 | } | 487 | } |
466 | 488 | ||
489 | int parse_options(int argc, const char **argv, const struct option *options, | ||
490 | const char * const usagestr[], int flags) | ||
491 | { | ||
492 | return parse_options_subcommand(argc, argv, options, NULL, | ||
493 | (const char **) usagestr, flags); | ||
494 | } | ||
495 | |||
467 | #define USAGE_OPTS_WIDTH 24 | 496 | #define USAGE_OPTS_WIDTH 24 |
468 | #define USAGE_GAP 2 | 497 | #define USAGE_GAP 2 |
469 | 498 | ||
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h index cbf0149cf221..d8dac8ac5f37 100644 --- a/tools/perf/util/parse-options.h +++ b/tools/perf/util/parse-options.h | |||
@@ -140,6 +140,11 @@ extern int parse_options(int argc, const char **argv, | |||
140 | const struct option *options, | 140 | const struct option *options, |
141 | const char * const usagestr[], int flags); | 141 | const char * const usagestr[], int flags); |
142 | 142 | ||
143 | extern int parse_options_subcommand(int argc, const char **argv, | ||
144 | const struct option *options, | ||
145 | const char *const subcommands[], | ||
146 | const char *usagestr[], int flags); | ||
147 | |||
143 | extern NORETURN void usage_with_options(const char * const *usagestr, | 148 | extern NORETURN void usage_with_options(const char * const *usagestr, |
144 | const struct option *options); | 149 | const struct option *options); |
145 | 150 | ||
@@ -148,7 +153,8 @@ extern NORETURN void usage_with_options(const char * const *usagestr, | |||
148 | enum { | 153 | enum { |
149 | PARSE_OPT_HELP = -1, | 154 | PARSE_OPT_HELP = -1, |
150 | PARSE_OPT_DONE, | 155 | PARSE_OPT_DONE, |
151 | PARSE_OPT_LIST, | 156 | PARSE_OPT_LIST_OPTS, |
157 | PARSE_OPT_LIST_SUBCMDS, | ||
152 | PARSE_OPT_UNKNOWN, | 158 | PARSE_OPT_UNKNOWN, |
153 | }; | 159 | }; |
154 | 160 | ||