aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/parse-options.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2015-10-25 04:40:31 -0400
committerIngo Molnar <mingo@kernel.org>2015-10-25 04:40:31 -0400
commit4341801873e23bbecee76dabb7c111e3693b900f (patch)
tree473e96f38af8c9e5a6bfd99ef20c021584168343 /tools/perf/util/parse-options.c
parent80fcd45ee05b4ef05e61d37a5ffb70a67095a9f6 (diff)
parent161d9041782b86c5493481566539bfc058ceeaff (diff)
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements from Arnaldo Carvalho de Melo: New user-visible features: - Show ordered command line options when -h is used or when an unknown option is specified. (Arnaldo Carvalho de Melo) - If options are passed after -h, show just its descriptions, not all options. (Arnaldo Carvalho de Melo) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf/util/parse-options.c')
-rw-r--r--tools/perf/util/parse-options.c90
1 files changed, 81 insertions, 9 deletions
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index 8aa7922397a9..22c2806bda98 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -2,6 +2,7 @@
2#include "parse-options.h" 2#include "parse-options.h"
3#include "cache.h" 3#include "cache.h"
4#include "header.h" 4#include "header.h"
5#include <linux/string.h>
5 6
6#define OPT_SHORT 1 7#define OPT_SHORT 1
7#define OPT_UNSET 2 8#define OPT_UNSET 2
@@ -372,7 +373,8 @@ void parse_options_start(struct parse_opt_ctx_t *ctx,
372} 373}
373 374
374static int usage_with_options_internal(const char * const *, 375static int usage_with_options_internal(const char * const *,
375 const struct option *, int); 376 const struct option *, int,
377 struct parse_opt_ctx_t *);
376 378
377int parse_options_step(struct parse_opt_ctx_t *ctx, 379int parse_options_step(struct parse_opt_ctx_t *ctx,
378 const struct option *options, 380 const struct option *options,
@@ -396,8 +398,9 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
396 398
397 if (arg[1] != '-') { 399 if (arg[1] != '-') {
398 ctx->opt = ++arg; 400 ctx->opt = ++arg;
399 if (internal_help && *ctx->opt == 'h') 401 if (internal_help && *ctx->opt == 'h') {
400 return usage_with_options_internal(usagestr, options, 0); 402 return usage_with_options_internal(usagestr, options, 0, ctx);
403 }
401 switch (parse_short_opt(ctx, options)) { 404 switch (parse_short_opt(ctx, options)) {
402 case -1: 405 case -1:
403 return parse_options_usage(usagestr, options, arg, 1); 406 return parse_options_usage(usagestr, options, arg, 1);
@@ -412,7 +415,7 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
412 check_typos(arg, options); 415 check_typos(arg, options);
413 while (ctx->opt) { 416 while (ctx->opt) {
414 if (internal_help && *ctx->opt == 'h') 417 if (internal_help && *ctx->opt == 'h')
415 return usage_with_options_internal(usagestr, options, 0); 418 return usage_with_options_internal(usagestr, options, 0, ctx);
416 arg = ctx->opt; 419 arg = ctx->opt;
417 switch (parse_short_opt(ctx, options)) { 420 switch (parse_short_opt(ctx, options)) {
418 case -1: 421 case -1:
@@ -445,9 +448,9 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
445 448
446 arg += 2; 449 arg += 2;
447 if (internal_help && !strcmp(arg, "help-all")) 450 if (internal_help && !strcmp(arg, "help-all"))
448 return usage_with_options_internal(usagestr, options, 1); 451 return usage_with_options_internal(usagestr, options, 1, ctx);
449 if (internal_help && !strcmp(arg, "help")) 452 if (internal_help && !strcmp(arg, "help"))
450 return usage_with_options_internal(usagestr, options, 0); 453 return usage_with_options_internal(usagestr, options, 0, ctx);
451 if (!strcmp(arg, "list-opts")) 454 if (!strcmp(arg, "list-opts"))
452 return PARSE_OPT_LIST_OPTS; 455 return PARSE_OPT_LIST_OPTS;
453 if (!strcmp(arg, "list-cmds")) 456 if (!strcmp(arg, "list-cmds"))
@@ -642,9 +645,69 @@ static void print_option_help(const struct option *opts, int full)
642 fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help); 645 fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help);
643} 646}
644 647
648static int option__cmp(const void *va, const void *vb)
649{
650 const struct option *a = va, *b = vb;
651 int sa = tolower(a->short_name), sb = tolower(b->short_name), ret;
652
653 if (sa == 0)
654 sa = 'z' + 1;
655 if (sb == 0)
656 sb = 'z' + 1;
657
658 ret = sa - sb;
659
660 if (ret == 0) {
661 const char *la = a->long_name ?: "",
662 *lb = b->long_name ?: "";
663 ret = strcmp(la, lb);
664 }
665
666 return ret;
667}
668
669static struct option *options__order(const struct option *opts)
670{
671 int nr_opts = 0;
672 const struct option *o = opts;
673 struct option *ordered;
674
675 for (o = opts; o->type != OPTION_END; o++)
676 ++nr_opts;
677
678 ordered = memdup(opts, sizeof(*o) * (nr_opts + 1));
679 if (ordered == NULL)
680 goto out;
681
682 qsort(ordered, nr_opts, sizeof(*o), option__cmp);
683out:
684 return ordered;
685}
686
687static bool option__in_argv(const struct option *opt, const struct parse_opt_ctx_t *ctx)
688{
689 int i;
690
691 for (i = 1; i < ctx->argc; ++i) {
692 const char *arg = ctx->argv[i];
693
694 if (arg[0] != '-')
695 continue;
696
697 if (arg[1] == opt->short_name ||
698 (arg[1] == '-' && opt->long_name && strcmp(opt->long_name, arg + 2) == 0))
699 return true;
700 }
701
702 return false;
703}
704
645int usage_with_options_internal(const char * const *usagestr, 705int usage_with_options_internal(const char * const *usagestr,
646 const struct option *opts, int full) 706 const struct option *opts, int full,
707 struct parse_opt_ctx_t *ctx)
647{ 708{
709 struct option *ordered;
710
648 if (!usagestr) 711 if (!usagestr)
649 return PARSE_OPT_HELP; 712 return PARSE_OPT_HELP;
650 713
@@ -661,11 +724,20 @@ int usage_with_options_internal(const char * const *usagestr,
661 if (opts->type != OPTION_GROUP) 724 if (opts->type != OPTION_GROUP)
662 fputc('\n', stderr); 725 fputc('\n', stderr);
663 726
664 for ( ; opts->type != OPTION_END; opts++) 727 ordered = options__order(opts);
728 if (ordered)
729 opts = ordered;
730
731 for ( ; opts->type != OPTION_END; opts++) {
732 if (ctx && ctx->argc > 1 && !option__in_argv(opts, ctx))
733 continue;
665 print_option_help(opts, full); 734 print_option_help(opts, full);
735 }
666 736
667 fputc('\n', stderr); 737 fputc('\n', stderr);
668 738
739 free(ordered);
740
669 return PARSE_OPT_HELP; 741 return PARSE_OPT_HELP;
670} 742}
671 743
@@ -673,7 +745,7 @@ void usage_with_options(const char * const *usagestr,
673 const struct option *opts) 745 const struct option *opts)
674{ 746{
675 exit_browser(false); 747 exit_browser(false);
676 usage_with_options_internal(usagestr, opts, 0); 748 usage_with_options_internal(usagestr, opts, 0, NULL);
677 exit(129); 749 exit(129);
678} 750}
679 751