at v4.0-rc2 735 lines 18 kB view raw
1#include "util.h" 2#include "parse-options.h" 3#include "cache.h" 4#include "header.h" 5 6#define OPT_SHORT 1 7#define OPT_UNSET 2 8 9static int opterror(const struct option *opt, const char *reason, int flags) 10{ 11 if (flags & OPT_SHORT) 12 return error("switch `%c' %s", opt->short_name, reason); 13 if (flags & OPT_UNSET) 14 return error("option `no-%s' %s", opt->long_name, reason); 15 return error("option `%s' %s", opt->long_name, reason); 16} 17 18static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt, 19 int flags, const char **arg) 20{ 21 if (p->opt) { 22 *arg = p->opt; 23 p->opt = NULL; 24 } else if ((opt->flags & PARSE_OPT_LASTARG_DEFAULT) && (p->argc == 1 || 25 **(p->argv + 1) == '-')) { 26 *arg = (const char *)opt->defval; 27 } else if (p->argc > 1) { 28 p->argc--; 29 *arg = *++p->argv; 30 } else 31 return opterror(opt, "requires a value", flags); 32 return 0; 33} 34 35static int get_value(struct parse_opt_ctx_t *p, 36 const struct option *opt, int flags) 37{ 38 const char *s, *arg = NULL; 39 const int unset = flags & OPT_UNSET; 40 41 if (unset && p->opt) 42 return opterror(opt, "takes no value", flags); 43 if (unset && (opt->flags & PARSE_OPT_NONEG)) 44 return opterror(opt, "isn't available", flags); 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 && p->excl_opt != 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 } 65 if (!(flags & OPT_SHORT) && p->opt) { 66 switch (opt->type) { 67 case OPTION_CALLBACK: 68 if (!(opt->flags & PARSE_OPT_NOARG)) 69 break; 70 /* FALLTHROUGH */ 71 case OPTION_BOOLEAN: 72 case OPTION_INCR: 73 case OPTION_BIT: 74 case OPTION_SET_UINT: 75 case OPTION_SET_PTR: 76 return opterror(opt, "takes no value", flags); 77 case OPTION_END: 78 case OPTION_ARGUMENT: 79 case OPTION_GROUP: 80 case OPTION_STRING: 81 case OPTION_INTEGER: 82 case OPTION_UINTEGER: 83 case OPTION_LONG: 84 case OPTION_U64: 85 default: 86 break; 87 } 88 } 89 90 switch (opt->type) { 91 case OPTION_BIT: 92 if (unset) 93 *(int *)opt->value &= ~opt->defval; 94 else 95 *(int *)opt->value |= opt->defval; 96 return 0; 97 98 case OPTION_BOOLEAN: 99 *(bool *)opt->value = unset ? false : true; 100 if (opt->set) 101 *(bool *)opt->set = true; 102 return 0; 103 104 case OPTION_INCR: 105 *(int *)opt->value = unset ? 0 : *(int *)opt->value + 1; 106 return 0; 107 108 case OPTION_SET_UINT: 109 *(unsigned int *)opt->value = unset ? 0 : opt->defval; 110 return 0; 111 112 case OPTION_SET_PTR: 113 *(void **)opt->value = unset ? NULL : (void *)opt->defval; 114 return 0; 115 116 case OPTION_STRING: 117 if (unset) 118 *(const char **)opt->value = NULL; 119 else if (opt->flags & PARSE_OPT_OPTARG && !p->opt) 120 *(const char **)opt->value = (const char *)opt->defval; 121 else 122 return get_arg(p, opt, flags, (const char **)opt->value); 123 return 0; 124 125 case OPTION_CALLBACK: 126 if (unset) 127 return (*opt->callback)(opt, NULL, 1) ? (-1) : 0; 128 if (opt->flags & PARSE_OPT_NOARG) 129 return (*opt->callback)(opt, NULL, 0) ? (-1) : 0; 130 if (opt->flags & PARSE_OPT_OPTARG && !p->opt) 131 return (*opt->callback)(opt, NULL, 0) ? (-1) : 0; 132 if (get_arg(p, opt, flags, &arg)) 133 return -1; 134 return (*opt->callback)(opt, arg, 0) ? (-1) : 0; 135 136 case OPTION_INTEGER: 137 if (unset) { 138 *(int *)opt->value = 0; 139 return 0; 140 } 141 if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { 142 *(int *)opt->value = opt->defval; 143 return 0; 144 } 145 if (get_arg(p, opt, flags, &arg)) 146 return -1; 147 *(int *)opt->value = strtol(arg, (char **)&s, 10); 148 if (*s) 149 return opterror(opt, "expects a numerical value", flags); 150 return 0; 151 152 case OPTION_UINTEGER: 153 if (unset) { 154 *(unsigned int *)opt->value = 0; 155 return 0; 156 } 157 if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { 158 *(unsigned int *)opt->value = opt->defval; 159 return 0; 160 } 161 if (get_arg(p, opt, flags, &arg)) 162 return -1; 163 *(unsigned int *)opt->value = strtol(arg, (char **)&s, 10); 164 if (*s) 165 return opterror(opt, "expects a numerical value", flags); 166 return 0; 167 168 case OPTION_LONG: 169 if (unset) { 170 *(long *)opt->value = 0; 171 return 0; 172 } 173 if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { 174 *(long *)opt->value = opt->defval; 175 return 0; 176 } 177 if (get_arg(p, opt, flags, &arg)) 178 return -1; 179 *(long *)opt->value = strtol(arg, (char **)&s, 10); 180 if (*s) 181 return opterror(opt, "expects a numerical value", flags); 182 return 0; 183 184 case OPTION_U64: 185 if (unset) { 186 *(u64 *)opt->value = 0; 187 return 0; 188 } 189 if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { 190 *(u64 *)opt->value = opt->defval; 191 return 0; 192 } 193 if (get_arg(p, opt, flags, &arg)) 194 return -1; 195 *(u64 *)opt->value = strtoull(arg, (char **)&s, 10); 196 if (*s) 197 return opterror(opt, "expects a numerical value", flags); 198 return 0; 199 200 case OPTION_END: 201 case OPTION_ARGUMENT: 202 case OPTION_GROUP: 203 default: 204 die("should not happen, someone must be hit on the forehead"); 205 } 206} 207 208static int parse_short_opt(struct parse_opt_ctx_t *p, const struct option *options) 209{ 210 for (; options->type != OPTION_END; options++) { 211 if (options->short_name == *p->opt) { 212 p->opt = p->opt[1] ? p->opt + 1 : NULL; 213 return get_value(p, options, OPT_SHORT); 214 } 215 } 216 return -2; 217} 218 219static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg, 220 const struct option *options) 221{ 222 const char *arg_end = strchr(arg, '='); 223 const struct option *abbrev_option = NULL, *ambiguous_option = NULL; 224 int abbrev_flags = 0, ambiguous_flags = 0; 225 226 if (!arg_end) 227 arg_end = arg + strlen(arg); 228 229 for (; options->type != OPTION_END; options++) { 230 const char *rest; 231 int flags = 0; 232 233 if (!options->long_name) 234 continue; 235 236 rest = skip_prefix(arg, options->long_name); 237 if (options->type == OPTION_ARGUMENT) { 238 if (!rest) 239 continue; 240 if (*rest == '=') 241 return opterror(options, "takes no value", flags); 242 if (*rest) 243 continue; 244 p->out[p->cpidx++] = arg - 2; 245 return 0; 246 } 247 if (!rest) { 248 if (!prefixcmp(options->long_name, "no-")) { 249 /* 250 * The long name itself starts with "no-", so 251 * accept the option without "no-" so that users 252 * do not have to enter "no-no-" to get the 253 * negation. 254 */ 255 rest = skip_prefix(arg, options->long_name + 3); 256 if (rest) { 257 flags |= OPT_UNSET; 258 goto match; 259 } 260 /* Abbreviated case */ 261 if (!prefixcmp(options->long_name + 3, arg)) { 262 flags |= OPT_UNSET; 263 goto is_abbreviated; 264 } 265 } 266 /* abbreviated? */ 267 if (!strncmp(options->long_name, arg, arg_end - arg)) { 268is_abbreviated: 269 if (abbrev_option) { 270 /* 271 * If this is abbreviated, it is 272 * ambiguous. So when there is no 273 * exact match later, we need to 274 * error out. 275 */ 276 ambiguous_option = abbrev_option; 277 ambiguous_flags = abbrev_flags; 278 } 279 if (!(flags & OPT_UNSET) && *arg_end) 280 p->opt = arg_end + 1; 281 abbrev_option = options; 282 abbrev_flags = flags; 283 continue; 284 } 285 /* negated and abbreviated very much? */ 286 if (!prefixcmp("no-", arg)) { 287 flags |= OPT_UNSET; 288 goto is_abbreviated; 289 } 290 /* negated? */ 291 if (strncmp(arg, "no-", 3)) 292 continue; 293 flags |= OPT_UNSET; 294 rest = skip_prefix(arg + 3, options->long_name); 295 /* abbreviated and negated? */ 296 if (!rest && !prefixcmp(options->long_name, arg + 3)) 297 goto is_abbreviated; 298 if (!rest) 299 continue; 300 } 301match: 302 if (*rest) { 303 if (*rest != '=') 304 continue; 305 p->opt = rest + 1; 306 } 307 return get_value(p, options, flags); 308 } 309 310 if (ambiguous_option) 311 return error("Ambiguous option: %s " 312 "(could be --%s%s or --%s%s)", 313 arg, 314 (ambiguous_flags & OPT_UNSET) ? "no-" : "", 315 ambiguous_option->long_name, 316 (abbrev_flags & OPT_UNSET) ? "no-" : "", 317 abbrev_option->long_name); 318 if (abbrev_option) 319 return get_value(p, abbrev_option, abbrev_flags); 320 return -2; 321} 322 323static void check_typos(const char *arg, const struct option *options) 324{ 325 if (strlen(arg) < 3) 326 return; 327 328 if (!prefixcmp(arg, "no-")) { 329 error ("did you mean `--%s` (with two dashes ?)", arg); 330 exit(129); 331 } 332 333 for (; options->type != OPTION_END; options++) { 334 if (!options->long_name) 335 continue; 336 if (!prefixcmp(options->long_name, arg)) { 337 error ("did you mean `--%s` (with two dashes ?)", arg); 338 exit(129); 339 } 340 } 341} 342 343void parse_options_start(struct parse_opt_ctx_t *ctx, 344 int argc, const char **argv, int flags) 345{ 346 memset(ctx, 0, sizeof(*ctx)); 347 ctx->argc = argc - 1; 348 ctx->argv = argv + 1; 349 ctx->out = argv; 350 ctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0); 351 ctx->flags = flags; 352 if ((flags & PARSE_OPT_KEEP_UNKNOWN) && 353 (flags & PARSE_OPT_STOP_AT_NON_OPTION)) 354 die("STOP_AT_NON_OPTION and KEEP_UNKNOWN don't go together"); 355} 356 357static int usage_with_options_internal(const char * const *, 358 const struct option *, int); 359 360int parse_options_step(struct parse_opt_ctx_t *ctx, 361 const struct option *options, 362 const char * const usagestr[]) 363{ 364 int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP); 365 int excl_short_opt = 1; 366 const char *arg; 367 368 /* we must reset ->opt, unknown short option leave it dangling */ 369 ctx->opt = NULL; 370 371 for (; ctx->argc; ctx->argc--, ctx->argv++) { 372 arg = ctx->argv[0]; 373 if (*arg != '-' || !arg[1]) { 374 if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION) 375 break; 376 ctx->out[ctx->cpidx++] = ctx->argv[0]; 377 continue; 378 } 379 380 if (arg[1] != '-') { 381 ctx->opt = ++arg; 382 if (internal_help && *ctx->opt == 'h') 383 return usage_with_options_internal(usagestr, options, 0); 384 switch (parse_short_opt(ctx, options)) { 385 case -1: 386 return parse_options_usage(usagestr, options, arg, 1); 387 case -2: 388 goto unknown; 389 case -3: 390 goto exclusive; 391 default: 392 break; 393 } 394 if (ctx->opt) 395 check_typos(arg, options); 396 while (ctx->opt) { 397 if (internal_help && *ctx->opt == 'h') 398 return usage_with_options_internal(usagestr, options, 0); 399 arg = ctx->opt; 400 switch (parse_short_opt(ctx, options)) { 401 case -1: 402 return parse_options_usage(usagestr, options, arg, 1); 403 case -2: 404 /* fake a short option thing to hide the fact that we may have 405 * started to parse aggregated stuff 406 * 407 * This is leaky, too bad. 408 */ 409 ctx->argv[0] = strdup(ctx->opt - 1); 410 *(char *)ctx->argv[0] = '-'; 411 goto unknown; 412 case -3: 413 goto exclusive; 414 default: 415 break; 416 } 417 } 418 continue; 419 } 420 421 if (!arg[2]) { /* "--" */ 422 if (!(ctx->flags & PARSE_OPT_KEEP_DASHDASH)) { 423 ctx->argc--; 424 ctx->argv++; 425 } 426 break; 427 } 428 429 arg += 2; 430 if (internal_help && !strcmp(arg, "help-all")) 431 return usage_with_options_internal(usagestr, options, 1); 432 if (internal_help && !strcmp(arg, "help")) 433 return usage_with_options_internal(usagestr, options, 0); 434 if (!strcmp(arg, "list-opts")) 435 return PARSE_OPT_LIST_OPTS; 436 if (!strcmp(arg, "list-cmds")) 437 return PARSE_OPT_LIST_SUBCMDS; 438 switch (parse_long_opt(ctx, arg, options)) { 439 case -1: 440 return parse_options_usage(usagestr, options, arg, 0); 441 case -2: 442 goto unknown; 443 case -3: 444 excl_short_opt = 0; 445 goto exclusive; 446 default: 447 break; 448 } 449 continue; 450unknown: 451 if (!(ctx->flags & PARSE_OPT_KEEP_UNKNOWN)) 452 return PARSE_OPT_UNKNOWN; 453 ctx->out[ctx->cpidx++] = ctx->argv[0]; 454 ctx->opt = NULL; 455 } 456 return PARSE_OPT_DONE; 457 458exclusive: 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; 468} 469 470int parse_options_end(struct parse_opt_ctx_t *ctx) 471{ 472 memmove(ctx->out + ctx->cpidx, ctx->argv, ctx->argc * sizeof(*ctx->out)); 473 ctx->out[ctx->cpidx + ctx->argc] = NULL; 474 return ctx->cpidx + ctx->argc; 475} 476 477int parse_options_subcommand(int argc, const char **argv, const struct option *options, 478 const char *const subcommands[], const char *usagestr[], int flags) 479{ 480 struct parse_opt_ctx_t ctx; 481 482 perf_header__set_cmdline(argc, argv); 483 484 /* build usage string if it's not provided */ 485 if (subcommands && !usagestr[0]) { 486 struct strbuf buf = STRBUF_INIT; 487 488 strbuf_addf(&buf, "perf %s [<options>] {", argv[0]); 489 for (int i = 0; subcommands[i]; i++) { 490 if (i) 491 strbuf_addstr(&buf, "|"); 492 strbuf_addstr(&buf, subcommands[i]); 493 } 494 strbuf_addstr(&buf, "}"); 495 496 usagestr[0] = strdup(buf.buf); 497 strbuf_release(&buf); 498 } 499 500 parse_options_start(&ctx, argc, argv, flags); 501 switch (parse_options_step(&ctx, options, usagestr)) { 502 case PARSE_OPT_HELP: 503 exit(129); 504 case PARSE_OPT_DONE: 505 break; 506 case PARSE_OPT_LIST_OPTS: 507 while (options->type != OPTION_END) { 508 printf("--%s ", options->long_name); 509 options++; 510 } 511 exit(130); 512 case PARSE_OPT_LIST_SUBCMDS: 513 for (int i = 0; subcommands[i]; i++) 514 printf("%s ", subcommands[i]); 515 exit(130); 516 default: /* PARSE_OPT_UNKNOWN */ 517 if (ctx.argv[0][1] == '-') { 518 error("unknown option `%s'", ctx.argv[0] + 2); 519 } else { 520 error("unknown switch `%c'", *ctx.opt); 521 } 522 usage_with_options(usagestr, options); 523 } 524 525 return parse_options_end(&ctx); 526} 527 528int parse_options(int argc, const char **argv, const struct option *options, 529 const char * const usagestr[], int flags) 530{ 531 return parse_options_subcommand(argc, argv, options, NULL, 532 (const char **) usagestr, flags); 533} 534 535#define USAGE_OPTS_WIDTH 24 536#define USAGE_GAP 2 537 538static void print_option_help(const struct option *opts, int full) 539{ 540 size_t pos; 541 int pad; 542 543 if (opts->type == OPTION_GROUP) { 544 fputc('\n', stderr); 545 if (*opts->help) 546 fprintf(stderr, "%s\n", opts->help); 547 return; 548 } 549 if (!full && (opts->flags & PARSE_OPT_HIDDEN)) 550 return; 551 if (opts->flags & PARSE_OPT_DISABLED) 552 return; 553 554 pos = fprintf(stderr, " "); 555 if (opts->short_name) 556 pos += fprintf(stderr, "-%c", opts->short_name); 557 else 558 pos += fprintf(stderr, " "); 559 560 if (opts->long_name && opts->short_name) 561 pos += fprintf(stderr, ", "); 562 if (opts->long_name) 563 pos += fprintf(stderr, "--%s", opts->long_name); 564 565 switch (opts->type) { 566 case OPTION_ARGUMENT: 567 break; 568 case OPTION_LONG: 569 case OPTION_U64: 570 case OPTION_INTEGER: 571 case OPTION_UINTEGER: 572 if (opts->flags & PARSE_OPT_OPTARG) 573 if (opts->long_name) 574 pos += fprintf(stderr, "[=<n>]"); 575 else 576 pos += fprintf(stderr, "[<n>]"); 577 else 578 pos += fprintf(stderr, " <n>"); 579 break; 580 case OPTION_CALLBACK: 581 if (opts->flags & PARSE_OPT_NOARG) 582 break; 583 /* FALLTHROUGH */ 584 case OPTION_STRING: 585 if (opts->argh) { 586 if (opts->flags & PARSE_OPT_OPTARG) 587 if (opts->long_name) 588 pos += fprintf(stderr, "[=<%s>]", opts->argh); 589 else 590 pos += fprintf(stderr, "[<%s>]", opts->argh); 591 else 592 pos += fprintf(stderr, " <%s>", opts->argh); 593 } else { 594 if (opts->flags & PARSE_OPT_OPTARG) 595 if (opts->long_name) 596 pos += fprintf(stderr, "[=...]"); 597 else 598 pos += fprintf(stderr, "[...]"); 599 else 600 pos += fprintf(stderr, " ..."); 601 } 602 break; 603 default: /* OPTION_{BIT,BOOLEAN,SET_UINT,SET_PTR} */ 604 case OPTION_END: 605 case OPTION_GROUP: 606 case OPTION_BIT: 607 case OPTION_BOOLEAN: 608 case OPTION_INCR: 609 case OPTION_SET_UINT: 610 case OPTION_SET_PTR: 611 break; 612 } 613 614 if (pos <= USAGE_OPTS_WIDTH) 615 pad = USAGE_OPTS_WIDTH - pos; 616 else { 617 fputc('\n', stderr); 618 pad = USAGE_OPTS_WIDTH; 619 } 620 fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help); 621} 622 623int usage_with_options_internal(const char * const *usagestr, 624 const struct option *opts, int full) 625{ 626 if (!usagestr) 627 return PARSE_OPT_HELP; 628 629 fprintf(stderr, "\n usage: %s\n", *usagestr++); 630 while (*usagestr && **usagestr) 631 fprintf(stderr, " or: %s\n", *usagestr++); 632 while (*usagestr) { 633 fprintf(stderr, "%s%s\n", 634 **usagestr ? " " : "", 635 *usagestr); 636 usagestr++; 637 } 638 639 if (opts->type != OPTION_GROUP) 640 fputc('\n', stderr); 641 642 for ( ; opts->type != OPTION_END; opts++) 643 print_option_help(opts, full); 644 645 fputc('\n', stderr); 646 647 return PARSE_OPT_HELP; 648} 649 650void usage_with_options(const char * const *usagestr, 651 const struct option *opts) 652{ 653 exit_browser(false); 654 usage_with_options_internal(usagestr, opts, 0); 655 exit(129); 656} 657 658int parse_options_usage(const char * const *usagestr, 659 const struct option *opts, 660 const char *optstr, bool short_opt) 661{ 662 if (!usagestr) 663 goto opt; 664 665 fprintf(stderr, "\n usage: %s\n", *usagestr++); 666 while (*usagestr && **usagestr) 667 fprintf(stderr, " or: %s\n", *usagestr++); 668 while (*usagestr) { 669 fprintf(stderr, "%s%s\n", 670 **usagestr ? " " : "", 671 *usagestr); 672 usagestr++; 673 } 674 fputc('\n', stderr); 675 676opt: 677 for ( ; opts->type != OPTION_END; opts++) { 678 if (short_opt) { 679 if (opts->short_name == *optstr) 680 break; 681 continue; 682 } 683 684 if (opts->long_name == NULL) 685 continue; 686 687 if (!prefixcmp(optstr, opts->long_name)) 688 break; 689 if (!prefixcmp(optstr, "no-") && 690 !prefixcmp(optstr + 3, opts->long_name)) 691 break; 692 } 693 694 if (opts->type != OPTION_END) 695 print_option_help(opts, 0); 696 697 return PARSE_OPT_HELP; 698} 699 700 701int parse_opt_verbosity_cb(const struct option *opt, 702 const char *arg __maybe_unused, 703 int unset) 704{ 705 int *target = opt->value; 706 707 if (unset) 708 /* --no-quiet, --no-verbose */ 709 *target = 0; 710 else if (opt->short_name == 'v') { 711 if (*target >= 0) 712 (*target)++; 713 else 714 *target = 1; 715 } else { 716 if (*target <= 0) 717 (*target)--; 718 else 719 *target = -1; 720 } 721 return 0; 722} 723 724void 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}