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