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; +		} +	} +}  |