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