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