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