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