diff options
Diffstat (limited to 'tools/perf/util/parse-options.c')
| -rw-r--r-- | tools/perf/util/parse-options.c | 218 | 
1 files changed, 130 insertions, 88 deletions
| diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c index 2bc9e70df7e2..31f404a032a9 100644 --- a/tools/perf/util/parse-options.c +++ b/tools/perf/util/parse-options.c @@ -339,10 +339,10 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,  		if (arg[1] != '-') {  			ctx->opt = arg + 1;  			if (internal_help && *ctx->opt == 'h') -				return parse_options_usage(usagestr, options); +				return usage_with_options_internal(usagestr, options, 0);  			switch (parse_short_opt(ctx, options)) {  			case -1: -				return parse_options_usage(usagestr, options); +				return parse_options_usage(usagestr, options, arg + 1, 1);  			case -2:  				goto unknown;  			default: @@ -352,10 +352,11 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,  				check_typos(arg + 1, options);  			while (ctx->opt) {  				if (internal_help && *ctx->opt == 'h') -					return parse_options_usage(usagestr, options); +					return usage_with_options_internal(usagestr, options, 0); +				arg = ctx->opt;  				switch (parse_short_opt(ctx, options)) {  				case -1: -					return parse_options_usage(usagestr, options); +					return parse_options_usage(usagestr, options, arg, 1);  				case -2:  					/* fake a short option thing to hide the fact that we may have  					 * started to parse aggregated stuff @@ -383,12 +384,12 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,  		if (internal_help && !strcmp(arg + 2, "help-all"))  			return usage_with_options_internal(usagestr, options, 1);  		if (internal_help && !strcmp(arg + 2, "help")) -			return parse_options_usage(usagestr, options); +			return usage_with_options_internal(usagestr, options, 0);  		if (!strcmp(arg + 2, "list-opts"))  			return PARSE_OPT_LIST;  		switch (parse_long_opt(ctx, arg + 2, options)) {  		case -1: -			return parse_options_usage(usagestr, options); +			return parse_options_usage(usagestr, options, arg + 2, 0);  		case -2:  			goto unknown;  		default: @@ -445,6 +446,89 @@ int parse_options(int argc, const char **argv, const struct option *options,  #define USAGE_OPTS_WIDTH 24  #define USAGE_GAP         2 +static void print_option_help(const struct option *opts, int full) +{ +	size_t pos; +	int pad; + +	if (opts->type == OPTION_GROUP) { +		fputc('\n', stderr); +		if (*opts->help) +			fprintf(stderr, "%s\n", opts->help); +		return; +	} +	if (!full && (opts->flags & PARSE_OPT_HIDDEN)) +		return; + +	pos = fprintf(stderr, "    "); +	if (opts->short_name) +		pos += fprintf(stderr, "-%c", opts->short_name); +	else +		pos += fprintf(stderr, "    "); + +	if (opts->long_name && opts->short_name) +		pos += fprintf(stderr, ", "); +	if (opts->long_name) +		pos += fprintf(stderr, "--%s", opts->long_name); + +	switch (opts->type) { +	case OPTION_ARGUMENT: +		break; +	case OPTION_LONG: +	case OPTION_U64: +	case OPTION_INTEGER: +	case OPTION_UINTEGER: +		if (opts->flags & PARSE_OPT_OPTARG) +			if (opts->long_name) +				pos += fprintf(stderr, "[=<n>]"); +			else +				pos += fprintf(stderr, "[<n>]"); +		else +			pos += fprintf(stderr, " <n>"); +		break; +	case OPTION_CALLBACK: +		if (opts->flags & PARSE_OPT_NOARG) +			break; +		/* FALLTHROUGH */ +	case OPTION_STRING: +		if (opts->argh) { +			if (opts->flags & PARSE_OPT_OPTARG) +				if (opts->long_name) +					pos += fprintf(stderr, "[=<%s>]", opts->argh); +				else +					pos += fprintf(stderr, "[<%s>]", opts->argh); +			else +				pos += fprintf(stderr, " <%s>", opts->argh); +		} else { +			if (opts->flags & PARSE_OPT_OPTARG) +				if (opts->long_name) +					pos += fprintf(stderr, "[=...]"); +				else +					pos += fprintf(stderr, "[...]"); +			else +				pos += fprintf(stderr, " ..."); +		} +		break; +	default: /* OPTION_{BIT,BOOLEAN,SET_UINT,SET_PTR} */ +	case OPTION_END: +	case OPTION_GROUP: +	case OPTION_BIT: +	case OPTION_BOOLEAN: +	case OPTION_INCR: +	case OPTION_SET_UINT: +	case OPTION_SET_PTR: +		break; +	} + +	if (pos <= USAGE_OPTS_WIDTH) +		pad = USAGE_OPTS_WIDTH - pos; +	else { +		fputc('\n', stderr); +		pad = USAGE_OPTS_WIDTH; +	} +	fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help); +} +  int usage_with_options_internal(const char * const *usagestr,  				const struct option *opts, int full)  { @@ -464,87 +548,9 @@ int usage_with_options_internal(const char * const *usagestr,  	if (opts->type != OPTION_GROUP)  		fputc('\n', stderr); -	for (; opts->type != OPTION_END; opts++) { -		size_t pos; -		int pad; - -		if (opts->type == OPTION_GROUP) { -			fputc('\n', stderr); -			if (*opts->help) -				fprintf(stderr, "%s\n", opts->help); -			continue; -		} -		if (!full && (opts->flags & PARSE_OPT_HIDDEN)) -			continue; - -		pos = fprintf(stderr, "    "); -		if (opts->short_name) -			pos += fprintf(stderr, "-%c", opts->short_name); -		else -			pos += fprintf(stderr, "    "); - -		if (opts->long_name && opts->short_name) -			pos += fprintf(stderr, ", "); -		if (opts->long_name) -			pos += fprintf(stderr, "--%s", opts->long_name); - -		switch (opts->type) { -		case OPTION_ARGUMENT: -			break; -		case OPTION_LONG: -		case OPTION_U64: -		case OPTION_INTEGER: -		case OPTION_UINTEGER: -			if (opts->flags & PARSE_OPT_OPTARG) -				if (opts->long_name) -					pos += fprintf(stderr, "[=<n>]"); -				else -					pos += fprintf(stderr, "[<n>]"); -			else -				pos += fprintf(stderr, " <n>"); -			break; -		case OPTION_CALLBACK: -			if (opts->flags & PARSE_OPT_NOARG) -				break; -			/* FALLTHROUGH */ -		case OPTION_STRING: -			if (opts->argh) { -				if (opts->flags & PARSE_OPT_OPTARG) -					if (opts->long_name) -						pos += fprintf(stderr, "[=<%s>]", opts->argh); -					else -						pos += fprintf(stderr, "[<%s>]", opts->argh); -				else -					pos += fprintf(stderr, " <%s>", opts->argh); -			} else { -				if (opts->flags & PARSE_OPT_OPTARG) -					if (opts->long_name) -						pos += fprintf(stderr, "[=...]"); -					else -						pos += fprintf(stderr, "[...]"); -				else -					pos += fprintf(stderr, " ..."); -			} -			break; -		default: /* OPTION_{BIT,BOOLEAN,SET_UINT,SET_PTR} */ -		case OPTION_END: -		case OPTION_GROUP: -		case OPTION_BIT: -		case OPTION_BOOLEAN: -		case OPTION_INCR: -		case OPTION_SET_UINT: -		case OPTION_SET_PTR: -			break; -		} +	for (  ; opts->type != OPTION_END; opts++) +		print_option_help(opts, full); -		if (pos <= USAGE_OPTS_WIDTH) -			pad = USAGE_OPTS_WIDTH - pos; -		else { -			fputc('\n', stderr); -			pad = USAGE_OPTS_WIDTH; -		} -		fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help); -	}  	fputc('\n', stderr);  	return PARSE_OPT_HELP; @@ -559,9 +565,45 @@ void usage_with_options(const char * const *usagestr,  }  int parse_options_usage(const char * const *usagestr, -			const struct option *opts) +			const struct option *opts, +			const char *optstr, bool short_opt)  { -	return usage_with_options_internal(usagestr, opts, 0); +	if (!usagestr) +		goto opt; + +	fprintf(stderr, "\n usage: %s\n", *usagestr++); +	while (*usagestr && **usagestr) +		fprintf(stderr, "    or: %s\n", *usagestr++); +	while (*usagestr) { +		fprintf(stderr, "%s%s\n", +				**usagestr ? "    " : "", +				*usagestr); +		usagestr++; +	} +	fputc('\n', stderr); + +opt: +	for (  ; opts->type != OPTION_END; opts++) { +		if (short_opt) { +			if (opts->short_name == *optstr) +				break; +			continue; +		} + +		if (opts->long_name == NULL) +			continue; + +		if (!prefixcmp(optstr, opts->long_name)) +			break; +		if (!prefixcmp(optstr, "no-") && +		    !prefixcmp(optstr + 3, opts->long_name)) +			break; +	} + +	if (opts->type != OPTION_END) +		print_option_help(opts, 0); + +	return PARSE_OPT_HELP;  } |