提交 ac697625 编写于 作者: N Namhyung Kim 提交者: Arnaldo Carvalho de Melo

perf tools: Show single option when failed to parse

Current option parser outputs whole option help string when it failed to
parse an option.  However this is not good for user if the command has
many option, she might feel hard which one is related easily.

Fix it by just showing the help message of the given option only.
Signed-off-by: NNamhyung Kim <namhyung@kernel.org>
Requested-by: NIngo Molnar <mingo@kernel.org>
Acked-by: NIngo Molnar <mingo@kernel.org>
Reviewed-by: NIngo Molnar <mingo@kernel.org>
Enthusiastically-Supported-by: NIngo Molnar <mingo@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1383291195-24386-2-git-send-email-namhyung@kernel.orgSigned-off-by: NArnaldo Carvalho de Melo <acme@redhat.com>
上级 42d88910
......@@ -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);
for ( ; opts->type != OPTION_END; opts++)
print_option_help(opts, full);
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);
}
fputc('\n', stderr);
return PARSE_OPT_HELP;
......@@ -559,9 +565,44 @@ 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)
return PARSE_OPT_HELP;
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);
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;
}
......
......@@ -158,7 +158,9 @@ struct parse_opt_ctx_t {
};
extern int parse_options_usage(const char * const *usagestr,
const struct option *opts);
const struct option *opts,
const char *optstr,
bool short_opt);
extern void parse_options_start(struct parse_opt_ctx_t *ctx,
int argc, const char **argv, int flags);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册