diff options
| author | Ingo Molnar <mingo@kernel.org> | 2015-10-25 09:40:31 +0100 | 
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2015-10-25 09:40:31 +0100 | 
| commit | 4341801873e23bbecee76dabb7c111e3693b900f (patch) | |
| tree | 473e96f38af8c9e5a6bfd99ef20c021584168343 /tools | |
| parent | 80fcd45ee05b4ef05e61d37a5ffb70a67095a9f6 (diff) | |
| parent | 161d9041782b86c5493481566539bfc058ceeaff (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')
| -rw-r--r-- | tools/perf/util/parse-options.c | 90 | 
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 @@  #include "parse-options.h"  #include "cache.h"  #include "header.h" +#include <linux/string.h>  #define OPT_SHORT 1  #define OPT_UNSET 2 @@ -372,7 +373,8 @@ void parse_options_start(struct parse_opt_ctx_t *ctx,  }  static int usage_with_options_internal(const char * const *, -				       const struct option *, int); +				       const struct option *, int, +				       struct parse_opt_ctx_t *);  int parse_options_step(struct parse_opt_ctx_t *ctx,  		       const struct option *options, @@ -396,8 +398,9 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,  		if (arg[1] != '-') {  			ctx->opt = ++arg; -			if (internal_help && *ctx->opt == 'h') -				return usage_with_options_internal(usagestr, options, 0); +			if (internal_help && *ctx->opt == 'h') { +				return usage_with_options_internal(usagestr, options, 0, ctx); +			}  			switch (parse_short_opt(ctx, options)) {  			case -1:  				return parse_options_usage(usagestr, options, arg, 1); @@ -412,7 +415,7 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,  				check_typos(arg, options);  			while (ctx->opt) {  				if (internal_help && *ctx->opt == 'h') -					return usage_with_options_internal(usagestr, options, 0); +					return usage_with_options_internal(usagestr, options, 0, ctx);  				arg = ctx->opt;  				switch (parse_short_opt(ctx, options)) {  				case -1: @@ -445,9 +448,9 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,  		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, ctx);  		if (internal_help && !strcmp(arg, "help")) -			return usage_with_options_internal(usagestr, options, 0); +			return usage_with_options_internal(usagestr, options, 0, ctx);  		if (!strcmp(arg, "list-opts"))  			return PARSE_OPT_LIST_OPTS;  		if (!strcmp(arg, "list-cmds")) @@ -642,9 +645,69 @@ static void print_option_help(const struct option *opts, int full)  	fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help);  } +static int option__cmp(const void *va, const void *vb) +{ +	const struct option *a = va, *b = vb; +	int sa = tolower(a->short_name), sb = tolower(b->short_name), ret; + +	if (sa == 0) +		sa = 'z' + 1; +	if (sb == 0) +		sb = 'z' + 1; + +	ret = sa - sb; + +	if (ret == 0) { +		const char *la = a->long_name ?: "", +			   *lb = b->long_name ?: ""; +		ret = strcmp(la, lb); +	} + +	return ret; +} + +static struct option *options__order(const struct option *opts) +{ +	int nr_opts = 0; +	const struct option *o = opts; +	struct option *ordered; + +	for (o = opts; o->type != OPTION_END; o++) +		++nr_opts; + +	ordered = memdup(opts, sizeof(*o) * (nr_opts + 1)); +	if (ordered == NULL) +		goto out; + +	qsort(ordered, nr_opts, sizeof(*o), option__cmp); +out: +	return ordered; +} + +static bool option__in_argv(const struct option *opt, const struct parse_opt_ctx_t *ctx) +{ +	int i; + +	for (i = 1; i < ctx->argc; ++i) { +		const char *arg = ctx->argv[i]; + +		if (arg[0] != '-') +			continue; + +		if (arg[1] == opt->short_name || +		    (arg[1] == '-' && opt->long_name && strcmp(opt->long_name, arg + 2) == 0)) +			return true; +	} + +	return false; +} +  int usage_with_options_internal(const char * const *usagestr, -				const struct option *opts, int full) +				const struct option *opts, int full, +				struct parse_opt_ctx_t *ctx)  { +	struct option *ordered; +  	if (!usagestr)  		return PARSE_OPT_HELP; @@ -661,11 +724,20 @@ int usage_with_options_internal(const char * const *usagestr,  	if (opts->type != OPTION_GROUP)  		fputc('\n', stderr); -	for (  ; opts->type != OPTION_END; opts++) +	ordered = options__order(opts); +	if (ordered) +		opts = ordered; + +	for (  ; opts->type != OPTION_END; opts++) { +		if (ctx && ctx->argc > 1 && !option__in_argv(opts, ctx)) +			continue;  		print_option_help(opts, full); +	}  	fputc('\n', stderr); +	free(ordered); +  	return PARSE_OPT_HELP;  } @@ -673,7 +745,7 @@ void usage_with_options(const char * const *usagestr,  			const struct option *opts)  {  	exit_browser(false); -	usage_with_options_internal(usagestr, opts, 0); +	usage_with_options_internal(usagestr, opts, 0, NULL);  	exit(129);  } | 
