git
/
parse-options.c
1332 строки · 34.9 Кб
1#include "git-compat-util.h"2#include "parse-options.h"3#include "abspath.h"4#include "parse.h"5#include "gettext.h"6#include "strbuf.h"7#include "string-list.h"8#include "utf8.h"9
10static int disallow_abbreviated_options;11
12enum opt_parsed {13OPT_LONG = 0,14OPT_SHORT = 1<<0,15OPT_UNSET = 1<<1,16};17
18static void optbug(const struct option *opt, const char *reason)19{
20if (opt->long_name && opt->short_name)21bug("switch '%c' (--%s) %s", opt->short_name,22opt->long_name, reason);23else if (opt->long_name)24bug("option '%s' %s", opt->long_name, reason);25else26bug("switch '%c' %s", opt->short_name, reason);27}
28
29static const char *optname(const struct option *opt, enum opt_parsed flags)30{
31static struct strbuf sb = STRBUF_INIT;32
33strbuf_reset(&sb);34if (flags & OPT_SHORT)35strbuf_addf(&sb, "switch `%c'", opt->short_name);36else if (flags & OPT_UNSET)37strbuf_addf(&sb, "option `no-%s'", opt->long_name);38else if (flags == OPT_LONG)39strbuf_addf(&sb, "option `%s'", opt->long_name);40else41BUG("optname() got unknown flags %d", flags);42
43return sb.buf;44}
45
46static enum parse_opt_result get_arg(struct parse_opt_ctx_t *p,47const struct option *opt,48enum opt_parsed flags, const char **arg)49{
50if (p->opt) {51*arg = p->opt;52p->opt = NULL;53} else if (p->argc == 1 && (opt->flags & PARSE_OPT_LASTARG_DEFAULT)) {54*arg = (const char *)opt->defval;55} else if (p->argc > 1) {56p->argc--;57*arg = *++p->argv;58} else59return error(_("%s requires a value"), optname(opt, flags));60return 0;61}
62
63static void fix_filename(const char *prefix, char **file)64{
65if (!file || !*file)66; /* leave as NULL */67else68*file = prefix_filename_except_for_dash(prefix, *file);69}
70
71static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p,72const struct option *opt,73enum opt_parsed flags,74const char **argp)75{
76const char *s, *arg;77const int unset = flags & OPT_UNSET;78int err;79
80if (unset && p->opt)81return error(_("%s takes no value"), optname(opt, flags));82if (unset && (opt->flags & PARSE_OPT_NONEG))83return error(_("%s isn't available"), optname(opt, flags));84if (!(flags & OPT_SHORT) && p->opt && (opt->flags & PARSE_OPT_NOARG))85return error(_("%s takes no value"), optname(opt, flags));86
87switch (opt->type) {88case OPTION_LOWLEVEL_CALLBACK:89return opt->ll_callback(p, opt, NULL, unset);90
91case OPTION_BIT:92if (unset)93*(int *)opt->value &= ~opt->defval;94else95*(int *)opt->value |= opt->defval;96return 0;97
98case OPTION_NEGBIT:99if (unset)100*(int *)opt->value |= opt->defval;101else102*(int *)opt->value &= ~opt->defval;103return 0;104
105case OPTION_BITOP:106if (unset)107BUG("BITOP can't have unset form");108*(int *)opt->value &= ~opt->extra;109*(int *)opt->value |= opt->defval;110return 0;111
112case OPTION_COUNTUP:113if (*(int *)opt->value < 0)114*(int *)opt->value = 0;115*(int *)opt->value = unset ? 0 : *(int *)opt->value + 1;116return 0;117
118case OPTION_SET_INT:119*(int *)opt->value = unset ? 0 : opt->defval;120return 0;121
122case OPTION_STRING:123if (unset)124*(const char **)opt->value = NULL;125else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)126*(const char **)opt->value = (const char *)opt->defval;127else128return get_arg(p, opt, flags, (const char **)opt->value);129return 0;130
131case OPTION_FILENAME:132err = 0;133if (unset)134*(const char **)opt->value = NULL;135else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)136*(const char **)opt->value = (const char *)opt->defval;137else138err = get_arg(p, opt, flags, (const char **)opt->value);139
140if (!err)141fix_filename(p->prefix, (char **)opt->value);142return err;143
144case OPTION_CALLBACK:145{146const char *p_arg = NULL;147int p_unset;148
149if (unset)150p_unset = 1;151else if (opt->flags & PARSE_OPT_NOARG)152p_unset = 0;153else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)154p_unset = 0;155else if (get_arg(p, opt, flags, &arg))156return -1;157else {158p_unset = 0;159p_arg = arg;160}161if (opt->flags & PARSE_OPT_CMDMODE)162*argp = p_arg;163if (opt->callback)164return (*opt->callback)(opt, p_arg, p_unset) ? (-1) : 0;165else166return (*opt->ll_callback)(p, opt, p_arg, p_unset);167}168case OPTION_INTEGER:169if (unset) {170*(int *)opt->value = 0;171return 0;172}173if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {174*(int *)opt->value = opt->defval;175return 0;176}177if (get_arg(p, opt, flags, &arg))178return -1;179if (!*arg)180return error(_("%s expects a numerical value"),181optname(opt, flags));182*(int *)opt->value = strtol(arg, (char **)&s, 10);183if (*s)184return error(_("%s expects a numerical value"),185optname(opt, flags));186return 0;187
188case OPTION_MAGNITUDE:189if (unset) {190*(unsigned long *)opt->value = 0;191return 0;192}193if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {194*(unsigned long *)opt->value = opt->defval;195return 0;196}197if (get_arg(p, opt, flags, &arg))198return -1;199if (!git_parse_ulong(arg, opt->value))200return error(_("%s expects a non-negative integer value"201" with an optional k/m/g suffix"),202optname(opt, flags));203return 0;204
205default:206BUG("opt->type %d should not happen", opt->type);207}208}
209
210struct parse_opt_cmdmode_list {211int value, *value_ptr;212const struct option *opt;213const char *arg;214enum opt_parsed flags;215struct parse_opt_cmdmode_list *next;216};217
218static void build_cmdmode_list(struct parse_opt_ctx_t *ctx,219const struct option *opts)220{
221ctx->cmdmode_list = NULL;222
223for (; opts->type != OPTION_END; opts++) {224struct parse_opt_cmdmode_list *elem = ctx->cmdmode_list;225int *value_ptr = opts->value;226
227if (!(opts->flags & PARSE_OPT_CMDMODE) || !value_ptr)228continue;229
230while (elem && elem->value_ptr != value_ptr)231elem = elem->next;232if (elem)233continue;234
235CALLOC_ARRAY(elem, 1);236elem->value_ptr = value_ptr;237elem->value = *value_ptr;238elem->next = ctx->cmdmode_list;239ctx->cmdmode_list = elem;240}241}
242
243static char *optnamearg(const struct option *opt, const char *arg,244enum opt_parsed flags)245{
246if (flags & OPT_SHORT)247return xstrfmt("-%c%s", opt->short_name, arg ? arg : "");248return xstrfmt("--%s%s%s%s", flags & OPT_UNSET ? "no-" : "",249opt->long_name, arg ? "=" : "", arg ? arg : "");250}
251
252static enum parse_opt_result get_value(struct parse_opt_ctx_t *p,253const struct option *opt,254enum opt_parsed flags)255{
256const char *arg = NULL;257enum parse_opt_result result = do_get_value(p, opt, flags, &arg);258struct parse_opt_cmdmode_list *elem = p->cmdmode_list;259char *opt_name, *other_opt_name;260
261for (; elem; elem = elem->next) {262if (*elem->value_ptr == elem->value)263continue;264
265if (elem->opt &&266(elem->opt->flags | opt->flags) & PARSE_OPT_CMDMODE)267break;268
269elem->opt = opt;270elem->arg = arg;271elem->flags = flags;272elem->value = *elem->value_ptr;273}274
275if (result || !elem)276return result;277
278opt_name = optnamearg(opt, arg, flags);279other_opt_name = optnamearg(elem->opt, elem->arg, elem->flags);280error(_("options '%s' and '%s' cannot be used together"),281opt_name, other_opt_name);282free(opt_name);283free(other_opt_name);284return -1;285}
286
287static enum parse_opt_result parse_short_opt(struct parse_opt_ctx_t *p,288const struct option *options)289{
290const struct option *numopt = NULL;291
292for (; options->type != OPTION_END; options++) {293if (options->short_name == *p->opt) {294p->opt = p->opt[1] ? p->opt + 1 : NULL;295return get_value(p, options, OPT_SHORT);296}297
298/*299* Handle the numerical option later, explicit one-digit
300* options take precedence over it.
301*/
302if (options->type == OPTION_NUMBER)303numopt = options;304}305if (numopt && isdigit(*p->opt)) {306size_t len = 1;307char *arg;308int rc;309
310while (isdigit(p->opt[len]))311len++;312arg = xmemdupz(p->opt, len);313p->opt = p->opt[len] ? p->opt + len : NULL;314if (numopt->callback)315rc = (*numopt->callback)(numopt, arg, 0) ? (-1) : 0;316else317rc = (*numopt->ll_callback)(p, numopt, arg, 0);318free(arg);319return rc;320}321return PARSE_OPT_UNKNOWN;322}
323
324static int has_string(const char *it, const char **array)325{
326while (*array)327if (!strcmp(it, *(array++)))328return 1;329return 0;330}
331
332static int is_alias(struct parse_opt_ctx_t *ctx,333const struct option *one_opt,334const struct option *another_opt)335{
336const char **group;337
338if (!ctx->alias_groups)339return 0;340
341if (!one_opt->long_name || !another_opt->long_name)342return 0;343
344for (group = ctx->alias_groups; *group; group += 3) {345/* it and other are from the same family? */346if (has_string(one_opt->long_name, group) &&347has_string(another_opt->long_name, group))348return 1;349}350return 0;351}
352
353struct parsed_option {354const struct option *option;355enum opt_parsed flags;356};357
358static void register_abbrev(struct parse_opt_ctx_t *p,359const struct option *option, enum opt_parsed flags,360struct parsed_option *abbrev,361struct parsed_option *ambiguous)362{
363if (p->flags & PARSE_OPT_KEEP_UNKNOWN_OPT)364return;365if (abbrev->option &&366!(abbrev->flags == flags && is_alias(p, abbrev->option, option))) {367/*368* If this is abbreviated, it is
369* ambiguous. So when there is no
370* exact match later, we need to
371* error out.
372*/
373ambiguous->option = abbrev->option;374ambiguous->flags = abbrev->flags;375}376abbrev->option = option;377abbrev->flags = flags;378}
379
380static enum parse_opt_result parse_long_opt(381struct parse_opt_ctx_t *p, const char *arg,382const struct option *options)383{
384const char *arg_end = strchrnul(arg, '=');385const char *arg_start = arg;386enum opt_parsed flags = OPT_LONG;387int arg_starts_with_no_no = 0;388struct parsed_option abbrev = { .option = NULL, .flags = OPT_LONG };389struct parsed_option ambiguous = { .option = NULL, .flags = OPT_LONG };390
391if (skip_prefix(arg_start, "no-", &arg_start)) {392if (skip_prefix(arg_start, "no-", &arg_start))393arg_starts_with_no_no = 1;394else395flags |= OPT_UNSET;396}397
398for (; options->type != OPTION_END; options++) {399const char *rest, *long_name = options->long_name;400enum opt_parsed opt_flags = OPT_LONG;401int allow_unset = !(options->flags & PARSE_OPT_NONEG);402
403if (options->type == OPTION_SUBCOMMAND)404continue;405if (!long_name)406continue;407
408if (skip_prefix(long_name, "no-", &long_name))409opt_flags |= OPT_UNSET;410else if (arg_starts_with_no_no)411continue;412
413if (((flags ^ opt_flags) & OPT_UNSET) && !allow_unset)414continue;415
416if (skip_prefix(arg_start, long_name, &rest)) {417if (*rest == '=')418p->opt = rest + 1;419else if (*rest)420continue;421return get_value(p, options, flags ^ opt_flags);422}423
424/* abbreviated? */425if (!strncmp(long_name, arg_start, arg_end - arg_start))426register_abbrev(p, options, flags ^ opt_flags,427&abbrev, &ambiguous);428
429/* negated and abbreviated very much? */430if (allow_unset && starts_with("no-", arg))431register_abbrev(p, options, OPT_UNSET ^ opt_flags,432&abbrev, &ambiguous);433}434
435if (disallow_abbreviated_options && (ambiguous.option || abbrev.option))436die("disallowed abbreviated or ambiguous option '%.*s'",437(int)(arg_end - arg), arg);438
439if (ambiguous.option) {440error(_("ambiguous option: %s "441"(could be --%s%s or --%s%s)"),442arg,443(ambiguous.flags & OPT_UNSET) ? "no-" : "",444ambiguous.option->long_name,445(abbrev.flags & OPT_UNSET) ? "no-" : "",446abbrev.option->long_name);447return PARSE_OPT_HELP;448}449if (abbrev.option) {450if (*arg_end)451p->opt = arg_end + 1;452return get_value(p, abbrev.option, abbrev.flags);453}454return PARSE_OPT_UNKNOWN;455}
456
457static enum parse_opt_result parse_nodash_opt(struct parse_opt_ctx_t *p,458const char *arg,459const struct option *options)460{
461for (; options->type != OPTION_END; options++) {462if (!(options->flags & PARSE_OPT_NODASH))463continue;464if (options->short_name == arg[0] && arg[1] == '\0')465return get_value(p, options, OPT_SHORT);466}467return PARSE_OPT_ERROR;468}
469
470static enum parse_opt_result parse_subcommand(const char *arg,471const struct option *options)472{
473for (; options->type != OPTION_END; options++)474if (options->type == OPTION_SUBCOMMAND &&475!strcmp(options->long_name, arg)) {476*(parse_opt_subcommand_fn **)options->value = options->subcommand_fn;477return PARSE_OPT_SUBCOMMAND;478}479
480return PARSE_OPT_UNKNOWN;481}
482
483static void check_typos(const char *arg, const struct option *options)484{
485if (strlen(arg) < 3)486return;487
488if (starts_with(arg, "no-")) {489error(_("did you mean `--%s` (with two dashes)?"), arg);490exit(129);491}492
493for (; options->type != OPTION_END; options++) {494if (!options->long_name)495continue;496if (starts_with(options->long_name, arg)) {497error(_("did you mean `--%s` (with two dashes)?"), arg);498exit(129);499}500}501}
502
503static void parse_options_check(const struct option *opts)504{
505char short_opts[128];506void *subcommand_value = NULL;507
508memset(short_opts, '\0', sizeof(short_opts));509for (; opts->type != OPTION_END; opts++) {510if ((opts->flags & PARSE_OPT_LASTARG_DEFAULT) &&511(opts->flags & PARSE_OPT_OPTARG))512optbug(opts, "uses incompatible flags "513"LASTARG_DEFAULT and OPTARG");514if (opts->short_name) {515if (0x7F <= opts->short_name)516optbug(opts, "invalid short name");517else if (short_opts[opts->short_name]++)518optbug(opts, "short name already used");519}520if (opts->flags & PARSE_OPT_NODASH &&521((opts->flags & PARSE_OPT_OPTARG) ||522!(opts->flags & PARSE_OPT_NOARG) ||523!(opts->flags & PARSE_OPT_NONEG) ||524opts->long_name))525optbug(opts, "uses feature "526"not supported for dashless options");527if (opts->type == OPTION_SET_INT && !opts->defval &&528opts->long_name && !(opts->flags & PARSE_OPT_NONEG))529optbug(opts, "OPTION_SET_INT 0 should not be negatable");530switch (opts->type) {531case OPTION_COUNTUP:532case OPTION_BIT:533case OPTION_NEGBIT:534case OPTION_SET_INT:535case OPTION_NUMBER:536if ((opts->flags & PARSE_OPT_OPTARG) ||537!(opts->flags & PARSE_OPT_NOARG))538optbug(opts, "should not accept an argument");539break;540case OPTION_CALLBACK:541if (!opts->callback && !opts->ll_callback)542optbug(opts, "OPTION_CALLBACK needs one callback");543else if (opts->callback && opts->ll_callback)544optbug(opts, "OPTION_CALLBACK can't have two callbacks");545break;546case OPTION_LOWLEVEL_CALLBACK:547if (!opts->ll_callback)548optbug(opts, "OPTION_LOWLEVEL_CALLBACK needs a callback");549if (opts->callback)550optbug(opts, "OPTION_LOWLEVEL_CALLBACK needs no high level callback");551break;552case OPTION_ALIAS:553optbug(opts, "OPT_ALIAS() should not remain at this point. "554"Are you using parse_options_step() directly?\n"555"That case is not supported yet.");556break;557case OPTION_SUBCOMMAND:558if (!opts->value || !opts->subcommand_fn)559optbug(opts, "OPTION_SUBCOMMAND needs a value and a subcommand function");560if (!subcommand_value)561subcommand_value = opts->value;562else if (subcommand_value != opts->value)563optbug(opts, "all OPTION_SUBCOMMANDs need the same value");564break;565default:566; /* ok. (usually accepts an argument) */567}568if (opts->argh &&569strcspn(opts->argh, " _") != strlen(opts->argh))570optbug(opts, "multi-word argh should use dash to separate words");571}572BUG_if_bug("invalid 'struct option'");573}
574
575static int has_subcommands(const struct option *options)576{
577for (; options->type != OPTION_END; options++)578if (options->type == OPTION_SUBCOMMAND)579return 1;580return 0;581}
582
583static void parse_options_start_1(struct parse_opt_ctx_t *ctx,584int argc, const char **argv, const char *prefix,585const struct option *options,586enum parse_opt_flags flags)587{
588ctx->argc = argc;589ctx->argv = argv;590if (!(flags & PARSE_OPT_ONE_SHOT)) {591ctx->argc--;592ctx->argv++;593}594ctx->total = ctx->argc;595ctx->out = argv;596ctx->prefix = prefix;597ctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0);598ctx->flags = flags;599ctx->has_subcommands = has_subcommands(options);600if (!ctx->has_subcommands && (flags & PARSE_OPT_SUBCOMMAND_OPTIONAL))601BUG("Using PARSE_OPT_SUBCOMMAND_OPTIONAL without subcommands");602if (ctx->has_subcommands) {603if (flags & PARSE_OPT_STOP_AT_NON_OPTION)604BUG("subcommands are incompatible with PARSE_OPT_STOP_AT_NON_OPTION");605if (!(flags & PARSE_OPT_SUBCOMMAND_OPTIONAL)) {606if (flags & PARSE_OPT_KEEP_UNKNOWN_OPT)607BUG("subcommands are incompatible with PARSE_OPT_KEEP_UNKNOWN_OPT unless in combination with PARSE_OPT_SUBCOMMAND_OPTIONAL");608if (flags & PARSE_OPT_KEEP_DASHDASH)609BUG("subcommands are incompatible with PARSE_OPT_KEEP_DASHDASH unless in combination with PARSE_OPT_SUBCOMMAND_OPTIONAL");610}611}612if ((flags & PARSE_OPT_KEEP_UNKNOWN_OPT) &&613(flags & PARSE_OPT_STOP_AT_NON_OPTION) &&614!(flags & PARSE_OPT_ONE_SHOT))615BUG("STOP_AT_NON_OPTION and KEEP_UNKNOWN don't go together");616if ((flags & PARSE_OPT_ONE_SHOT) &&617(flags & PARSE_OPT_KEEP_ARGV0))618BUG("Can't keep argv0 if you don't have it");619parse_options_check(options);620build_cmdmode_list(ctx, options);621}
622
623void parse_options_start(struct parse_opt_ctx_t *ctx,624int argc, const char **argv, const char *prefix,625const struct option *options,626enum parse_opt_flags flags)627{
628memset(ctx, 0, sizeof(*ctx));629parse_options_start_1(ctx, argc, argv, prefix, options, flags);630}
631
632static void show_negated_gitcomp(const struct option *opts, int show_all,633int nr_noopts)634{
635int printed_dashdash = 0;636
637for (; opts->type != OPTION_END; opts++) {638int has_unset_form = 0;639const char *name;640
641if (!opts->long_name)642continue;643if (!show_all &&644(opts->flags & (PARSE_OPT_HIDDEN | PARSE_OPT_NOCOMPLETE)))645continue;646if (opts->flags & PARSE_OPT_NONEG)647continue;648
649switch (opts->type) {650case OPTION_STRING:651case OPTION_FILENAME:652case OPTION_INTEGER:653case OPTION_MAGNITUDE:654case OPTION_CALLBACK:655case OPTION_BIT:656case OPTION_NEGBIT:657case OPTION_COUNTUP:658case OPTION_SET_INT:659has_unset_form = 1;660break;661default:662break;663}664if (!has_unset_form)665continue;666
667if (skip_prefix(opts->long_name, "no-", &name)) {668if (nr_noopts < 0)669printf(" --%s", name);670} else if (nr_noopts >= 0) {671if (nr_noopts && !printed_dashdash) {672printf(" --");673printed_dashdash = 1;674}675printf(" --no-%s", opts->long_name);676nr_noopts++;677}678}679}
680
681static int show_gitcomp(const struct option *opts, int show_all)682{
683const struct option *original_opts = opts;684int nr_noopts = 0;685
686for (; opts->type != OPTION_END; opts++) {687const char *prefix = "--";688const char *suffix = "";689
690if (!opts->long_name)691continue;692if (!show_all &&693(opts->flags & (PARSE_OPT_HIDDEN | PARSE_OPT_NOCOMPLETE | PARSE_OPT_FROM_ALIAS)))694continue;695
696switch (opts->type) {697case OPTION_SUBCOMMAND:698prefix = "";699break;700case OPTION_GROUP:701continue;702case OPTION_STRING:703case OPTION_FILENAME:704case OPTION_INTEGER:705case OPTION_MAGNITUDE:706case OPTION_CALLBACK:707if (opts->flags & PARSE_OPT_NOARG)708break;709if (opts->flags & PARSE_OPT_OPTARG)710break;711if (opts->flags & PARSE_OPT_LASTARG_DEFAULT)712break;713suffix = "=";714break;715default:716break;717}718if (opts->flags & PARSE_OPT_COMP_ARG)719suffix = "=";720if (starts_with(opts->long_name, "no-"))721nr_noopts++;722printf("%s%s%s%s", opts == original_opts ? "" : " ",723prefix, opts->long_name, suffix);724}725show_negated_gitcomp(original_opts, show_all, -1);726show_negated_gitcomp(original_opts, show_all, nr_noopts);727fputc('\n', stdout);728return PARSE_OPT_COMPLETE;729}
730
731/*
732* Scan and may produce a new option[] array, which should be used
733* instead of the original 'options'.
734*
735* Right now this is only used to preprocess and substitute
736* OPTION_ALIAS.
737*
738* The returned options should be freed using free_preprocessed_options.
739*/
740static struct option *preprocess_options(struct parse_opt_ctx_t *ctx,741const struct option *options)742{
743struct option *newopt;744int i, nr, alias;745int nr_aliases = 0;746
747for (nr = 0; options[nr].type != OPTION_END; nr++) {748if (options[nr].type == OPTION_ALIAS)749nr_aliases++;750}751
752if (!nr_aliases)753return NULL;754
755DUP_ARRAY(newopt, options, nr + 1);756
757/* each alias has two string pointers and NULL */758CALLOC_ARRAY(ctx->alias_groups, 3 * (nr_aliases + 1));759
760for (alias = 0, i = 0; i < nr; i++) {761int short_name;762const char *long_name;763const char *source;764struct strbuf help = STRBUF_INIT;765int j;766
767if (newopt[i].type != OPTION_ALIAS)768continue;769
770short_name = newopt[i].short_name;771long_name = newopt[i].long_name;772source = newopt[i].value;773
774if (!long_name)775BUG("An alias must have long option name");776strbuf_addf(&help, _("alias of --%s"), source);777
778for (j = 0; j < nr; j++) {779const char *name = options[j].long_name;780
781if (!name || strcmp(name, source))782continue;783
784if (options[j].type == OPTION_ALIAS)785BUG("No please. Nested aliases are not supported.");786
787memcpy(newopt + i, options + j, sizeof(*newopt));788newopt[i].short_name = short_name;789newopt[i].long_name = long_name;790newopt[i].help = strbuf_detach(&help, NULL);791newopt[i].flags |= PARSE_OPT_FROM_ALIAS;792break;793}794
795if (j == nr)796BUG("could not find source option '%s' of alias '%s'",797source, newopt[i].long_name);798ctx->alias_groups[alias * 3 + 0] = newopt[i].long_name;799ctx->alias_groups[alias * 3 + 1] = options[j].long_name;800ctx->alias_groups[alias * 3 + 2] = NULL;801alias++;802}803
804return newopt;805}
806
807static void free_preprocessed_options(struct option *options)808{
809int i;810
811if (!options)812return;813
814for (i = 0; options[i].type != OPTION_END; i++) {815if (options[i].flags & PARSE_OPT_FROM_ALIAS)816free((void *)options[i].help);817}818free(options);819}
820
821static enum parse_opt_result usage_with_options_internal(struct parse_opt_ctx_t *,822const char * const *,823const struct option *,824int, int);825
826enum parse_opt_result parse_options_step(struct parse_opt_ctx_t *ctx,827const struct option *options,828const char * const usagestr[])829{
830int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP);831
832/* we must reset ->opt, unknown short option leave it dangling */833ctx->opt = NULL;834
835for (; ctx->argc; ctx->argc--, ctx->argv++) {836const char *arg = ctx->argv[0];837
838if (ctx->flags & PARSE_OPT_ONE_SHOT &&839ctx->argc != ctx->total)840break;841
842if (*arg != '-' || !arg[1]) {843if (parse_nodash_opt(ctx, arg, options) == 0)844continue;845if (!ctx->has_subcommands) {846if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION)847return PARSE_OPT_NON_OPTION;848ctx->out[ctx->cpidx++] = ctx->argv[0];849continue;850}851switch (parse_subcommand(arg, options)) {852case PARSE_OPT_SUBCOMMAND:853return PARSE_OPT_SUBCOMMAND;854case PARSE_OPT_UNKNOWN:855if (ctx->flags & PARSE_OPT_SUBCOMMAND_OPTIONAL)856/*857* arg is neither a short or long
858* option nor a subcommand. Since
859* this command has a default
860* operation mode, we have to treat
861* this arg and all remaining args
862* as args meant to that default
863* operation mode.
864* So we are done parsing.
865*/
866return PARSE_OPT_DONE;867error(_("unknown subcommand: `%s'"), arg);868usage_with_options(usagestr, options);869case PARSE_OPT_COMPLETE:870case PARSE_OPT_HELP:871case PARSE_OPT_ERROR:872case PARSE_OPT_DONE:873case PARSE_OPT_NON_OPTION:874/* Impossible. */875BUG("parse_subcommand() cannot return these");876}877}878
879/* lone -h asks for help */880if (internal_help && ctx->total == 1 && !strcmp(arg + 1, "h"))881goto show_usage;882
883/*884* lone --git-completion-helper and --git-completion-helper-all
885* are asked by git-completion.bash
886*/
887if (ctx->total == 1 && !strcmp(arg, "--git-completion-helper"))888return show_gitcomp(options, 0);889if (ctx->total == 1 && !strcmp(arg, "--git-completion-helper-all"))890return show_gitcomp(options, 1);891
892if (arg[1] != '-') {893ctx->opt = arg + 1;894switch (parse_short_opt(ctx, options)) {895case PARSE_OPT_ERROR:896return PARSE_OPT_ERROR;897case PARSE_OPT_UNKNOWN:898if (ctx->opt)899check_typos(arg + 1, options);900if (internal_help && *ctx->opt == 'h')901goto show_usage;902goto unknown;903case PARSE_OPT_NON_OPTION:904case PARSE_OPT_SUBCOMMAND:905case PARSE_OPT_HELP:906case PARSE_OPT_COMPLETE:907BUG("parse_short_opt() cannot return these");908case PARSE_OPT_DONE:909break;910}911if (ctx->opt)912check_typos(arg + 1, options);913while (ctx->opt) {914switch (parse_short_opt(ctx, options)) {915case PARSE_OPT_ERROR:916return PARSE_OPT_ERROR;917case PARSE_OPT_UNKNOWN:918if (internal_help && *ctx->opt == 'h')919goto show_usage;920
921/* fake a short option thing to hide the fact that we may have922* started to parse aggregated stuff
923*
924* This is leaky, too bad.
925*/
926ctx->argv[0] = xstrdup(ctx->opt - 1);927*(char *)ctx->argv[0] = '-';928goto unknown;929case PARSE_OPT_NON_OPTION:930case PARSE_OPT_SUBCOMMAND:931case PARSE_OPT_COMPLETE:932case PARSE_OPT_HELP:933BUG("parse_short_opt() cannot return these");934case PARSE_OPT_DONE:935break;936}937}938continue;939}940
941if (!arg[2] /* "--" */) {942if (!(ctx->flags & PARSE_OPT_KEEP_DASHDASH)) {943ctx->argc--;944ctx->argv++;945}946break;947} else if (!strcmp(arg + 2, "end-of-options")) {948if (!(ctx->flags & PARSE_OPT_KEEP_UNKNOWN_OPT)) {949ctx->argc--;950ctx->argv++;951}952break;953}954
955if (internal_help && !strcmp(arg + 2, "help-all"))956return usage_with_options_internal(ctx, usagestr, options, 1, 0);957if (internal_help && !strcmp(arg + 2, "help"))958goto show_usage;959switch (parse_long_opt(ctx, arg + 2, options)) {960case PARSE_OPT_ERROR:961return PARSE_OPT_ERROR;962case PARSE_OPT_UNKNOWN:963goto unknown;964case PARSE_OPT_HELP:965goto show_usage;966case PARSE_OPT_NON_OPTION:967case PARSE_OPT_SUBCOMMAND:968case PARSE_OPT_COMPLETE:969BUG("parse_long_opt() cannot return these");970case PARSE_OPT_DONE:971break;972}973continue;974unknown:975if (ctx->flags & PARSE_OPT_ONE_SHOT)976break;977if (ctx->has_subcommands &&978(ctx->flags & PARSE_OPT_SUBCOMMAND_OPTIONAL) &&979(ctx->flags & PARSE_OPT_KEEP_UNKNOWN_OPT)) {980/*981* Found an unknown option given to a command with
982* subcommands that has a default operation mode:
983* we treat this option and all remaining args as
984* arguments meant to that default operation mode.
985* So we are done parsing.
986*/
987return PARSE_OPT_DONE;988}989if (!(ctx->flags & PARSE_OPT_KEEP_UNKNOWN_OPT))990return PARSE_OPT_UNKNOWN;991ctx->out[ctx->cpidx++] = ctx->argv[0];992ctx->opt = NULL;993}994return PARSE_OPT_DONE;995
996show_usage:997return usage_with_options_internal(ctx, usagestr, options, 0, 0);998}
999
1000int parse_options_end(struct parse_opt_ctx_t *ctx)1001{
1002if (ctx->flags & PARSE_OPT_ONE_SHOT)1003return ctx->total - ctx->argc;1004
1005MOVE_ARRAY(ctx->out + ctx->cpidx, ctx->argv, ctx->argc);1006ctx->out[ctx->cpidx + ctx->argc] = NULL;1007return ctx->cpidx + ctx->argc;1008}
1009
1010int parse_options(int argc, const char **argv,1011const char *prefix,1012const struct option *options,1013const char * const usagestr[],1014enum parse_opt_flags flags)1015{
1016struct parse_opt_ctx_t ctx;1017struct option *real_options;1018
1019disallow_abbreviated_options =1020git_env_bool("GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS", 0);1021
1022memset(&ctx, 0, sizeof(ctx));1023real_options = preprocess_options(&ctx, options);1024if (real_options)1025options = real_options;1026parse_options_start_1(&ctx, argc, argv, prefix, options, flags);1027switch (parse_options_step(&ctx, options, usagestr)) {1028case PARSE_OPT_HELP:1029case PARSE_OPT_ERROR:1030exit(129);1031case PARSE_OPT_COMPLETE:1032exit(0);1033case PARSE_OPT_NON_OPTION:1034case PARSE_OPT_SUBCOMMAND:1035break;1036case PARSE_OPT_DONE:1037if (ctx.has_subcommands &&1038!(flags & PARSE_OPT_SUBCOMMAND_OPTIONAL)) {1039error(_("need a subcommand"));1040usage_with_options(usagestr, options);1041}1042break;1043case PARSE_OPT_UNKNOWN:1044if (ctx.argv[0][1] == '-') {1045error(_("unknown option `%s'"), ctx.argv[0] + 2);1046} else if (isascii(*ctx.opt)) {1047error(_("unknown switch `%c'"), *ctx.opt);1048} else {1049error(_("unknown non-ascii option in string: `%s'"),1050ctx.argv[0]);1051}1052usage_with_options(usagestr, options);1053}1054
1055precompose_argv_prefix(argc, argv, NULL);1056free_preprocessed_options(real_options);1057free(ctx.alias_groups);1058for (struct parse_opt_cmdmode_list *elem = ctx.cmdmode_list; elem;) {1059struct parse_opt_cmdmode_list *next = elem->next;1060free(elem);1061elem = next;1062}1063return parse_options_end(&ctx);1064}
1065
1066static int usage_argh(const struct option *opts, FILE *outfile)1067{
1068const char *s;1069int literal = (opts->flags & PARSE_OPT_LITERAL_ARGHELP) ||1070!opts->argh || !!strpbrk(opts->argh, "()<>[]|");1071if (opts->flags & PARSE_OPT_OPTARG)1072if (opts->long_name)1073s = literal ? "[=%s]" : "[=<%s>]";1074else1075s = literal ? "[%s]" : "[<%s>]";1076else1077s = literal ? " %s" : " <%s>";1078return utf8_fprintf(outfile, s, opts->argh ? _(opts->argh) : _("..."));1079}
1080
1081static int usage_indent(FILE *outfile)1082{
1083return fprintf(outfile, " ");1084}
1085
1086#define USAGE_OPTS_WIDTH 261087
1088static void usage_padding(FILE *outfile, size_t pos)1089{
1090if (pos < USAGE_OPTS_WIDTH)1091fprintf(outfile, "%*s", USAGE_OPTS_WIDTH - (int)pos, "");1092else1093fprintf(outfile, "\n%*s", USAGE_OPTS_WIDTH, "");1094}
1095
1096static const struct option *find_option_by_long_name(const struct option *opts,1097const char *long_name)1098{
1099for (; opts->type != OPTION_END; opts++) {1100if (opts->long_name && !strcmp(opts->long_name, long_name))1101return opts;1102}1103return NULL;1104}
1105
1106static enum parse_opt_result usage_with_options_internal(struct parse_opt_ctx_t *ctx,1107const char * const *usagestr,1108const struct option *opts,1109int full, int err)1110{
1111const struct option *all_opts = opts;1112FILE *outfile = err ? stderr : stdout;1113int need_newline;1114
1115const char *usage_prefix = _("usage: %s");1116/*1117* The translation could be anything, but we can count on
1118* msgfmt(1)'s --check option to have asserted that "%s" is in
1119* the translation. So compute the length of the "usage: "
1120* part. We are assuming that the translator wasn't overly
1121* clever and used e.g. "%1$s" instead of "%s", there's only
1122* one "%s" in "usage_prefix" above, so there's no reason to
1123* do so even with a RTL language.
1124*/
1125size_t usage_len = strlen(usage_prefix) - strlen("%s");1126/*1127* TRANSLATORS: the colon here should align with the
1128* one in "usage: %s" translation.
1129*/
1130const char *or_prefix = _(" or: %s");1131/*1132* TRANSLATORS: You should only need to translate this format
1133* string if your language is a RTL language (e.g. Arabic,
1134* Hebrew etc.), not if it's a LTR language (e.g. German,
1135* Russian, Chinese etc.).
1136*
1137* When a translated usage string has an embedded "\n" it's
1138* because options have wrapped to the next line. The line
1139* after the "\n" will then be padded to align with the
1140* command name, such as N_("git cmd [opt]\n<8
1141* spaces>[opt2]"), where the 8 spaces are the same length as
1142* "git cmd ".
1143*
1144* This format string prints out that already-translated
1145* line. The "%*s" is whitespace padding to account for the
1146* padding at the start of the line that we add in this
1147* function. The "%s" is a line in the (hopefully already
1148* translated) N_() usage string, which contained embedded
1149* newlines before we split it up.
1150*/
1151const char *usage_continued = _("%*s%s");1152const char *prefix = usage_prefix;1153int saw_empty_line = 0;1154
1155if (!usagestr)1156return PARSE_OPT_HELP;1157
1158if (!err && ctx && ctx->flags & PARSE_OPT_SHELL_EVAL)1159fprintf(outfile, "cat <<\\EOF\n");1160
1161while (*usagestr) {1162const char *str = _(*usagestr++);1163struct string_list list = STRING_LIST_INIT_DUP;1164unsigned int j;1165
1166if (!saw_empty_line && !*str)1167saw_empty_line = 1;1168
1169string_list_split(&list, str, '\n', -1);1170for (j = 0; j < list.nr; j++) {1171const char *line = list.items[j].string;1172
1173if (saw_empty_line && *line)1174fprintf_ln(outfile, _(" %s"), line);1175else if (saw_empty_line)1176fputc('\n', outfile);1177else if (!j)1178fprintf_ln(outfile, prefix, line);1179else1180fprintf_ln(outfile, usage_continued,1181(int)usage_len, "", line);1182}1183string_list_clear(&list, 0);1184
1185prefix = or_prefix;1186}1187
1188need_newline = 1;1189
1190for (; opts->type != OPTION_END; opts++) {1191size_t pos;1192const char *cp, *np;1193const char *positive_name = NULL;1194
1195if (opts->type == OPTION_SUBCOMMAND)1196continue;1197if (opts->type == OPTION_GROUP) {1198fputc('\n', outfile);1199need_newline = 0;1200if (*opts->help)1201fprintf(outfile, "%s\n", _(opts->help));1202continue;1203}1204if (!full && (opts->flags & PARSE_OPT_HIDDEN))1205continue;1206
1207if (need_newline) {1208fputc('\n', outfile);1209need_newline = 0;1210}1211
1212pos = usage_indent(outfile);1213if (opts->short_name) {1214if (opts->flags & PARSE_OPT_NODASH)1215pos += fprintf(outfile, "%c", opts->short_name);1216else1217pos += fprintf(outfile, "-%c", opts->short_name);1218}1219if (opts->long_name && opts->short_name)1220pos += fprintf(outfile, ", ");1221if (opts->long_name) {1222const char *long_name = opts->long_name;1223if ((opts->flags & PARSE_OPT_NONEG) ||1224skip_prefix(long_name, "no-", &positive_name))1225pos += fprintf(outfile, "--%s", long_name);1226else1227pos += fprintf(outfile, "--[no-]%s", long_name);1228}1229
1230if (opts->type == OPTION_NUMBER)1231pos += utf8_fprintf(outfile, _("-NUM"));1232
1233if ((opts->flags & PARSE_OPT_LITERAL_ARGHELP) ||1234!(opts->flags & PARSE_OPT_NOARG))1235pos += usage_argh(opts, outfile);1236
1237if (opts->type == OPTION_ALIAS) {1238usage_padding(outfile, pos);1239fprintf_ln(outfile, _("alias of --%s"),1240(const char *)opts->value);1241continue;1242}1243
1244for (cp = opts->help ? _(opts->help) : ""; *cp; cp = np) {1245np = strchrnul(cp, '\n');1246if (*np)1247np++;1248usage_padding(outfile, pos);1249fwrite(cp, 1, np - cp, outfile);1250pos = 0;1251}1252fputc('\n', outfile);1253
1254if (positive_name) {1255if (find_option_by_long_name(all_opts, positive_name))1256continue;1257pos = usage_indent(outfile);1258pos += fprintf(outfile, "--%s", positive_name);1259usage_padding(outfile, pos);1260fprintf_ln(outfile, _("opposite of --no-%s"),1261positive_name);1262}1263}1264fputc('\n', outfile);1265
1266if (!err && ctx && ctx->flags & PARSE_OPT_SHELL_EVAL)1267fputs("EOF\n", outfile);1268
1269return PARSE_OPT_HELP;1270}
1271
1272void NORETURN usage_with_options(const char * const *usagestr,1273const struct option *opts)1274{
1275usage_with_options_internal(NULL, usagestr, opts, 0, 1);1276exit(129);1277}
1278
1279void NORETURN usage_msg_opt(const char *msg,1280const char * const *usagestr,1281const struct option *options)1282{
1283die_message("%s\n", msg); /* The extra \n is intentional */1284usage_with_options(usagestr, options);1285}
1286
1287void NORETURN usage_msg_optf(const char * const fmt,1288const char * const *usagestr,1289const struct option *options, ...)1290{
1291struct strbuf msg = STRBUF_INIT;1292va_list ap;1293va_start(ap, options);1294strbuf_vaddf(&msg, fmt, ap);1295va_end(ap);1296
1297usage_msg_opt(msg.buf, usagestr, options);1298}
1299
1300void die_for_incompatible_opt4(int opt1, const char *opt1_name,1301int opt2, const char *opt2_name,1302int opt3, const char *opt3_name,1303int opt4, const char *opt4_name)1304{
1305int count = 0;1306const char *options[4];1307
1308if (opt1)1309options[count++] = opt1_name;1310if (opt2)1311options[count++] = opt2_name;1312if (opt3)1313options[count++] = opt3_name;1314if (opt4)1315options[count++] = opt4_name;1316switch (count) {1317case 4:1318die(_("options '%s', '%s', '%s', and '%s' cannot be used together"),1319opt1_name, opt2_name, opt3_name, opt4_name);1320break;1321case 3:1322die(_("options '%s', '%s', and '%s' cannot be used together"),1323options[0], options[1], options[2]);1324break;1325case 2:1326die(_("options '%s' and '%s' cannot be used together"),1327options[0], options[1]);1328break;1329default:1330break;1331}1332}
1333