parse-options.con commit parse-options: check empty value in OPT_INTEGER and OPT_ABBREV (f7e68a0)
   1#include "git-compat-util.h"
   2#include "parse-options.h"
   3#include "cache.h"
   4#include "config.h"
   5#include "commit.h"
   6#include "color.h"
   7#include "utf8.h"
   8
   9#define OPT_SHORT 1
  10#define OPT_UNSET 2
  11
  12int optbug(const struct option *opt, const char *reason)
  13{
  14        if (opt->long_name) {
  15                if (opt->short_name)
  16                        return error("BUG: switch '%c' (--%s) %s",
  17                                     opt->short_name, opt->long_name, reason);
  18                return error("BUG: option '%s' %s", opt->long_name, reason);
  19        }
  20        return error("BUG: switch '%c' %s", opt->short_name, reason);
  21}
  22
  23static enum parse_opt_result get_arg(struct parse_opt_ctx_t *p,
  24                                     const struct option *opt,
  25                                     int flags, const char **arg)
  26{
  27        if (p->opt) {
  28                *arg = p->opt;
  29                p->opt = NULL;
  30        } else if (p->argc == 1 && (opt->flags & PARSE_OPT_LASTARG_DEFAULT)) {
  31                *arg = (const char *)opt->defval;
  32        } else if (p->argc > 1) {
  33                p->argc--;
  34                *arg = *++p->argv;
  35        } else
  36                return error(_("%s requires a value"), optname(opt, flags));
  37        return 0;
  38}
  39
  40static void fix_filename(const char *prefix, const char **file)
  41{
  42        if (!file || !*file || !prefix || is_absolute_path(*file)
  43            || !strcmp("-", *file))
  44                return;
  45        *file = prefix_filename(prefix, *file);
  46}
  47
  48static enum parse_opt_result opt_command_mode_error(
  49        const struct option *opt,
  50        const struct option *all_opts,
  51        int flags)
  52{
  53        const struct option *that;
  54        struct strbuf that_name = STRBUF_INIT;
  55
  56        /*
  57         * Find the other option that was used to set the variable
  58         * already, and report that this is not compatible with it.
  59         */
  60        for (that = all_opts; that->type != OPTION_END; that++) {
  61                if (that == opt ||
  62                    that->type != OPTION_CMDMODE ||
  63                    that->value != opt->value ||
  64                    that->defval != *(int *)opt->value)
  65                        continue;
  66
  67                if (that->long_name)
  68                        strbuf_addf(&that_name, "--%s", that->long_name);
  69                else
  70                        strbuf_addf(&that_name, "-%c", that->short_name);
  71                error(_("%s is incompatible with %s"),
  72                      optname(opt, flags), that_name.buf);
  73                strbuf_release(&that_name);
  74                return PARSE_OPT_ERROR;
  75        }
  76        return error(_("%s : incompatible with something else"),
  77                     optname(opt, flags));
  78}
  79
  80static enum parse_opt_result get_value(struct parse_opt_ctx_t *p,
  81                                       const struct option *opt,
  82                                       const struct option *all_opts,
  83                                       int flags)
  84{
  85        const char *s, *arg;
  86        const int unset = flags & OPT_UNSET;
  87        int err;
  88
  89        if (unset && p->opt)
  90                return error(_("%s takes no value"), optname(opt, flags));
  91        if (unset && (opt->flags & PARSE_OPT_NONEG))
  92                return error(_("%s isn't available"), optname(opt, flags));
  93        if (!(flags & OPT_SHORT) && p->opt && (opt->flags & PARSE_OPT_NOARG))
  94                return error(_("%s takes no value"), optname(opt, flags));
  95
  96        switch (opt->type) {
  97        case OPTION_LOWLEVEL_CALLBACK:
  98                return opt->ll_callback(p, opt, NULL, unset);
  99
 100        case OPTION_BIT:
 101                if (unset)
 102                        *(int *)opt->value &= ~opt->defval;
 103                else
 104                        *(int *)opt->value |= opt->defval;
 105                return 0;
 106
 107        case OPTION_NEGBIT:
 108                if (unset)
 109                        *(int *)opt->value |= opt->defval;
 110                else
 111                        *(int *)opt->value &= ~opt->defval;
 112                return 0;
 113
 114        case OPTION_BITOP:
 115                if (unset)
 116                        BUG("BITOP can't have unset form");
 117                *(int *)opt->value &= ~opt->extra;
 118                *(int *)opt->value |= opt->defval;
 119                return 0;
 120
 121        case OPTION_COUNTUP:
 122                if (*(int *)opt->value < 0)
 123                        *(int *)opt->value = 0;
 124                *(int *)opt->value = unset ? 0 : *(int *)opt->value + 1;
 125                return 0;
 126
 127        case OPTION_SET_INT:
 128                *(int *)opt->value = unset ? 0 : opt->defval;
 129                return 0;
 130
 131        case OPTION_CMDMODE:
 132                /*
 133                 * Giving the same mode option twice, although is unnecessary,
 134                 * is not a grave error, so let it pass.
 135                 */
 136                if (*(int *)opt->value && *(int *)opt->value != opt->defval)
 137                        return opt_command_mode_error(opt, all_opts, flags);
 138                *(int *)opt->value = opt->defval;
 139                return 0;
 140
 141        case OPTION_STRING:
 142                if (unset)
 143                        *(const char **)opt->value = NULL;
 144                else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
 145                        *(const char **)opt->value = (const char *)opt->defval;
 146                else
 147                        return get_arg(p, opt, flags, (const char **)opt->value);
 148                return 0;
 149
 150        case OPTION_FILENAME:
 151                err = 0;
 152                if (unset)
 153                        *(const char **)opt->value = NULL;
 154                else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
 155                        *(const char **)opt->value = (const char *)opt->defval;
 156                else
 157                        err = get_arg(p, opt, flags, (const char **)opt->value);
 158
 159                if (!err)
 160                        fix_filename(p->prefix, (const char **)opt->value);
 161                return err;
 162
 163        case OPTION_CALLBACK:
 164        {
 165                const char *p_arg = NULL;
 166                int p_unset;
 167
 168                if (unset)
 169                        p_unset = 1;
 170                else if (opt->flags & PARSE_OPT_NOARG)
 171                        p_unset = 0;
 172                else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
 173                        p_unset = 0;
 174                else if (get_arg(p, opt, flags, &arg))
 175                        return -1;
 176                else {
 177                        p_unset = 0;
 178                        p_arg = arg;
 179                }
 180                if (opt->callback)
 181                        return (*opt->callback)(opt, p_arg, p_unset) ? (-1) : 0;
 182                else
 183                        return (*opt->ll_callback)(p, opt, p_arg, p_unset);
 184        }
 185        case OPTION_INTEGER:
 186                if (unset) {
 187                        *(int *)opt->value = 0;
 188                        return 0;
 189                }
 190                if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
 191                        *(int *)opt->value = opt->defval;
 192                        return 0;
 193                }
 194                if (get_arg(p, opt, flags, &arg))
 195                        return -1;
 196                if (!*arg)
 197                        return error(_("%s expects a numerical value"),
 198                                     optname(opt, flags));
 199                *(int *)opt->value = strtol(arg, (char **)&s, 10);
 200                if (*s)
 201                        return error(_("%s expects a numerical value"),
 202                                     optname(opt, flags));
 203                return 0;
 204
 205        case OPTION_MAGNITUDE:
 206                if (unset) {
 207                        *(unsigned long *)opt->value = 0;
 208                        return 0;
 209                }
 210                if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
 211                        *(unsigned long *)opt->value = opt->defval;
 212                        return 0;
 213                }
 214                if (get_arg(p, opt, flags, &arg))
 215                        return -1;
 216                if (!git_parse_ulong(arg, opt->value))
 217                        return error(_("%s expects a non-negative integer value"
 218                                       " with an optional k/m/g suffix"),
 219                                     optname(opt, flags));
 220                return 0;
 221
 222        default:
 223                BUG("opt->type %d should not happen", opt->type);
 224        }
 225}
 226
 227static enum parse_opt_result parse_short_opt(struct parse_opt_ctx_t *p,
 228                                             const struct option *options)
 229{
 230        const struct option *all_opts = options;
 231        const struct option *numopt = NULL;
 232
 233        for (; options->type != OPTION_END; options++) {
 234                if (options->short_name == *p->opt) {
 235                        p->opt = p->opt[1] ? p->opt + 1 : NULL;
 236                        return get_value(p, options, all_opts, OPT_SHORT);
 237                }
 238
 239                /*
 240                 * Handle the numerical option later, explicit one-digit
 241                 * options take precedence over it.
 242                 */
 243                if (options->type == OPTION_NUMBER)
 244                        numopt = options;
 245        }
 246        if (numopt && isdigit(*p->opt)) {
 247                size_t len = 1;
 248                char *arg;
 249                int rc;
 250
 251                while (isdigit(p->opt[len]))
 252                        len++;
 253                arg = xmemdupz(p->opt, len);
 254                p->opt = p->opt[len] ? p->opt + len : NULL;
 255                if (numopt->callback)
 256                        rc = (*numopt->callback)(numopt, arg, 0) ? (-1) : 0;
 257                else
 258                        rc = (*numopt->ll_callback)(p, numopt, arg, 0);
 259                free(arg);
 260                return rc;
 261        }
 262        return PARSE_OPT_UNKNOWN;
 263}
 264
 265static enum parse_opt_result parse_long_opt(
 266        struct parse_opt_ctx_t *p, const char *arg,
 267        const struct option *options)
 268{
 269        const struct option *all_opts = options;
 270        const char *arg_end = strchrnul(arg, '=');
 271        const struct option *abbrev_option = NULL, *ambiguous_option = NULL;
 272        int abbrev_flags = 0, ambiguous_flags = 0;
 273
 274        for (; options->type != OPTION_END; options++) {
 275                const char *rest, *long_name = options->long_name;
 276                int flags = 0, opt_flags = 0;
 277
 278                if (!long_name)
 279                        continue;
 280
 281again:
 282                if (!skip_prefix(arg, long_name, &rest))
 283                        rest = NULL;
 284                if (options->type == OPTION_ARGUMENT) {
 285                        if (!rest)
 286                                continue;
 287                        if (*rest == '=')
 288                                return error(_("%s takes no value"),
 289                                             optname(options, flags));
 290                        if (*rest)
 291                                continue;
 292                        p->out[p->cpidx++] = arg - 2;
 293                        return PARSE_OPT_DONE;
 294                }
 295                if (!rest) {
 296                        /* abbreviated? */
 297                        if (!(p->flags & PARSE_OPT_KEEP_UNKNOWN) &&
 298                            !strncmp(long_name, arg, arg_end - arg)) {
 299is_abbreviated:
 300                                if (abbrev_option) {
 301                                        /*
 302                                         * If this is abbreviated, it is
 303                                         * ambiguous. So when there is no
 304                                         * exact match later, we need to
 305                                         * error out.
 306                                         */
 307                                        ambiguous_option = abbrev_option;
 308                                        ambiguous_flags = abbrev_flags;
 309                                }
 310                                if (!(flags & OPT_UNSET) && *arg_end)
 311                                        p->opt = arg_end + 1;
 312                                abbrev_option = options;
 313                                abbrev_flags = flags ^ opt_flags;
 314                                continue;
 315                        }
 316                        /* negation allowed? */
 317                        if (options->flags & PARSE_OPT_NONEG)
 318                                continue;
 319                        /* negated and abbreviated very much? */
 320                        if (starts_with("no-", arg)) {
 321                                flags |= OPT_UNSET;
 322                                goto is_abbreviated;
 323                        }
 324                        /* negated? */
 325                        if (!starts_with(arg, "no-")) {
 326                                if (starts_with(long_name, "no-")) {
 327                                        long_name += 3;
 328                                        opt_flags |= OPT_UNSET;
 329                                        goto again;
 330                                }
 331                                continue;
 332                        }
 333                        flags |= OPT_UNSET;
 334                        if (!skip_prefix(arg + 3, long_name, &rest)) {
 335                                /* abbreviated and negated? */
 336                                if (starts_with(long_name, arg + 3))
 337                                        goto is_abbreviated;
 338                                else
 339                                        continue;
 340                        }
 341                }
 342                if (*rest) {
 343                        if (*rest != '=')
 344                                continue;
 345                        p->opt = rest + 1;
 346                }
 347                return get_value(p, options, all_opts, flags ^ opt_flags);
 348        }
 349
 350        if (ambiguous_option) {
 351                error(_("ambiguous option: %s "
 352                        "(could be --%s%s or --%s%s)"),
 353                        arg,
 354                        (ambiguous_flags & OPT_UNSET) ?  "no-" : "",
 355                        ambiguous_option->long_name,
 356                        (abbrev_flags & OPT_UNSET) ?  "no-" : "",
 357                        abbrev_option->long_name);
 358                return PARSE_OPT_HELP;
 359        }
 360        if (abbrev_option)
 361                return get_value(p, abbrev_option, all_opts, abbrev_flags);
 362        return PARSE_OPT_UNKNOWN;
 363}
 364
 365static int parse_nodash_opt(struct parse_opt_ctx_t *p, const char *arg,
 366                            const struct option *options)
 367{
 368        const struct option *all_opts = options;
 369
 370        for (; options->type != OPTION_END; options++) {
 371                if (!(options->flags & PARSE_OPT_NODASH))
 372                        continue;
 373                if (options->short_name == arg[0] && arg[1] == '\0')
 374                        return get_value(p, options, all_opts, OPT_SHORT);
 375        }
 376        return -2;
 377}
 378
 379static void check_typos(const char *arg, const struct option *options)
 380{
 381        if (strlen(arg) < 3)
 382                return;
 383
 384        if (starts_with(arg, "no-")) {
 385                error(_("did you mean `--%s` (with two dashes ?)"), arg);
 386                exit(129);
 387        }
 388
 389        for (; options->type != OPTION_END; options++) {
 390                if (!options->long_name)
 391                        continue;
 392                if (starts_with(options->long_name, arg)) {
 393                        error(_("did you mean `--%s` (with two dashes ?)"), arg);
 394                        exit(129);
 395                }
 396        }
 397}
 398
 399static void parse_options_check(const struct option *opts)
 400{
 401        int err = 0;
 402        char short_opts[128];
 403
 404        memset(short_opts, '\0', sizeof(short_opts));
 405        for (; opts->type != OPTION_END; opts++) {
 406                if ((opts->flags & PARSE_OPT_LASTARG_DEFAULT) &&
 407                    (opts->flags & PARSE_OPT_OPTARG))
 408                        err |= optbug(opts, "uses incompatible flags "
 409                                        "LASTARG_DEFAULT and OPTARG");
 410                if (opts->short_name) {
 411                        if (0x7F <= opts->short_name)
 412                                err |= optbug(opts, "invalid short name");
 413                        else if (short_opts[opts->short_name]++)
 414                                err |= optbug(opts, "short name already used");
 415                }
 416                if (opts->flags & PARSE_OPT_NODASH &&
 417                    ((opts->flags & PARSE_OPT_OPTARG) ||
 418                     !(opts->flags & PARSE_OPT_NOARG) ||
 419                     !(opts->flags & PARSE_OPT_NONEG) ||
 420                     opts->long_name))
 421                        err |= optbug(opts, "uses feature "
 422                                        "not supported for dashless options");
 423                switch (opts->type) {
 424                case OPTION_COUNTUP:
 425                case OPTION_BIT:
 426                case OPTION_NEGBIT:
 427                case OPTION_SET_INT:
 428                case OPTION_NUMBER:
 429                        if ((opts->flags & PARSE_OPT_OPTARG) ||
 430                            !(opts->flags & PARSE_OPT_NOARG))
 431                                err |= optbug(opts, "should not accept an argument");
 432                        break;
 433                case OPTION_CALLBACK:
 434                        if (!opts->callback && !opts->ll_callback)
 435                                BUG("OPTION_CALLBACK needs one callback");
 436                        if (opts->callback && opts->ll_callback)
 437                                BUG("OPTION_CALLBACK can't have two callbacks");
 438                        break;
 439                case OPTION_LOWLEVEL_CALLBACK:
 440                        if (!opts->ll_callback)
 441                                BUG("OPTION_LOWLEVEL_CALLBACK needs a callback");
 442                        if (opts->callback)
 443                                BUG("OPTION_LOWLEVEL_CALLBACK needs no high level callback");
 444                        break;
 445                default:
 446                        ; /* ok. (usually accepts an argument) */
 447                }
 448                if (opts->argh &&
 449                    strcspn(opts->argh, " _") != strlen(opts->argh))
 450                        err |= optbug(opts, "multi-word argh should use dash to separate words");
 451        }
 452        if (err)
 453                exit(128);
 454}
 455
 456void parse_options_start(struct parse_opt_ctx_t *ctx,
 457                         int argc, const char **argv, const char *prefix,
 458                         const struct option *options, int flags)
 459{
 460        memset(ctx, 0, sizeof(*ctx));
 461        ctx->argc = argc;
 462        ctx->argv = argv;
 463        if (!(flags & PARSE_OPT_ONE_SHOT)) {
 464                ctx->argc--;
 465                ctx->argv++;
 466        }
 467        ctx->total = ctx->argc;
 468        ctx->out   = argv;
 469        ctx->prefix = prefix;
 470        ctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0);
 471        ctx->flags = flags;
 472        if ((flags & PARSE_OPT_KEEP_UNKNOWN) &&
 473            (flags & PARSE_OPT_STOP_AT_NON_OPTION) &&
 474            !(flags & PARSE_OPT_ONE_SHOT))
 475                BUG("STOP_AT_NON_OPTION and KEEP_UNKNOWN don't go together");
 476        if ((flags & PARSE_OPT_ONE_SHOT) &&
 477            (flags & PARSE_OPT_KEEP_ARGV0))
 478                BUG("Can't keep argv0 if you don't have it");
 479        parse_options_check(options);
 480}
 481
 482static void show_negated_gitcomp(const struct option *opts, int nr_noopts)
 483{
 484        int printed_dashdash = 0;
 485
 486        for (; opts->type != OPTION_END; opts++) {
 487                int has_unset_form = 0;
 488                const char *name;
 489
 490                if (!opts->long_name)
 491                        continue;
 492                if (opts->flags & (PARSE_OPT_HIDDEN | PARSE_OPT_NOCOMPLETE))
 493                        continue;
 494                if (opts->flags & PARSE_OPT_NONEG)
 495                        continue;
 496
 497                switch (opts->type) {
 498                case OPTION_STRING:
 499                case OPTION_FILENAME:
 500                case OPTION_INTEGER:
 501                case OPTION_MAGNITUDE:
 502                case OPTION_CALLBACK:
 503                case OPTION_BIT:
 504                case OPTION_NEGBIT:
 505                case OPTION_COUNTUP:
 506                case OPTION_SET_INT:
 507                        has_unset_form = 1;
 508                        break;
 509                default:
 510                        break;
 511                }
 512                if (!has_unset_form)
 513                        continue;
 514
 515                if (skip_prefix(opts->long_name, "no-", &name)) {
 516                        if (nr_noopts < 0)
 517                                printf(" --%s", name);
 518                } else if (nr_noopts >= 0) {
 519                        if (nr_noopts && !printed_dashdash) {
 520                                printf(" --");
 521                                printed_dashdash = 1;
 522                        }
 523                        printf(" --no-%s", opts->long_name);
 524                        nr_noopts++;
 525                }
 526        }
 527}
 528
 529static int show_gitcomp(struct parse_opt_ctx_t *ctx,
 530                        const struct option *opts)
 531{
 532        const struct option *original_opts = opts;
 533        int nr_noopts = 0;
 534
 535        for (; opts->type != OPTION_END; opts++) {
 536                const char *suffix = "";
 537
 538                if (!opts->long_name)
 539                        continue;
 540                if (opts->flags & (PARSE_OPT_HIDDEN | PARSE_OPT_NOCOMPLETE))
 541                        continue;
 542
 543                switch (opts->type) {
 544                case OPTION_GROUP:
 545                        continue;
 546                case OPTION_STRING:
 547                case OPTION_FILENAME:
 548                case OPTION_INTEGER:
 549                case OPTION_MAGNITUDE:
 550                case OPTION_CALLBACK:
 551                        if (opts->flags & PARSE_OPT_NOARG)
 552                                break;
 553                        if (opts->flags & PARSE_OPT_OPTARG)
 554                                break;
 555                        if (opts->flags & PARSE_OPT_LASTARG_DEFAULT)
 556                                break;
 557                        suffix = "=";
 558                        break;
 559                default:
 560                        break;
 561                }
 562                if (opts->flags & PARSE_OPT_COMP_ARG)
 563                        suffix = "=";
 564                if (starts_with(opts->long_name, "no-"))
 565                        nr_noopts++;
 566                printf(" --%s%s", opts->long_name, suffix);
 567        }
 568        show_negated_gitcomp(original_opts, -1);
 569        show_negated_gitcomp(original_opts, nr_noopts);
 570        fputc('\n', stdout);
 571        return PARSE_OPT_COMPLETE;
 572}
 573
 574static int usage_with_options_internal(struct parse_opt_ctx_t *,
 575                                       const char * const *,
 576                                       const struct option *, int, int);
 577
 578int parse_options_step(struct parse_opt_ctx_t *ctx,
 579                       const struct option *options,
 580                       const char * const usagestr[])
 581{
 582        int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP);
 583
 584        /* we must reset ->opt, unknown short option leave it dangling */
 585        ctx->opt = NULL;
 586
 587        for (; ctx->argc; ctx->argc--, ctx->argv++) {
 588                const char *arg = ctx->argv[0];
 589
 590                if (ctx->flags & PARSE_OPT_ONE_SHOT &&
 591                    ctx->argc != ctx->total)
 592                        break;
 593
 594                if (*arg != '-' || !arg[1]) {
 595                        if (parse_nodash_opt(ctx, arg, options) == 0)
 596                                continue;
 597                        if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION)
 598                                return PARSE_OPT_NON_OPTION;
 599                        ctx->out[ctx->cpidx++] = ctx->argv[0];
 600                        continue;
 601                }
 602
 603                /* lone -h asks for help */
 604                if (internal_help && ctx->total == 1 && !strcmp(arg + 1, "h"))
 605                        goto show_usage;
 606
 607                /* lone --git-completion-helper is asked by git-completion.bash */
 608                if (ctx->total == 1 && !strcmp(arg + 1, "-git-completion-helper"))
 609                        return show_gitcomp(ctx, options);
 610
 611                if (arg[1] != '-') {
 612                        ctx->opt = arg + 1;
 613                        switch (parse_short_opt(ctx, options)) {
 614                        case PARSE_OPT_ERROR:
 615                                return PARSE_OPT_ERROR;
 616                        case PARSE_OPT_UNKNOWN:
 617                                if (ctx->opt)
 618                                        check_typos(arg + 1, options);
 619                                if (internal_help && *ctx->opt == 'h')
 620                                        goto show_usage;
 621                                goto unknown;
 622                        case PARSE_OPT_NON_OPTION:
 623                        case PARSE_OPT_HELP:
 624                        case PARSE_OPT_COMPLETE:
 625                                BUG("parse_short_opt() cannot return these");
 626                        case PARSE_OPT_DONE:
 627                                break;
 628                        }
 629                        if (ctx->opt)
 630                                check_typos(arg + 1, options);
 631                        while (ctx->opt) {
 632                                switch (parse_short_opt(ctx, options)) {
 633                                case PARSE_OPT_ERROR:
 634                                        return PARSE_OPT_ERROR;
 635                                case PARSE_OPT_UNKNOWN:
 636                                        if (internal_help && *ctx->opt == 'h')
 637                                                goto show_usage;
 638
 639                                        /* fake a short option thing to hide the fact that we may have
 640                                         * started to parse aggregated stuff
 641                                         *
 642                                         * This is leaky, too bad.
 643                                         */
 644                                        ctx->argv[0] = xstrdup(ctx->opt - 1);
 645                                        *(char *)ctx->argv[0] = '-';
 646                                        goto unknown;
 647                                case PARSE_OPT_NON_OPTION:
 648                                case PARSE_OPT_COMPLETE:
 649                                case PARSE_OPT_HELP:
 650                                        BUG("parse_short_opt() cannot return these");
 651                                case PARSE_OPT_DONE:
 652                                        break;
 653                                }
 654                        }
 655                        continue;
 656                }
 657
 658                if (!arg[2]) { /* "--" */
 659                        if (!(ctx->flags & PARSE_OPT_KEEP_DASHDASH)) {
 660                                ctx->argc--;
 661                                ctx->argv++;
 662                        }
 663                        break;
 664                }
 665
 666                if (internal_help && !strcmp(arg + 2, "help-all"))
 667                        return usage_with_options_internal(ctx, usagestr, options, 1, 0);
 668                if (internal_help && !strcmp(arg + 2, "help"))
 669                        goto show_usage;
 670                switch (parse_long_opt(ctx, arg + 2, options)) {
 671                case PARSE_OPT_ERROR:
 672                        return PARSE_OPT_ERROR;
 673                case PARSE_OPT_UNKNOWN:
 674                        goto unknown;
 675                case PARSE_OPT_HELP:
 676                        goto show_usage;
 677                case PARSE_OPT_NON_OPTION:
 678                case PARSE_OPT_COMPLETE:
 679                        BUG("parse_long_opt() cannot return these");
 680                case PARSE_OPT_DONE:
 681                        break;
 682                }
 683                continue;
 684unknown:
 685                if (ctx->flags & PARSE_OPT_ONE_SHOT)
 686                        break;
 687                if (!(ctx->flags & PARSE_OPT_KEEP_UNKNOWN))
 688                        return PARSE_OPT_UNKNOWN;
 689                ctx->out[ctx->cpidx++] = ctx->argv[0];
 690                ctx->opt = NULL;
 691        }
 692        return PARSE_OPT_DONE;
 693
 694 show_usage:
 695        return usage_with_options_internal(ctx, usagestr, options, 0, 0);
 696}
 697
 698int parse_options_end(struct parse_opt_ctx_t *ctx)
 699{
 700        if (ctx->flags & PARSE_OPT_ONE_SHOT)
 701                return ctx->total - ctx->argc;
 702
 703        MOVE_ARRAY(ctx->out + ctx->cpidx, ctx->argv, ctx->argc);
 704        ctx->out[ctx->cpidx + ctx->argc] = NULL;
 705        return ctx->cpidx + ctx->argc;
 706}
 707
 708int parse_options(int argc, const char **argv, const char *prefix,
 709                  const struct option *options, const char * const usagestr[],
 710                  int flags)
 711{
 712        struct parse_opt_ctx_t ctx;
 713
 714        parse_options_start(&ctx, argc, argv, prefix, options, flags);
 715        switch (parse_options_step(&ctx, options, usagestr)) {
 716        case PARSE_OPT_HELP:
 717        case PARSE_OPT_ERROR:
 718                exit(129);
 719        case PARSE_OPT_COMPLETE:
 720                exit(0);
 721        case PARSE_OPT_NON_OPTION:
 722        case PARSE_OPT_DONE:
 723                break;
 724        default: /* PARSE_OPT_UNKNOWN */
 725                if (ctx.argv[0][1] == '-') {
 726                        error(_("unknown option `%s'"), ctx.argv[0] + 2);
 727                } else if (isascii(*ctx.opt)) {
 728                        error(_("unknown switch `%c'"), *ctx.opt);
 729                } else {
 730                        error(_("unknown non-ascii option in string: `%s'"),
 731                              ctx.argv[0]);
 732                }
 733                usage_with_options(usagestr, options);
 734        }
 735
 736        precompose_argv(argc, argv);
 737        return parse_options_end(&ctx);
 738}
 739
 740static int usage_argh(const struct option *opts, FILE *outfile)
 741{
 742        const char *s;
 743        int literal = (opts->flags & PARSE_OPT_LITERAL_ARGHELP) ||
 744                !opts->argh || !!strpbrk(opts->argh, "()<>[]|");
 745        if (opts->flags & PARSE_OPT_OPTARG)
 746                if (opts->long_name)
 747                        s = literal ? "[=%s]" : "[=<%s>]";
 748                else
 749                        s = literal ? "[%s]" : "[<%s>]";
 750        else
 751                s = literal ? " %s" : " <%s>";
 752        return utf8_fprintf(outfile, s, opts->argh ? _(opts->argh) : _("..."));
 753}
 754
 755#define USAGE_OPTS_WIDTH 24
 756#define USAGE_GAP         2
 757
 758static int usage_with_options_internal(struct parse_opt_ctx_t *ctx,
 759                                       const char * const *usagestr,
 760                                       const struct option *opts, int full, int err)
 761{
 762        FILE *outfile = err ? stderr : stdout;
 763        int need_newline;
 764
 765        if (!usagestr)
 766                return PARSE_OPT_HELP;
 767
 768        if (!err && ctx && ctx->flags & PARSE_OPT_SHELL_EVAL)
 769                fprintf(outfile, "cat <<\\EOF\n");
 770
 771        fprintf_ln(outfile, _("usage: %s"), _(*usagestr++));
 772        while (*usagestr && **usagestr)
 773                /*
 774                 * TRANSLATORS: the colon here should align with the
 775                 * one in "usage: %s" translation.
 776                 */
 777                fprintf_ln(outfile, _("   or: %s"), _(*usagestr++));
 778        while (*usagestr) {
 779                if (**usagestr)
 780                        fprintf_ln(outfile, _("    %s"), _(*usagestr));
 781                else
 782                        fputc('\n', outfile);
 783                usagestr++;
 784        }
 785
 786        need_newline = 1;
 787
 788        for (; opts->type != OPTION_END; opts++) {
 789                size_t pos;
 790                int pad;
 791
 792                if (opts->type == OPTION_GROUP) {
 793                        fputc('\n', outfile);
 794                        need_newline = 0;
 795                        if (*opts->help)
 796                                fprintf(outfile, "%s\n", _(opts->help));
 797                        continue;
 798                }
 799                if (!full && (opts->flags & PARSE_OPT_HIDDEN))
 800                        continue;
 801
 802                if (need_newline) {
 803                        fputc('\n', outfile);
 804                        need_newline = 0;
 805                }
 806
 807                pos = fprintf(outfile, "    ");
 808                if (opts->short_name) {
 809                        if (opts->flags & PARSE_OPT_NODASH)
 810                                pos += fprintf(outfile, "%c", opts->short_name);
 811                        else
 812                                pos += fprintf(outfile, "-%c", opts->short_name);
 813                }
 814                if (opts->long_name && opts->short_name)
 815                        pos += fprintf(outfile, ", ");
 816                if (opts->long_name)
 817                        pos += fprintf(outfile, "--%s", opts->long_name);
 818                if (opts->type == OPTION_NUMBER)
 819                        pos += utf8_fprintf(outfile, _("-NUM"));
 820
 821                if ((opts->flags & PARSE_OPT_LITERAL_ARGHELP) ||
 822                    !(opts->flags & PARSE_OPT_NOARG))
 823                        pos += usage_argh(opts, outfile);
 824
 825                if (pos <= USAGE_OPTS_WIDTH)
 826                        pad = USAGE_OPTS_WIDTH - pos;
 827                else {
 828                        fputc('\n', outfile);
 829                        pad = USAGE_OPTS_WIDTH;
 830                }
 831                fprintf(outfile, "%*s%s\n", pad + USAGE_GAP, "", _(opts->help));
 832        }
 833        fputc('\n', outfile);
 834
 835        if (!err && ctx && ctx->flags & PARSE_OPT_SHELL_EVAL)
 836                fputs("EOF\n", outfile);
 837
 838        return PARSE_OPT_HELP;
 839}
 840
 841void NORETURN usage_with_options(const char * const *usagestr,
 842                        const struct option *opts)
 843{
 844        usage_with_options_internal(NULL, usagestr, opts, 0, 1);
 845        exit(129);
 846}
 847
 848void NORETURN usage_msg_opt(const char *msg,
 849                   const char * const *usagestr,
 850                   const struct option *options)
 851{
 852        fprintf(stderr, "fatal: %s\n\n", msg);
 853        usage_with_options(usagestr, options);
 854}
 855
 856const char *optname(const struct option *opt, int flags)
 857{
 858        static struct strbuf sb = STRBUF_INIT;
 859
 860        strbuf_reset(&sb);
 861        if (flags & OPT_SHORT)
 862                strbuf_addf(&sb, "switch `%c'", opt->short_name);
 863        else if (flags & OPT_UNSET)
 864                strbuf_addf(&sb, "option `no-%s'", opt->long_name);
 865        else
 866                strbuf_addf(&sb, "option `%s'", opt->long_name);
 867
 868        return sb.buf;
 869}