diff options
-rw-r--r-- | tools/perf/util/parse-options.c | 59 | ||||
-rw-r--r-- | tools/perf/util/parse-options.h | 2 |
2 files changed, 50 insertions, 11 deletions
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c index b6016101b40b..f62dee7bd924 100644 --- a/tools/perf/util/parse-options.c +++ b/tools/perf/util/parse-options.c | |||
@@ -45,6 +45,23 @@ static int get_value(struct parse_opt_ctx_t *p, | |||
45 | if (opt->flags & PARSE_OPT_DISABLED) | 45 | if (opt->flags & PARSE_OPT_DISABLED) |
46 | return opterror(opt, "is not usable", flags); | 46 | return opterror(opt, "is not usable", flags); |
47 | 47 | ||
48 | if (opt->flags & PARSE_OPT_EXCLUSIVE) { | ||
49 | if (p->excl_opt) { | ||
50 | char msg[128]; | ||
51 | |||
52 | if (((flags & OPT_SHORT) && p->excl_opt->short_name) || | ||
53 | p->excl_opt->long_name == NULL) { | ||
54 | scnprintf(msg, sizeof(msg), "cannot be used with switch `%c'", | ||
55 | p->excl_opt->short_name); | ||
56 | } else { | ||
57 | scnprintf(msg, sizeof(msg), "cannot be used with %s", | ||
58 | p->excl_opt->long_name); | ||
59 | } | ||
60 | opterror(opt, msg, flags); | ||
61 | return -3; | ||
62 | } | ||
63 | p->excl_opt = opt; | ||
64 | } | ||
48 | if (!(flags & OPT_SHORT) && p->opt) { | 65 | if (!(flags & OPT_SHORT) && p->opt) { |
49 | switch (opt->type) { | 66 | switch (opt->type) { |
50 | case OPTION_CALLBACK: | 67 | case OPTION_CALLBACK: |
@@ -345,13 +362,14 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, | |||
345 | const char * const usagestr[]) | 362 | const char * const usagestr[]) |
346 | { | 363 | { |
347 | int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP); | 364 | int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP); |
365 | int excl_short_opt = 1; | ||
366 | const char *arg; | ||
348 | 367 | ||
349 | /* we must reset ->opt, unknown short option leave it dangling */ | 368 | /* we must reset ->opt, unknown short option leave it dangling */ |
350 | ctx->opt = NULL; | 369 | ctx->opt = NULL; |
351 | 370 | ||
352 | for (; ctx->argc; ctx->argc--, ctx->argv++) { | 371 | for (; ctx->argc; ctx->argc--, ctx->argv++) { |
353 | const char *arg = ctx->argv[0]; | 372 | arg = ctx->argv[0]; |
354 | |||
355 | if (*arg != '-' || !arg[1]) { | 373 | if (*arg != '-' || !arg[1]) { |
356 | if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION) | 374 | if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION) |
357 | break; | 375 | break; |
@@ -360,19 +378,21 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, | |||
360 | } | 378 | } |
361 | 379 | ||
362 | if (arg[1] != '-') { | 380 | if (arg[1] != '-') { |
363 | ctx->opt = arg + 1; | 381 | ctx->opt = ++arg; |
364 | if (internal_help && *ctx->opt == 'h') | 382 | if (internal_help && *ctx->opt == 'h') |
365 | return usage_with_options_internal(usagestr, options, 0); | 383 | return usage_with_options_internal(usagestr, options, 0); |
366 | switch (parse_short_opt(ctx, options)) { | 384 | switch (parse_short_opt(ctx, options)) { |
367 | case -1: | 385 | case -1: |
368 | return parse_options_usage(usagestr, options, arg + 1, 1); | 386 | return parse_options_usage(usagestr, options, arg, 1); |
369 | case -2: | 387 | case -2: |
370 | goto unknown; | 388 | goto unknown; |
389 | case -3: | ||
390 | goto exclusive; | ||
371 | default: | 391 | default: |
372 | break; | 392 | break; |
373 | } | 393 | } |
374 | if (ctx->opt) | 394 | if (ctx->opt) |
375 | check_typos(arg + 1, options); | 395 | check_typos(arg, options); |
376 | while (ctx->opt) { | 396 | while (ctx->opt) { |
377 | if (internal_help && *ctx->opt == 'h') | 397 | if (internal_help && *ctx->opt == 'h') |
378 | return usage_with_options_internal(usagestr, options, 0); | 398 | return usage_with_options_internal(usagestr, options, 0); |
@@ -389,6 +409,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, | |||
389 | ctx->argv[0] = strdup(ctx->opt - 1); | 409 | ctx->argv[0] = strdup(ctx->opt - 1); |
390 | *(char *)ctx->argv[0] = '-'; | 410 | *(char *)ctx->argv[0] = '-'; |
391 | goto unknown; | 411 | goto unknown; |
412 | case -3: | ||
413 | goto exclusive; | ||
392 | default: | 414 | default: |
393 | break; | 415 | break; |
394 | } | 416 | } |
@@ -404,19 +426,23 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, | |||
404 | break; | 426 | break; |
405 | } | 427 | } |
406 | 428 | ||
407 | if (internal_help && !strcmp(arg + 2, "help-all")) | 429 | arg += 2; |
430 | if (internal_help && !strcmp(arg, "help-all")) | ||
408 | return usage_with_options_internal(usagestr, options, 1); | 431 | return usage_with_options_internal(usagestr, options, 1); |
409 | if (internal_help && !strcmp(arg + 2, "help")) | 432 | if (internal_help && !strcmp(arg, "help")) |
410 | return usage_with_options_internal(usagestr, options, 0); | 433 | return usage_with_options_internal(usagestr, options, 0); |
411 | if (!strcmp(arg + 2, "list-opts")) | 434 | if (!strcmp(arg, "list-opts")) |
412 | return PARSE_OPT_LIST_OPTS; | 435 | return PARSE_OPT_LIST_OPTS; |
413 | if (!strcmp(arg + 2, "list-cmds")) | 436 | if (!strcmp(arg, "list-cmds")) |
414 | return PARSE_OPT_LIST_SUBCMDS; | 437 | return PARSE_OPT_LIST_SUBCMDS; |
415 | switch (parse_long_opt(ctx, arg + 2, options)) { | 438 | switch (parse_long_opt(ctx, arg, options)) { |
416 | case -1: | 439 | case -1: |
417 | return parse_options_usage(usagestr, options, arg + 2, 0); | 440 | return parse_options_usage(usagestr, options, arg, 0); |
418 | case -2: | 441 | case -2: |
419 | goto unknown; | 442 | goto unknown; |
443 | case -3: | ||
444 | excl_short_opt = 0; | ||
445 | goto exclusive; | ||
420 | default: | 446 | default: |
421 | break; | 447 | break; |
422 | } | 448 | } |
@@ -428,6 +454,17 @@ unknown: | |||
428 | ctx->opt = NULL; | 454 | ctx->opt = NULL; |
429 | } | 455 | } |
430 | return PARSE_OPT_DONE; | 456 | return PARSE_OPT_DONE; |
457 | |||
458 | exclusive: | ||
459 | parse_options_usage(usagestr, options, arg, excl_short_opt); | ||
460 | if ((excl_short_opt && ctx->excl_opt->short_name) || | ||
461 | ctx->excl_opt->long_name == NULL) { | ||
462 | char opt = ctx->excl_opt->short_name; | ||
463 | parse_options_usage(NULL, options, &opt, 1); | ||
464 | } else { | ||
465 | parse_options_usage(NULL, options, ctx->excl_opt->long_name, 0); | ||
466 | } | ||
467 | return PARSE_OPT_HELP; | ||
431 | } | 468 | } |
432 | 469 | ||
433 | int parse_options_end(struct parse_opt_ctx_t *ctx) | 470 | int parse_options_end(struct parse_opt_ctx_t *ctx) |
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h index b7c80dbc7627..97b153fb4999 100644 --- a/tools/perf/util/parse-options.h +++ b/tools/perf/util/parse-options.h | |||
@@ -39,6 +39,7 @@ enum parse_opt_option_flags { | |||
39 | PARSE_OPT_HIDDEN = 8, | 39 | PARSE_OPT_HIDDEN = 8, |
40 | PARSE_OPT_LASTARG_DEFAULT = 16, | 40 | PARSE_OPT_LASTARG_DEFAULT = 16, |
41 | PARSE_OPT_DISABLED = 32, | 41 | PARSE_OPT_DISABLED = 32, |
42 | PARSE_OPT_EXCLUSIVE = 64, | ||
42 | }; | 43 | }; |
43 | 44 | ||
44 | struct option; | 45 | struct option; |
@@ -174,6 +175,7 @@ struct parse_opt_ctx_t { | |||
174 | const char **out; | 175 | const char **out; |
175 | int argc, cpidx; | 176 | int argc, cpidx; |
176 | const char *opt; | 177 | const char *opt; |
178 | const struct option *excl_opt; | ||
177 | int flags; | 179 | int flags; |
178 | }; | 180 | }; |
179 | 181 | ||