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, | |||
| 42 | return opterror(opt, "takes no value", flags); | 42 | return opterror(opt, "takes no value", flags); |
| 43 | if (unset && (opt->flags & PARSE_OPT_NONEG)) | 43 | if (unset && (opt->flags & PARSE_OPT_NONEG)) |
| 44 | return opterror(opt, "isn't available", flags); | 44 | return opterror(opt, "isn't available", flags); |
| 45 | 45 | if (opt->flags & PARSE_OPT_DISABLED) | |
| 46 | return opterror(opt, "is not usable", flags); | ||
| 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 | } | ||
| 46 | if (!(flags & OPT_SHORT) && p->opt) { | 65 | if (!(flags & OPT_SHORT) && p->opt) { |
| 47 | switch (opt->type) { | 66 | switch (opt->type) { |
| 48 | case OPTION_CALLBACK: | 67 | case OPTION_CALLBACK: |
| @@ -343,13 +362,14 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, | |||
| 343 | const char * const usagestr[]) | 362 | const char * const usagestr[]) |
| 344 | { | 363 | { |
| 345 | 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; | ||
| 346 | 367 | ||
| 347 | /* we must reset ->opt, unknown short option leave it dangling */ | 368 | /* we must reset ->opt, unknown short option leave it dangling */ |
| 348 | ctx->opt = NULL; | 369 | ctx->opt = NULL; |
| 349 | 370 | ||
| 350 | for (; ctx->argc; ctx->argc--, ctx->argv++) { | 371 | for (; ctx->argc; ctx->argc--, ctx->argv++) { |
| 351 | const char *arg = ctx->argv[0]; | 372 | arg = ctx->argv[0]; |
| 352 | |||
| 353 | if (*arg != '-' || !arg[1]) { | 373 | if (*arg != '-' || !arg[1]) { |
| 354 | if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION) | 374 | if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION) |
| 355 | break; | 375 | break; |
| @@ -358,19 +378,21 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, | |||
| 358 | } | 378 | } |
| 359 | 379 | ||
| 360 | if (arg[1] != '-') { | 380 | if (arg[1] != '-') { |
| 361 | ctx->opt = arg + 1; | 381 | ctx->opt = ++arg; |
| 362 | if (internal_help && *ctx->opt == 'h') | 382 | if (internal_help && *ctx->opt == 'h') |
| 363 | return usage_with_options_internal(usagestr, options, 0); | 383 | return usage_with_options_internal(usagestr, options, 0); |
| 364 | switch (parse_short_opt(ctx, options)) { | 384 | switch (parse_short_opt(ctx, options)) { |
| 365 | case -1: | 385 | case -1: |
| 366 | return parse_options_usage(usagestr, options, arg + 1, 1); | 386 | return parse_options_usage(usagestr, options, arg, 1); |
| 367 | case -2: | 387 | case -2: |
| 368 | goto unknown; | 388 | goto unknown; |
| 389 | case -3: | ||
| 390 | goto exclusive; | ||
| 369 | default: | 391 | default: |
| 370 | break; | 392 | break; |
| 371 | } | 393 | } |
| 372 | if (ctx->opt) | 394 | if (ctx->opt) |
| 373 | check_typos(arg + 1, options); | 395 | check_typos(arg, options); |
| 374 | while (ctx->opt) { | 396 | while (ctx->opt) { |
| 375 | if (internal_help && *ctx->opt == 'h') | 397 | if (internal_help && *ctx->opt == 'h') |
| 376 | return usage_with_options_internal(usagestr, options, 0); | 398 | return usage_with_options_internal(usagestr, options, 0); |
| @@ -387,6 +409,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, | |||
| 387 | ctx->argv[0] = strdup(ctx->opt - 1); | 409 | ctx->argv[0] = strdup(ctx->opt - 1); |
| 388 | *(char *)ctx->argv[0] = '-'; | 410 | *(char *)ctx->argv[0] = '-'; |
| 389 | goto unknown; | 411 | goto unknown; |
| 412 | case -3: | ||
| 413 | goto exclusive; | ||
| 390 | default: | 414 | default: |
| 391 | break; | 415 | break; |
| 392 | } | 416 | } |
| @@ -402,19 +426,23 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, | |||
| 402 | break; | 426 | break; |
| 403 | } | 427 | } |
| 404 | 428 | ||
| 405 | if (internal_help && !strcmp(arg + 2, "help-all")) | 429 | arg += 2; |
| 430 | if (internal_help && !strcmp(arg, "help-all")) | ||
| 406 | return usage_with_options_internal(usagestr, options, 1); | 431 | return usage_with_options_internal(usagestr, options, 1); |
| 407 | if (internal_help && !strcmp(arg + 2, "help")) | 432 | if (internal_help && !strcmp(arg, "help")) |
| 408 | return usage_with_options_internal(usagestr, options, 0); | 433 | return usage_with_options_internal(usagestr, options, 0); |
| 409 | if (!strcmp(arg + 2, "list-opts")) | 434 | if (!strcmp(arg, "list-opts")) |
| 410 | return PARSE_OPT_LIST_OPTS; | 435 | return PARSE_OPT_LIST_OPTS; |
| 411 | if (!strcmp(arg + 2, "list-cmds")) | 436 | if (!strcmp(arg, "list-cmds")) |
| 412 | return PARSE_OPT_LIST_SUBCMDS; | 437 | return PARSE_OPT_LIST_SUBCMDS; |
| 413 | switch (parse_long_opt(ctx, arg + 2, options)) { | 438 | switch (parse_long_opt(ctx, arg, options)) { |
| 414 | case -1: | 439 | case -1: |
| 415 | return parse_options_usage(usagestr, options, arg + 2, 0); | 440 | return parse_options_usage(usagestr, options, arg, 0); |
| 416 | case -2: | 441 | case -2: |
| 417 | goto unknown; | 442 | goto unknown; |
| 443 | case -3: | ||
| 444 | excl_short_opt = 0; | ||
| 445 | goto exclusive; | ||
| 418 | default: | 446 | default: |
| 419 | break; | 447 | break; |
| 420 | } | 448 | } |
| @@ -426,6 +454,17 @@ unknown: | |||
| 426 | ctx->opt = NULL; | 454 | ctx->opt = NULL; |
| 427 | } | 455 | } |
| 428 | 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; | ||
| 429 | } | 468 | } |
| 430 | 469 | ||
| 431 | int parse_options_end(struct parse_opt_ctx_t *ctx) | 470 | 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) | |||
| 509 | } | 548 | } |
| 510 | if (!full && (opts->flags & PARSE_OPT_HIDDEN)) | 549 | if (!full && (opts->flags & PARSE_OPT_HIDDEN)) |
| 511 | return; | 550 | return; |
| 551 | if (opts->flags & PARSE_OPT_DISABLED) | ||
| 552 | return; | ||
| 512 | 553 | ||
| 513 | pos = fprintf(stderr, " "); | 554 | pos = fprintf(stderr, " "); |
| 514 | if (opts->short_name) | 555 | if (opts->short_name) |
| @@ -679,3 +720,16 @@ int parse_opt_verbosity_cb(const struct option *opt, | |||
| 679 | } | 720 | } |
| 680 | return 0; | 721 | return 0; |
| 681 | } | 722 | } |
| 723 | |||
| 724 | void set_option_flag(struct option *opts, int shortopt, const char *longopt, | ||
| 725 | int flag) | ||
| 726 | { | ||
| 727 | for (; opts->type != OPTION_END; opts++) { | ||
| 728 | if ((shortopt && opts->short_name == shortopt) || | ||
| 729 | (opts->long_name && longopt && | ||
| 730 | !strcmp(opts->long_name, longopt))) { | ||
| 731 | opts->flags |= flag; | ||
| 732 | break; | ||
| 733 | } | ||
| 734 | } | ||
| 735 | } | ||
