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 | ||