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