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, | |||
| 339 | if (arg[1] != '-') { | 339 | if (arg[1] != '-') { |
| 340 | ctx->opt = arg + 1; | 340 | ctx->opt = arg + 1; |
| 341 | if (internal_help && *ctx->opt == 'h') | 341 | if (internal_help && *ctx->opt == 'h') |
| 342 | return parse_options_usage(usagestr, options); | 342 | return usage_with_options_internal(usagestr, options, 0); |
| 343 | switch (parse_short_opt(ctx, options)) { | 343 | switch (parse_short_opt(ctx, options)) { |
| 344 | case -1: | 344 | case -1: |
| 345 | return parse_options_usage(usagestr, options); | 345 | return parse_options_usage(usagestr, options, arg + 1, 1); |
| 346 | case -2: | 346 | case -2: |
| 347 | goto unknown; | 347 | goto unknown; |
| 348 | default: | 348 | default: |
| @@ -352,10 +352,11 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, | |||
| 352 | check_typos(arg + 1, options); | 352 | check_typos(arg + 1, options); |
| 353 | while (ctx->opt) { | 353 | while (ctx->opt) { |
| 354 | if (internal_help && *ctx->opt == 'h') | 354 | if (internal_help && *ctx->opt == 'h') |
| 355 | return parse_options_usage(usagestr, options); | 355 | return usage_with_options_internal(usagestr, options, 0); |
| 356 | arg = ctx->opt; | ||
| 356 | switch (parse_short_opt(ctx, options)) { | 357 | switch (parse_short_opt(ctx, options)) { |
| 357 | case -1: | 358 | case -1: |
| 358 | return parse_options_usage(usagestr, options); | 359 | return parse_options_usage(usagestr, options, arg, 1); |
| 359 | case -2: | 360 | case -2: |
| 360 | /* fake a short option thing to hide the fact that we may have | 361 | /* fake a short option thing to hide the fact that we may have |
| 361 | * started to parse aggregated stuff | 362 | * started to parse aggregated stuff |
| @@ -383,12 +384,12 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, | |||
| 383 | if (internal_help && !strcmp(arg + 2, "help-all")) | 384 | if (internal_help && !strcmp(arg + 2, "help-all")) |
| 384 | return usage_with_options_internal(usagestr, options, 1); | 385 | return usage_with_options_internal(usagestr, options, 1); |
| 385 | if (internal_help && !strcmp(arg + 2, "help")) | 386 | if (internal_help && !strcmp(arg + 2, "help")) |
| 386 | return parse_options_usage(usagestr, options); | 387 | return usage_with_options_internal(usagestr, options, 0); |
| 387 | if (!strcmp(arg + 2, "list-opts")) | 388 | if (!strcmp(arg + 2, "list-opts")) |
| 388 | return PARSE_OPT_LIST; | 389 | return PARSE_OPT_LIST; |
| 389 | switch (parse_long_opt(ctx, arg + 2, options)) { | 390 | switch (parse_long_opt(ctx, arg + 2, options)) { |
| 390 | case -1: | 391 | case -1: |
| 391 | return parse_options_usage(usagestr, options); | 392 | return parse_options_usage(usagestr, options, arg + 2, 0); |
| 392 | case -2: | 393 | case -2: |
| 393 | goto unknown; | 394 | goto unknown; |
| 394 | default: | 395 | default: |
| @@ -445,6 +446,89 @@ int parse_options(int argc, const char **argv, const struct option *options, | |||
| 445 | #define USAGE_OPTS_WIDTH 24 | 446 | #define USAGE_OPTS_WIDTH 24 |
| 446 | #define USAGE_GAP 2 | 447 | #define USAGE_GAP 2 |
| 447 | 448 | ||
| 449 | static void print_option_help(const struct option *opts, int full) | ||
| 450 | { | ||
| 451 | size_t pos; | ||
| 452 | int pad; | ||
| 453 | |||
| 454 | if (opts->type == OPTION_GROUP) { | ||
| 455 | fputc('\n', stderr); | ||
| 456 | if (*opts->help) | ||
| 457 | fprintf(stderr, "%s\n", opts->help); | ||
| 458 | return; | ||
| 459 | } | ||
| 460 | if (!full && (opts->flags & PARSE_OPT_HIDDEN)) | ||
| 461 | return; | ||
| 462 | |||
| 463 | pos = fprintf(stderr, " "); | ||
| 464 | if (opts->short_name) | ||
| 465 | pos += fprintf(stderr, "-%c", opts->short_name); | ||
| 466 | else | ||
| 467 | pos += fprintf(stderr, " "); | ||
| 468 | |||
| 469 | if (opts->long_name && opts->short_name) | ||
| 470 | pos += fprintf(stderr, ", "); | ||
| 471 | if (opts->long_name) | ||
| 472 | pos += fprintf(stderr, "--%s", opts->long_name); | ||
| 473 | |||
| 474 | switch (opts->type) { | ||
| 475 | case OPTION_ARGUMENT: | ||
| 476 | break; | ||
| 477 | case OPTION_LONG: | ||
| 478 | case OPTION_U64: | ||
| 479 | case OPTION_INTEGER: | ||
| 480 | case OPTION_UINTEGER: | ||
| 481 | if (opts->flags & PARSE_OPT_OPTARG) | ||
| 482 | if (opts->long_name) | ||
| 483 | pos += fprintf(stderr, "[=<n>]"); | ||
| 484 | else | ||
| 485 | pos += fprintf(stderr, "[<n>]"); | ||
| 486 | else | ||
| 487 | pos += fprintf(stderr, " <n>"); | ||
| 488 | break; | ||
| 489 | case OPTION_CALLBACK: | ||
| 490 | if (opts->flags & PARSE_OPT_NOARG) | ||
| 491 | break; | ||
| 492 | /* FALLTHROUGH */ | ||
| 493 | case OPTION_STRING: | ||
| 494 | if (opts->argh) { | ||
| 495 | if (opts->flags & PARSE_OPT_OPTARG) | ||
| 496 | if (opts->long_name) | ||
| 497 | pos += fprintf(stderr, "[=<%s>]", opts->argh); | ||
| 498 | else | ||
| 499 | pos += fprintf(stderr, "[<%s>]", opts->argh); | ||
| 500 | else | ||
| 501 | pos += fprintf(stderr, " <%s>", opts->argh); | ||
| 502 | } else { | ||
| 503 | if (opts->flags & PARSE_OPT_OPTARG) | ||
| 504 | if (opts->long_name) | ||
| 505 | pos += fprintf(stderr, "[=...]"); | ||
| 506 | else | ||
| 507 | pos += fprintf(stderr, "[...]"); | ||
| 508 | else | ||
| 509 | pos += fprintf(stderr, " ..."); | ||
| 510 | } | ||
| 511 | break; | ||
| 512 | default: /* OPTION_{BIT,BOOLEAN,SET_UINT,SET_PTR} */ | ||
| 513 | case OPTION_END: | ||
| 514 | case OPTION_GROUP: | ||
| 515 | case OPTION_BIT: | ||
| 516 | case OPTION_BOOLEAN: | ||
| 517 | case OPTION_INCR: | ||
| 518 | case OPTION_SET_UINT: | ||
| 519 | case OPTION_SET_PTR: | ||
| 520 | break; | ||
| 521 | } | ||
| 522 | |||
| 523 | if (pos <= USAGE_OPTS_WIDTH) | ||
| 524 | pad = USAGE_OPTS_WIDTH - pos; | ||
| 525 | else { | ||
| 526 | fputc('\n', stderr); | ||
| 527 | pad = USAGE_OPTS_WIDTH; | ||
| 528 | } | ||
| 529 | fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help); | ||
| 530 | } | ||
| 531 | |||
| 448 | int usage_with_options_internal(const char * const *usagestr, | 532 | int usage_with_options_internal(const char * const *usagestr, |
| 449 | const struct option *opts, int full) | 533 | const struct option *opts, int full) |
| 450 | { | 534 | { |
| @@ -464,87 +548,9 @@ int usage_with_options_internal(const char * const *usagestr, | |||
| 464 | if (opts->type != OPTION_GROUP) | 548 | if (opts->type != OPTION_GROUP) |
| 465 | fputc('\n', stderr); | 549 | fputc('\n', stderr); |
| 466 | 550 | ||
| 467 | for (; opts->type != OPTION_END; opts++) { | 551 | for ( ; opts->type != OPTION_END; opts++) |
| 468 | size_t pos; | 552 | print_option_help(opts, full); |
| 469 | int pad; | ||
| 470 | |||
| 471 | if (opts->type == OPTION_GROUP) { | ||
| 472 | fputc('\n', stderr); | ||
| 473 | if (*opts->help) | ||
| 474 | fprintf(stderr, "%s\n", opts->help); | ||
| 475 | continue; | ||
| 476 | } | ||
| 477 | if (!full && (opts->flags & PARSE_OPT_HIDDEN)) | ||
| 478 | continue; | ||
| 479 | |||
| 480 | pos = fprintf(stderr, " "); | ||
| 481 | if (opts->short_name) | ||
| 482 | pos += fprintf(stderr, "-%c", opts->short_name); | ||
| 483 | else | ||
| 484 | pos += fprintf(stderr, " "); | ||
| 485 | |||
| 486 | if (opts->long_name && opts->short_name) | ||
| 487 | pos += fprintf(stderr, ", "); | ||
| 488 | if (opts->long_name) | ||
| 489 | pos += fprintf(stderr, "--%s", opts->long_name); | ||
| 490 | |||
| 491 | switch (opts->type) { | ||
| 492 | case OPTION_ARGUMENT: | ||
| 493 | break; | ||
| 494 | case OPTION_LONG: | ||
| 495 | case OPTION_U64: | ||
| 496 | case OPTION_INTEGER: | ||
| 497 | case OPTION_UINTEGER: | ||
| 498 | if (opts->flags & PARSE_OPT_OPTARG) | ||
| 499 | if (opts->long_name) | ||
| 500 | pos += fprintf(stderr, "[=<n>]"); | ||
| 501 | else | ||
| 502 | pos += fprintf(stderr, "[<n>]"); | ||
| 503 | else | ||
| 504 | pos += fprintf(stderr, " <n>"); | ||
| 505 | break; | ||
| 506 | case OPTION_CALLBACK: | ||
| 507 | if (opts->flags & PARSE_OPT_NOARG) | ||
| 508 | break; | ||
| 509 | /* FALLTHROUGH */ | ||
| 510 | case OPTION_STRING: | ||
| 511 | if (opts->argh) { | ||
| 512 | if (opts->flags & PARSE_OPT_OPTARG) | ||
| 513 | if (opts->long_name) | ||
| 514 | pos += fprintf(stderr, "[=<%s>]", opts->argh); | ||
| 515 | else | ||
| 516 | pos += fprintf(stderr, "[<%s>]", opts->argh); | ||
| 517 | else | ||
| 518 | pos += fprintf(stderr, " <%s>", opts->argh); | ||
| 519 | } else { | ||
| 520 | if (opts->flags & PARSE_OPT_OPTARG) | ||
| 521 | if (opts->long_name) | ||
| 522 | pos += fprintf(stderr, "[=...]"); | ||
| 523 | else | ||
| 524 | pos += fprintf(stderr, "[...]"); | ||
| 525 | else | ||
| 526 | pos += fprintf(stderr, " ..."); | ||
| 527 | } | ||
| 528 | break; | ||
| 529 | default: /* OPTION_{BIT,BOOLEAN,SET_UINT,SET_PTR} */ | ||
| 530 | case OPTION_END: | ||
| 531 | case OPTION_GROUP: | ||
| 532 | case OPTION_BIT: | ||
| 533 | case OPTION_BOOLEAN: | ||
| 534 | case OPTION_INCR: | ||
| 535 | case OPTION_SET_UINT: | ||
| 536 | case OPTION_SET_PTR: | ||
| 537 | break; | ||
| 538 | } | ||
| 539 | 553 | ||
| 540 | if (pos <= USAGE_OPTS_WIDTH) | ||
| 541 | pad = USAGE_OPTS_WIDTH - pos; | ||
| 542 | else { | ||
| 543 | fputc('\n', stderr); | ||
| 544 | pad = USAGE_OPTS_WIDTH; | ||
| 545 | } | ||
| 546 | fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help); | ||
| 547 | } | ||
| 548 | fputc('\n', stderr); | 554 | fputc('\n', stderr); |
| 549 | 555 | ||
| 550 | return PARSE_OPT_HELP; | 556 | return PARSE_OPT_HELP; |
| @@ -559,9 +565,45 @@ void usage_with_options(const char * const *usagestr, | |||
| 559 | } | 565 | } |
| 560 | 566 | ||
| 561 | int parse_options_usage(const char * const *usagestr, | 567 | int parse_options_usage(const char * const *usagestr, |
| 562 | const struct option *opts) | 568 | const struct option *opts, |
| 569 | const char *optstr, bool short_opt) | ||
| 563 | { | 570 | { |
| 564 | return usage_with_options_internal(usagestr, opts, 0); | 571 | if (!usagestr) |
| 572 | goto opt; | ||
| 573 | |||
| 574 | fprintf(stderr, "\n usage: %s\n", *usagestr++); | ||
| 575 | while (*usagestr && **usagestr) | ||
| 576 | fprintf(stderr, " or: %s\n", *usagestr++); | ||
| 577 | while (*usagestr) { | ||
| 578 | fprintf(stderr, "%s%s\n", | ||
| 579 | **usagestr ? " " : "", | ||
| 580 | *usagestr); | ||
| 581 | usagestr++; | ||
| 582 | } | ||
| 583 | fputc('\n', stderr); | ||
| 584 | |||
| 585 | opt: | ||
| 586 | for ( ; opts->type != OPTION_END; opts++) { | ||
| 587 | if (short_opt) { | ||
| 588 | if (opts->short_name == *optstr) | ||
| 589 | break; | ||
| 590 | continue; | ||
| 591 | } | ||
| 592 | |||
| 593 | if (opts->long_name == NULL) | ||
| 594 | continue; | ||
| 595 | |||
| 596 | if (!prefixcmp(optstr, opts->long_name)) | ||
| 597 | break; | ||
| 598 | if (!prefixcmp(optstr, "no-") && | ||
| 599 | !prefixcmp(optstr + 3, opts->long_name)) | ||
| 600 | break; | ||
| 601 | } | ||
| 602 | |||
| 603 | if (opts->type != OPTION_END) | ||
| 604 | print_option_help(opts, 0); | ||
| 605 | |||
| 606 | return PARSE_OPT_HELP; | ||
| 565 | } | 607 | } |
| 566 | 608 | ||
| 567 | 609 | ||
