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 9 static 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 18 static 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 35 static 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 46 if (!(flags & OPT_SHORT) && p->opt) { 47 switch (opt->type) { 48 case OPTION_CALLBACK: 49 if (!(opt->flags & PARSE_OPT_NOARG)) 50 break; 51 /* FALLTHROUGH */ 52 case OPTION_BOOLEAN: 53 case OPTION_INCR: 54 case OPTION_BIT: 55 case OPTION_SET_UINT: 56 case OPTION_SET_PTR: 57 return opterror(opt, "takes no value", flags); 58 case OPTION_END: 59 case OPTION_ARGUMENT: 60 case OPTION_GROUP: 61 case OPTION_STRING: 62 case OPTION_INTEGER: 63 case OPTION_UINTEGER: 64 case OPTION_LONG: 65 case OPTION_U64: 66 default: 67 break; 68 } 69 } 70 71 switch (opt->type) { 72 case OPTION_BIT: 73 if (unset) 74 *(int *)opt->value &= ~opt->defval; 75 else 76 *(int *)opt->value |= opt->defval; 77 return 0; 78 79 case OPTION_BOOLEAN: 80 *(bool *)opt->value = unset ? false : true; 81 return 0; 82 83 case OPTION_INCR: 84 *(int *)opt->value = unset ? 0 : *(int *)opt->value + 1; 85 return 0; 86 87 case OPTION_SET_UINT: 88 *(unsigned int *)opt->value = unset ? 0 : opt->defval; 89 return 0; 90 91 case OPTION_SET_PTR: 92 *(void **)opt->value = unset ? NULL : (void *)opt->defval; 93 return 0; 94 95 case OPTION_STRING: 96 if (unset) 97 *(const char **)opt->value = NULL; 98 else if (opt->flags & PARSE_OPT_OPTARG && !p->opt) 99 *(const char **)opt->value = (const char *)opt->defval; 100 else 101 return get_arg(p, opt, flags, (const char **)opt->value); 102 return 0; 103 104 case OPTION_CALLBACK: 105 if (unset) 106 return (*opt->callback)(opt, NULL, 1) ? (-1) : 0; 107 if (opt->flags & PARSE_OPT_NOARG) 108 return (*opt->callback)(opt, NULL, 0) ? (-1) : 0; 109 if (opt->flags & PARSE_OPT_OPTARG && !p->opt) 110 return (*opt->callback)(opt, NULL, 0) ? (-1) : 0; 111 if (get_arg(p, opt, flags, &arg)) 112 return -1; 113 return (*opt->callback)(opt, arg, 0) ? (-1) : 0; 114 115 case OPTION_INTEGER: 116 if (unset) { 117 *(int *)opt->value = 0; 118 return 0; 119 } 120 if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { 121 *(int *)opt->value = opt->defval; 122 return 0; 123 } 124 if (get_arg(p, opt, flags, &arg)) 125 return -1; 126 *(int *)opt->value = strtol(arg, (char **)&s, 10); 127 if (*s) 128 return opterror(opt, "expects a numerical value", flags); 129 return 0; 130 131 case OPTION_UINTEGER: 132 if (unset) { 133 *(unsigned int *)opt->value = 0; 134 return 0; 135 } 136 if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { 137 *(unsigned int *)opt->value = opt->defval; 138 return 0; 139 } 140 if (get_arg(p, opt, flags, &arg)) 141 return -1; 142 *(unsigned int *)opt->value = strtol(arg, (char **)&s, 10); 143 if (*s) 144 return opterror(opt, "expects a numerical value", flags); 145 return 0; 146 147 case OPTION_LONG: 148 if (unset) { 149 *(long *)opt->value = 0; 150 return 0; 151 } 152 if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { 153 *(long *)opt->value = opt->defval; 154 return 0; 155 } 156 if (get_arg(p, opt, flags, &arg)) 157 return -1; 158 *(long *)opt->value = strtol(arg, (char **)&s, 10); 159 if (*s) 160 return opterror(opt, "expects a numerical value", flags); 161 return 0; 162 163 case OPTION_U64: 164 if (unset) { 165 *(u64 *)opt->value = 0; 166 return 0; 167 } 168 if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { 169 *(u64 *)opt->value = opt->defval; 170 return 0; 171 } 172 if (get_arg(p, opt, flags, &arg)) 173 return -1; 174 *(u64 *)opt->value = strtoull(arg, (char **)&s, 10); 175 if (*s) 176 return opterror(opt, "expects a numerical value", flags); 177 return 0; 178 179 case OPTION_END: 180 case OPTION_ARGUMENT: 181 case OPTION_GROUP: 182 default: 183 die("should not happen, someone must be hit on the forehead"); 184 } 185 } 186 187 static int parse_short_opt(struct parse_opt_ctx_t *p, const struct option *options) 188 { 189 for (; options->type != OPTION_END; options++) { 190 if (options->short_name == *p->opt) { 191 p->opt = p->opt[1] ? p->opt + 1 : NULL; 192 return get_value(p, options, OPT_SHORT); 193 } 194 } 195 return -2; 196 } 197 198 static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg, 199 const struct option *options) 200 { 201 const char *arg_end = strchr(arg, '='); 202 const struct option *abbrev_option = NULL, *ambiguous_option = NULL; 203 int abbrev_flags = 0, ambiguous_flags = 0; 204 205 if (!arg_end) 206 arg_end = arg + strlen(arg); 207 208 for (; options->type != OPTION_END; options++) { 209 const char *rest; 210 int flags = 0; 211 212 if (!options->long_name) 213 continue; 214 215 rest = skip_prefix(arg, options->long_name); 216 if (options->type == OPTION_ARGUMENT) { 217 if (!rest) 218 continue; 219 if (*rest == '=') 220 return opterror(options, "takes no value", flags); 221 if (*rest) 222 continue; 223 p->out[p->cpidx++] = arg - 2; 224 return 0; 225 } 226 if (!rest) { 227 /* abbreviated? */ 228 if (!strncmp(options->long_name, arg, arg_end - arg)) { 229 is_abbreviated: 230 if (abbrev_option) { 231 /* 232 * If this is abbreviated, it is 233 * ambiguous. So when there is no 234 * exact match later, we need to 235 * error out. 236 */ 237 ambiguous_option = abbrev_option; 238 ambiguous_flags = abbrev_flags; 239 } 240 if (!(flags & OPT_UNSET) && *arg_end) 241 p->opt = arg_end + 1; 242 abbrev_option = options; 243 abbrev_flags = flags; 244 continue; 245 } 246 /* negated and abbreviated very much? */ 247 if (!prefixcmp("no-", arg)) { 248 flags |= OPT_UNSET; 249 goto is_abbreviated; 250 } 251 /* negated? */ 252 if (strncmp(arg, "no-", 3)) 253 continue; 254 flags |= OPT_UNSET; 255 rest = skip_prefix(arg + 3, options->long_name); 256 /* abbreviated and negated? */ 257 if (!rest && !prefixcmp(options->long_name, arg + 3)) 258 goto is_abbreviated; 259 if (!rest) 260 continue; 261 } 262 if (*rest) { 263 if (*rest != '=') 264 continue; 265 p->opt = rest + 1; 266 } 267 return get_value(p, options, flags); 268 } 269 270 if (ambiguous_option) 271 return error("Ambiguous option: %s " 272 "(could be --%s%s or --%s%s)", 273 arg, 274 (ambiguous_flags & OPT_UNSET) ? "no-" : "", 275 ambiguous_option->long_name, 276 (abbrev_flags & OPT_UNSET) ? "no-" : "", 277 abbrev_option->long_name); 278 if (abbrev_option) 279 return get_value(p, abbrev_option, abbrev_flags); 280 return -2; 281 } 282 283 static void check_typos(const char *arg, const struct option *options) 284 { 285 if (strlen(arg) < 3) 286 return; 287 288 if (!prefixcmp(arg, "no-")) { 289 error ("did you mean `--%s` (with two dashes ?)", arg); 290 exit(129); 291 } 292 293 for (; options->type != OPTION_END; options++) { 294 if (!options->long_name) 295 continue; 296 if (!prefixcmp(options->long_name, arg)) { 297 error ("did you mean `--%s` (with two dashes ?)", arg); 298 exit(129); 299 } 300 } 301 } 302 303 void parse_options_start(struct parse_opt_ctx_t *ctx, 304 int argc, const char **argv, int flags) 305 { 306 memset(ctx, 0, sizeof(*ctx)); 307 ctx->argc = argc - 1; 308 ctx->argv = argv + 1; 309 ctx->out = argv; 310 ctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0); 311 ctx->flags = flags; 312 if ((flags & PARSE_OPT_KEEP_UNKNOWN) && 313 (flags & PARSE_OPT_STOP_AT_NON_OPTION)) 314 die("STOP_AT_NON_OPTION and KEEP_UNKNOWN don't go together"); 315 } 316 317 static int usage_with_options_internal(const char * const *, 318 const struct option *, int); 319 320 int parse_options_step(struct parse_opt_ctx_t *ctx, 321 const struct option *options, 322 const char * const usagestr[]) 323 { 324 int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP); 325 326 /* we must reset ->opt, unknown short option leave it dangling */ 327 ctx->opt = NULL; 328 329 for (; ctx->argc; ctx->argc--, ctx->argv++) { 330 const char *arg = ctx->argv[0]; 331 332 if (*arg != '-' || !arg[1]) { 333 if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION) 334 break; 335 ctx->out[ctx->cpidx++] = ctx->argv[0]; 336 continue; 337 } 338 339 if (arg[1] != '-') { 340 ctx->opt = arg + 1; 341 if (internal_help && *ctx->opt == 'h') 342 return parse_options_usage(usagestr, options); 343 switch (parse_short_opt(ctx, options)) { 344 case -1: 345 return parse_options_usage(usagestr, options); 346 case -2: 347 goto unknown; 348 default: 349 break; 350 } 351 if (ctx->opt) 352 check_typos(arg + 1, options); 353 while (ctx->opt) { 354 if (internal_help && *ctx->opt == 'h') 355 return parse_options_usage(usagestr, options); 356 switch (parse_short_opt(ctx, options)) { 357 case -1: 358 return parse_options_usage(usagestr, options); 359 case -2: 360 /* fake a short option thing to hide the fact that we may have 361 * started to parse aggregated stuff 362 * 363 * This is leaky, too bad. 364 */ 365 ctx->argv[0] = strdup(ctx->opt - 1); 366 *(char *)ctx->argv[0] = '-'; 367 goto unknown; 368 default: 369 break; 370 } 371 } 372 continue; 373 } 374 375 if (!arg[2]) { /* "--" */ 376 if (!(ctx->flags & PARSE_OPT_KEEP_DASHDASH)) { 377 ctx->argc--; 378 ctx->argv++; 379 } 380 break; 381 } 382 383 if (internal_help && !strcmp(arg + 2, "help-all")) 384 return usage_with_options_internal(usagestr, options, 1); 385 if (internal_help && !strcmp(arg + 2, "help")) 386 return parse_options_usage(usagestr, options); 387 if (!strcmp(arg + 2, "list-opts")) 388 return PARSE_OPT_LIST; 389 switch (parse_long_opt(ctx, arg + 2, options)) { 390 case -1: 391 return parse_options_usage(usagestr, options); 392 case -2: 393 goto unknown; 394 default: 395 break; 396 } 397 continue; 398 unknown: 399 if (!(ctx->flags & PARSE_OPT_KEEP_UNKNOWN)) 400 return PARSE_OPT_UNKNOWN; 401 ctx->out[ctx->cpidx++] = ctx->argv[0]; 402 ctx->opt = NULL; 403 } 404 return PARSE_OPT_DONE; 405 } 406 407 int parse_options_end(struct parse_opt_ctx_t *ctx) 408 { 409 memmove(ctx->out + ctx->cpidx, ctx->argv, ctx->argc * sizeof(*ctx->out)); 410 ctx->out[ctx->cpidx + ctx->argc] = NULL; 411 return ctx->cpidx + ctx->argc; 412 } 413 414 int parse_options(int argc, const char **argv, const struct option *options, 415 const char * const usagestr[], int flags) 416 { 417 struct parse_opt_ctx_t ctx; 418 419 perf_header__set_cmdline(argc, argv); 420 421 parse_options_start(&ctx, argc, argv, flags); 422 switch (parse_options_step(&ctx, options, usagestr)) { 423 case PARSE_OPT_HELP: 424 exit(129); 425 case PARSE_OPT_DONE: 426 break; 427 case PARSE_OPT_LIST: 428 while (options->type != OPTION_END) { 429 printf("--%s ", options->long_name); 430 options++; 431 } 432 exit(130); 433 default: /* PARSE_OPT_UNKNOWN */ 434 if (ctx.argv[0][1] == '-') { 435 error("unknown option `%s'", ctx.argv[0] + 2); 436 } else { 437 error("unknown switch `%c'", *ctx.opt); 438 } 439 usage_with_options(usagestr, options); 440 } 441 442 return parse_options_end(&ctx); 443 } 444 445 #define USAGE_OPTS_WIDTH 24 446 #define USAGE_GAP 2 447 448 int usage_with_options_internal(const char * const *usagestr, 449 const struct option *opts, int full) 450 { 451 if (!usagestr) 452 return PARSE_OPT_HELP; 453 454 fprintf(stderr, "\n usage: %s\n", *usagestr++); 455 while (*usagestr && **usagestr) 456 fprintf(stderr, " or: %s\n", *usagestr++); 457 while (*usagestr) { 458 fprintf(stderr, "%s%s\n", 459 **usagestr ? " " : "", 460 *usagestr); 461 usagestr++; 462 } 463 464 if (opts->type != OPTION_GROUP) 465 fputc('\n', stderr); 466 467 for (; opts->type != OPTION_END; opts++) { 468 size_t pos; 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 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); 549 550 return PARSE_OPT_HELP; 551 } 552 553 void usage_with_options(const char * const *usagestr, 554 const struct option *opts) 555 { 556 exit_browser(false); 557 usage_with_options_internal(usagestr, opts, 0); 558 exit(129); 559 } 560 561 int parse_options_usage(const char * const *usagestr, 562 const struct option *opts) 563 { 564 return usage_with_options_internal(usagestr, opts, 0); 565 } 566 567 568 int parse_opt_verbosity_cb(const struct option *opt, 569 const char *arg __maybe_unused, 570 int unset) 571 { 572 int *target = opt->value; 573 574 if (unset) 575 /* --no-quiet, --no-verbose */ 576 *target = 0; 577 else if (opt->short_name == 'v') { 578 if (*target >= 0) 579 (*target)++; 580 else 581 *target = 1; 582 } else { 583 if (*target <= 0) 584 (*target)--; 585 else 586 *target = -1; 587 } 588 return 0; 589 } 590