Linux-libre 4.19.8-gnu
[librecmc/linux-libre.git] / tools / lib / subcmd / parse-options.c
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/compiler.h>
3 #include <linux/string.h>
4 #include <linux/types.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <stdint.h>
8 #include <string.h>
9 #include <ctype.h>
10 #include "subcmd-util.h"
11 #include "parse-options.h"
12 #include "subcmd-config.h"
13 #include "pager.h"
14
15 #define OPT_SHORT 1
16 #define OPT_UNSET 2
17
18 char *error_buf;
19
20 static int opterror(const struct option *opt, const char *reason, int flags)
21 {
22         if (flags & OPT_SHORT)
23                 fprintf(stderr, " Error: switch `%c' %s", opt->short_name, reason);
24         else if (flags & OPT_UNSET)
25                 fprintf(stderr, " Error: option `no-%s' %s", opt->long_name, reason);
26         else
27                 fprintf(stderr, " Error: option `%s' %s", opt->long_name, reason);
28
29         return -1;
30 }
31
32 static const char *skip_prefix(const char *str, const char *prefix)
33 {
34         size_t len = strlen(prefix);
35         return strncmp(str, prefix, len) ? NULL : str + len;
36 }
37
38 static void optwarning(const struct option *opt, const char *reason, int flags)
39 {
40         if (flags & OPT_SHORT)
41                 fprintf(stderr, " Warning: switch `%c' %s", opt->short_name, reason);
42         else if (flags & OPT_UNSET)
43                 fprintf(stderr, " Warning: option `no-%s' %s", opt->long_name, reason);
44         else
45                 fprintf(stderr, " Warning: option `%s' %s", opt->long_name, reason);
46 }
47
48 static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,
49                    int flags, const char **arg)
50 {
51         const char *res;
52
53         if (p->opt) {
54                 res = p->opt;
55                 p->opt = NULL;
56         } else if ((opt->flags & PARSE_OPT_LASTARG_DEFAULT) && (p->argc == 1 ||
57                     **(p->argv + 1) == '-')) {
58                 res = (const char *)opt->defval;
59         } else if (p->argc > 1) {
60                 p->argc--;
61                 res = *++p->argv;
62         } else
63                 return opterror(opt, "requires a value", flags);
64         if (arg)
65                 *arg = res;
66         return 0;
67 }
68
69 static int get_value(struct parse_opt_ctx_t *p,
70                      const struct option *opt, int flags)
71 {
72         const char *s, *arg = NULL;
73         const int unset = flags & OPT_UNSET;
74         int err;
75
76         if (unset && p->opt)
77                 return opterror(opt, "takes no value", flags);
78         if (unset && (opt->flags & PARSE_OPT_NONEG))
79                 return opterror(opt, "isn't available", flags);
80         if (opt->flags & PARSE_OPT_DISABLED)
81                 return opterror(opt, "is not usable", flags);
82
83         if (opt->flags & PARSE_OPT_EXCLUSIVE) {
84                 if (p->excl_opt && p->excl_opt != opt) {
85                         char msg[128];
86
87                         if (((flags & OPT_SHORT) && p->excl_opt->short_name) ||
88                             p->excl_opt->long_name == NULL) {
89                                 snprintf(msg, sizeof(msg), "cannot be used with switch `%c'",
90                                          p->excl_opt->short_name);
91                         } else {
92                                 snprintf(msg, sizeof(msg), "cannot be used with %s",
93                                          p->excl_opt->long_name);
94                         }
95                         opterror(opt, msg, flags);
96                         return -3;
97                 }
98                 p->excl_opt = opt;
99         }
100         if (!(flags & OPT_SHORT) && p->opt) {
101                 switch (opt->type) {
102                 case OPTION_CALLBACK:
103                         if (!(opt->flags & PARSE_OPT_NOARG))
104                                 break;
105                         /* FALLTHROUGH */
106                 case OPTION_BOOLEAN:
107                 case OPTION_INCR:
108                 case OPTION_BIT:
109                 case OPTION_SET_UINT:
110                 case OPTION_SET_PTR:
111                         return opterror(opt, "takes no value", flags);
112                 case OPTION_END:
113                 case OPTION_ARGUMENT:
114                 case OPTION_GROUP:
115                 case OPTION_STRING:
116                 case OPTION_INTEGER:
117                 case OPTION_UINTEGER:
118                 case OPTION_LONG:
119                 case OPTION_U64:
120                 default:
121                         break;
122                 }
123         }
124
125         if (opt->flags & PARSE_OPT_NOBUILD) {
126                 char reason[128];
127                 bool noarg = false;
128
129                 err = snprintf(reason, sizeof(reason),
130                                 opt->flags & PARSE_OPT_CANSKIP ?
131                                         "is being ignored because %s " :
132                                         "is not available because %s",
133                                 opt->build_opt);
134                 reason[sizeof(reason) - 1] = '\0';
135
136                 if (err < 0)
137                         strncpy(reason, opt->flags & PARSE_OPT_CANSKIP ?
138                                         "is being ignored" :
139                                         "is not available",
140                                         sizeof(reason));
141
142                 if (!(opt->flags & PARSE_OPT_CANSKIP))
143                         return opterror(opt, reason, flags);
144
145                 err = 0;
146                 if (unset)
147                         noarg = true;
148                 if (opt->flags & PARSE_OPT_NOARG)
149                         noarg = true;
150                 if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
151                         noarg = true;
152
153                 switch (opt->type) {
154                 case OPTION_BOOLEAN:
155                 case OPTION_INCR:
156                 case OPTION_BIT:
157                 case OPTION_SET_UINT:
158                 case OPTION_SET_PTR:
159                 case OPTION_END:
160                 case OPTION_ARGUMENT:
161                 case OPTION_GROUP:
162                         noarg = true;
163                         break;
164                 case OPTION_CALLBACK:
165                 case OPTION_STRING:
166                 case OPTION_INTEGER:
167                 case OPTION_UINTEGER:
168                 case OPTION_LONG:
169                 case OPTION_U64:
170                 default:
171                         break;
172                 }
173
174                 if (!noarg)
175                         err = get_arg(p, opt, flags, NULL);
176                 if (err)
177                         return err;
178
179                 optwarning(opt, reason, flags);
180                 return 0;
181         }
182
183         switch (opt->type) {
184         case OPTION_BIT:
185                 if (unset)
186                         *(int *)opt->value &= ~opt->defval;
187                 else
188                         *(int *)opt->value |= opt->defval;
189                 return 0;
190
191         case OPTION_BOOLEAN:
192                 *(bool *)opt->value = unset ? false : true;
193                 if (opt->set)
194                         *(bool *)opt->set = true;
195                 return 0;
196
197         case OPTION_INCR:
198                 *(int *)opt->value = unset ? 0 : *(int *)opt->value + 1;
199                 return 0;
200
201         case OPTION_SET_UINT:
202                 *(unsigned int *)opt->value = unset ? 0 : opt->defval;
203                 return 0;
204
205         case OPTION_SET_PTR:
206                 *(void **)opt->value = unset ? NULL : (void *)opt->defval;
207                 return 0;
208
209         case OPTION_STRING:
210                 err = 0;
211                 if (unset)
212                         *(const char **)opt->value = NULL;
213                 else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
214                         *(const char **)opt->value = (const char *)opt->defval;
215                 else
216                         err = get_arg(p, opt, flags, (const char **)opt->value);
217
218                 if (opt->set)
219                         *(bool *)opt->set = true;
220
221                 /* PARSE_OPT_NOEMPTY: Allow NULL but disallow empty string. */
222                 if (opt->flags & PARSE_OPT_NOEMPTY) {
223                         const char *val = *(const char **)opt->value;
224
225                         if (!val)
226                                 return err;
227
228                         /* Similar to unset if we are given an empty string. */
229                         if (val[0] == '\0') {
230                                 *(const char **)opt->value = NULL;
231                                 return 0;
232                         }
233                 }
234
235                 return err;
236
237         case OPTION_CALLBACK:
238                 if (unset)
239                         return (*opt->callback)(opt, NULL, 1) ? (-1) : 0;
240                 if (opt->flags & PARSE_OPT_NOARG)
241                         return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;
242                 if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
243                         return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;
244                 if (get_arg(p, opt, flags, &arg))
245                         return -1;
246                 return (*opt->callback)(opt, arg, 0) ? (-1) : 0;
247
248         case OPTION_INTEGER:
249                 if (unset) {
250                         *(int *)opt->value = 0;
251                         return 0;
252                 }
253                 if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
254                         *(int *)opt->value = opt->defval;
255                         return 0;
256                 }
257                 if (get_arg(p, opt, flags, &arg))
258                         return -1;
259                 *(int *)opt->value = strtol(arg, (char **)&s, 10);
260                 if (*s)
261                         return opterror(opt, "expects a numerical value", flags);
262                 return 0;
263
264         case OPTION_UINTEGER:
265                 if (unset) {
266                         *(unsigned int *)opt->value = 0;
267                         return 0;
268                 }
269                 if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
270                         *(unsigned int *)opt->value = opt->defval;
271                         return 0;
272                 }
273                 if (get_arg(p, opt, flags, &arg))
274                         return -1;
275                 if (arg[0] == '-')
276                         return opterror(opt, "expects an unsigned numerical value", flags);
277                 *(unsigned int *)opt->value = strtol(arg, (char **)&s, 10);
278                 if (*s)
279                         return opterror(opt, "expects a numerical value", flags);
280                 return 0;
281
282         case OPTION_LONG:
283                 if (unset) {
284                         *(long *)opt->value = 0;
285                         return 0;
286                 }
287                 if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
288                         *(long *)opt->value = opt->defval;
289                         return 0;
290                 }
291                 if (get_arg(p, opt, flags, &arg))
292                         return -1;
293                 *(long *)opt->value = strtol(arg, (char **)&s, 10);
294                 if (*s)
295                         return opterror(opt, "expects a numerical value", flags);
296                 return 0;
297
298         case OPTION_U64:
299                 if (unset) {
300                         *(u64 *)opt->value = 0;
301                         return 0;
302                 }
303                 if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
304                         *(u64 *)opt->value = opt->defval;
305                         return 0;
306                 }
307                 if (get_arg(p, opt, flags, &arg))
308                         return -1;
309                 if (arg[0] == '-')
310                         return opterror(opt, "expects an unsigned numerical value", flags);
311                 *(u64 *)opt->value = strtoull(arg, (char **)&s, 10);
312                 if (*s)
313                         return opterror(opt, "expects a numerical value", flags);
314                 return 0;
315
316         case OPTION_END:
317         case OPTION_ARGUMENT:
318         case OPTION_GROUP:
319         default:
320                 die("should not happen, someone must be hit on the forehead");
321         }
322 }
323
324 static int parse_short_opt(struct parse_opt_ctx_t *p, const struct option *options)
325 {
326 retry:
327         for (; options->type != OPTION_END; options++) {
328                 if (options->short_name == *p->opt) {
329                         p->opt = p->opt[1] ? p->opt + 1 : NULL;
330                         return get_value(p, options, OPT_SHORT);
331                 }
332         }
333
334         if (options->parent) {
335                 options = options->parent;
336                 goto retry;
337         }
338
339         return -2;
340 }
341
342 static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
343                           const struct option *options)
344 {
345         const char *arg_end = strchr(arg, '=');
346         const struct option *abbrev_option = NULL, *ambiguous_option = NULL;
347         int abbrev_flags = 0, ambiguous_flags = 0;
348
349         if (!arg_end)
350                 arg_end = arg + strlen(arg);
351
352 retry:
353         for (; options->type != OPTION_END; options++) {
354                 const char *rest;
355                 int flags = 0;
356
357                 if (!options->long_name)
358                         continue;
359
360                 rest = skip_prefix(arg, options->long_name);
361                 if (options->type == OPTION_ARGUMENT) {
362                         if (!rest)
363                                 continue;
364                         if (*rest == '=')
365                                 return opterror(options, "takes no value", flags);
366                         if (*rest)
367                                 continue;
368                         p->out[p->cpidx++] = arg - 2;
369                         return 0;
370                 }
371                 if (!rest) {
372                         if (strstarts(options->long_name, "no-")) {
373                                 /*
374                                  * The long name itself starts with "no-", so
375                                  * accept the option without "no-" so that users
376                                  * do not have to enter "no-no-" to get the
377                                  * negation.
378                                  */
379                                 rest = skip_prefix(arg, options->long_name + 3);
380                                 if (rest) {
381                                         flags |= OPT_UNSET;
382                                         goto match;
383                                 }
384                                 /* Abbreviated case */
385                                 if (strstarts(options->long_name + 3, arg)) {
386                                         flags |= OPT_UNSET;
387                                         goto is_abbreviated;
388                                 }
389                         }
390                         /* abbreviated? */
391                         if (!strncmp(options->long_name, arg, arg_end - arg)) {
392 is_abbreviated:
393                                 if (abbrev_option) {
394                                         /*
395                                          * If this is abbreviated, it is
396                                          * ambiguous. So when there is no
397                                          * exact match later, we need to
398                                          * error out.
399                                          */
400                                         ambiguous_option = abbrev_option;
401                                         ambiguous_flags = abbrev_flags;
402                                 }
403                                 if (!(flags & OPT_UNSET) && *arg_end)
404                                         p->opt = arg_end + 1;
405                                 abbrev_option = options;
406                                 abbrev_flags = flags;
407                                 continue;
408                         }
409                         /* negated and abbreviated very much? */
410                         if (strstarts("no-", arg)) {
411                                 flags |= OPT_UNSET;
412                                 goto is_abbreviated;
413                         }
414                         /* negated? */
415                         if (strncmp(arg, "no-", 3))
416                                 continue;
417                         flags |= OPT_UNSET;
418                         rest = skip_prefix(arg + 3, options->long_name);
419                         /* abbreviated and negated? */
420                         if (!rest && strstarts(options->long_name, arg + 3))
421                                 goto is_abbreviated;
422                         if (!rest)
423                                 continue;
424                 }
425 match:
426                 if (*rest) {
427                         if (*rest != '=')
428                                 continue;
429                         p->opt = rest + 1;
430                 }
431                 return get_value(p, options, flags);
432         }
433
434         if (ambiguous_option) {
435                  fprintf(stderr,
436                          " Error: Ambiguous option: %s (could be --%s%s or --%s%s)\n",
437                          arg,
438                          (ambiguous_flags & OPT_UNSET) ?  "no-" : "",
439                          ambiguous_option->long_name,
440                          (abbrev_flags & OPT_UNSET) ?  "no-" : "",
441                          abbrev_option->long_name);
442                  return -1;
443         }
444         if (abbrev_option)
445                 return get_value(p, abbrev_option, abbrev_flags);
446
447         if (options->parent) {
448                 options = options->parent;
449                 goto retry;
450         }
451
452         return -2;
453 }
454
455 static void check_typos(const char *arg, const struct option *options)
456 {
457         if (strlen(arg) < 3)
458                 return;
459
460         if (strstarts(arg, "no-")) {
461                 fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)\n", arg);
462                 exit(129);
463         }
464
465         for (; options->type != OPTION_END; options++) {
466                 if (!options->long_name)
467                         continue;
468                 if (strstarts(options->long_name, arg)) {
469                         fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)\n", arg);
470                         exit(129);
471                 }
472         }
473 }
474
475 static void parse_options_start(struct parse_opt_ctx_t *ctx,
476                                 int argc, const char **argv, int flags)
477 {
478         memset(ctx, 0, sizeof(*ctx));
479         ctx->argc = argc - 1;
480         ctx->argv = argv + 1;
481         ctx->out  = argv;
482         ctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0);
483         ctx->flags = flags;
484         if ((flags & PARSE_OPT_KEEP_UNKNOWN) &&
485             (flags & PARSE_OPT_STOP_AT_NON_OPTION))
486                 die("STOP_AT_NON_OPTION and KEEP_UNKNOWN don't go together");
487 }
488
489 static int usage_with_options_internal(const char * const *,
490                                        const struct option *, int,
491                                        struct parse_opt_ctx_t *);
492
493 static int parse_options_step(struct parse_opt_ctx_t *ctx,
494                               const struct option *options,
495                               const char * const usagestr[])
496 {
497         int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP);
498         int excl_short_opt = 1;
499         const char *arg;
500
501         /* we must reset ->opt, unknown short option leave it dangling */
502         ctx->opt = NULL;
503
504         for (; ctx->argc; ctx->argc--, ctx->argv++) {
505                 arg = ctx->argv[0];
506                 if (*arg != '-' || !arg[1]) {
507                         if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION)
508                                 break;
509                         ctx->out[ctx->cpidx++] = ctx->argv[0];
510                         continue;
511                 }
512
513                 if (arg[1] != '-') {
514                         ctx->opt = ++arg;
515                         if (internal_help && *ctx->opt == 'h') {
516                                 return usage_with_options_internal(usagestr, options, 0, ctx);
517                         }
518                         switch (parse_short_opt(ctx, options)) {
519                         case -1:
520                                 return parse_options_usage(usagestr, options, arg, 1);
521                         case -2:
522                                 goto unknown;
523                         case -3:
524                                 goto exclusive;
525                         default:
526                                 break;
527                         }
528                         if (ctx->opt)
529                                 check_typos(arg, options);
530                         while (ctx->opt) {
531                                 if (internal_help && *ctx->opt == 'h')
532                                         return usage_with_options_internal(usagestr, options, 0, ctx);
533                                 arg = ctx->opt;
534                                 switch (parse_short_opt(ctx, options)) {
535                                 case -1:
536                                         return parse_options_usage(usagestr, options, arg, 1);
537                                 case -2:
538                                         /* fake a short option thing to hide the fact that we may have
539                                          * started to parse aggregated stuff
540                                          *
541                                          * This is leaky, too bad.
542                                          */
543                                         ctx->argv[0] = strdup(ctx->opt - 1);
544                                         *(char *)ctx->argv[0] = '-';
545                                         goto unknown;
546                                 case -3:
547                                         goto exclusive;
548                                 default:
549                                         break;
550                                 }
551                         }
552                         continue;
553                 }
554
555                 if (!arg[2]) { /* "--" */
556                         if (!(ctx->flags & PARSE_OPT_KEEP_DASHDASH)) {
557                                 ctx->argc--;
558                                 ctx->argv++;
559                         }
560                         break;
561                 }
562
563                 arg += 2;
564                 if (internal_help && !strcmp(arg, "help-all"))
565                         return usage_with_options_internal(usagestr, options, 1, ctx);
566                 if (internal_help && !strcmp(arg, "help"))
567                         return usage_with_options_internal(usagestr, options, 0, ctx);
568                 if (!strcmp(arg, "list-opts"))
569                         return PARSE_OPT_LIST_OPTS;
570                 if (!strcmp(arg, "list-cmds"))
571                         return PARSE_OPT_LIST_SUBCMDS;
572                 switch (parse_long_opt(ctx, arg, options)) {
573                 case -1:
574                         return parse_options_usage(usagestr, options, arg, 0);
575                 case -2:
576                         goto unknown;
577                 case -3:
578                         excl_short_opt = 0;
579                         goto exclusive;
580                 default:
581                         break;
582                 }
583                 continue;
584 unknown:
585                 if (!(ctx->flags & PARSE_OPT_KEEP_UNKNOWN))
586                         return PARSE_OPT_UNKNOWN;
587                 ctx->out[ctx->cpidx++] = ctx->argv[0];
588                 ctx->opt = NULL;
589         }
590         return PARSE_OPT_DONE;
591
592 exclusive:
593         parse_options_usage(usagestr, options, arg, excl_short_opt);
594         if ((excl_short_opt && ctx->excl_opt->short_name) ||
595             ctx->excl_opt->long_name == NULL) {
596                 char opt = ctx->excl_opt->short_name;
597                 parse_options_usage(NULL, options, &opt, 1);
598         } else {
599                 parse_options_usage(NULL, options, ctx->excl_opt->long_name, 0);
600         }
601         return PARSE_OPT_HELP;
602 }
603
604 static int parse_options_end(struct parse_opt_ctx_t *ctx)
605 {
606         memmove(ctx->out + ctx->cpidx, ctx->argv, ctx->argc * sizeof(*ctx->out));
607         ctx->out[ctx->cpidx + ctx->argc] = NULL;
608         return ctx->cpidx + ctx->argc;
609 }
610
611 int parse_options_subcommand(int argc, const char **argv, const struct option *options,
612                         const char *const subcommands[], const char *usagestr[], int flags)
613 {
614         struct parse_opt_ctx_t ctx;
615
616         /* build usage string if it's not provided */
617         if (subcommands && !usagestr[0]) {
618                 char *buf = NULL;
619
620                 astrcatf(&buf, "%s %s [<options>] {", subcmd_config.exec_name, argv[0]);
621
622                 for (int i = 0; subcommands[i]; i++) {
623                         if (i)
624                                 astrcat(&buf, "|");
625                         astrcat(&buf, subcommands[i]);
626                 }
627                 astrcat(&buf, "}");
628
629                 usagestr[0] = buf;
630         }
631
632         parse_options_start(&ctx, argc, argv, flags);
633         switch (parse_options_step(&ctx, options, usagestr)) {
634         case PARSE_OPT_HELP:
635                 exit(129);
636         case PARSE_OPT_DONE:
637                 break;
638         case PARSE_OPT_LIST_OPTS:
639                 while (options->type != OPTION_END) {
640                         if (options->long_name)
641                                 printf("--%s ", options->long_name);
642                         options++;
643                 }
644                 putchar('\n');
645                 exit(130);
646         case PARSE_OPT_LIST_SUBCMDS:
647                 if (subcommands) {
648                         for (int i = 0; subcommands[i]; i++)
649                                 printf("%s ", subcommands[i]);
650                 }
651                 putchar('\n');
652                 exit(130);
653         default: /* PARSE_OPT_UNKNOWN */
654                 if (ctx.argv[0][1] == '-')
655                         astrcatf(&error_buf, "unknown option `%s'",
656                                  ctx.argv[0] + 2);
657                 else
658                         astrcatf(&error_buf, "unknown switch `%c'", *ctx.opt);
659                 usage_with_options(usagestr, options);
660         }
661
662         return parse_options_end(&ctx);
663 }
664
665 int parse_options(int argc, const char **argv, const struct option *options,
666                   const char * const usagestr[], int flags)
667 {
668         return parse_options_subcommand(argc, argv, options, NULL,
669                                         (const char **) usagestr, flags);
670 }
671
672 #define USAGE_OPTS_WIDTH 24
673 #define USAGE_GAP         2
674
675 static void print_option_help(const struct option *opts, int full)
676 {
677         size_t pos;
678         int pad;
679
680         if (opts->type == OPTION_GROUP) {
681                 fputc('\n', stderr);
682                 if (*opts->help)
683                         fprintf(stderr, "%s\n", opts->help);
684                 return;
685         }
686         if (!full && (opts->flags & PARSE_OPT_HIDDEN))
687                 return;
688         if (opts->flags & PARSE_OPT_DISABLED)
689                 return;
690
691         pos = fprintf(stderr, "    ");
692         if (opts->short_name)
693                 pos += fprintf(stderr, "-%c", opts->short_name);
694         else
695                 pos += fprintf(stderr, "    ");
696
697         if (opts->long_name && opts->short_name)
698                 pos += fprintf(stderr, ", ");
699         if (opts->long_name)
700                 pos += fprintf(stderr, "--%s", opts->long_name);
701
702         switch (opts->type) {
703         case OPTION_ARGUMENT:
704                 break;
705         case OPTION_LONG:
706         case OPTION_U64:
707         case OPTION_INTEGER:
708         case OPTION_UINTEGER:
709                 if (opts->flags & PARSE_OPT_OPTARG)
710                         if (opts->long_name)
711                                 pos += fprintf(stderr, "[=<n>]");
712                         else
713                                 pos += fprintf(stderr, "[<n>]");
714                 else
715                         pos += fprintf(stderr, " <n>");
716                 break;
717         case OPTION_CALLBACK:
718                 if (opts->flags & PARSE_OPT_NOARG)
719                         break;
720                 /* FALLTHROUGH */
721         case OPTION_STRING:
722                 if (opts->argh) {
723                         if (opts->flags & PARSE_OPT_OPTARG)
724                                 if (opts->long_name)
725                                         pos += fprintf(stderr, "[=<%s>]", opts->argh);
726                                 else
727                                         pos += fprintf(stderr, "[<%s>]", opts->argh);
728                         else
729                                 pos += fprintf(stderr, " <%s>", opts->argh);
730                 } else {
731                         if (opts->flags & PARSE_OPT_OPTARG)
732                                 if (opts->long_name)
733                                         pos += fprintf(stderr, "[=...]");
734                                 else
735                                         pos += fprintf(stderr, "[...]");
736                         else
737                                 pos += fprintf(stderr, " ...");
738                 }
739                 break;
740         default: /* OPTION_{BIT,BOOLEAN,SET_UINT,SET_PTR} */
741         case OPTION_END:
742         case OPTION_GROUP:
743         case OPTION_BIT:
744         case OPTION_BOOLEAN:
745         case OPTION_INCR:
746         case OPTION_SET_UINT:
747         case OPTION_SET_PTR:
748                 break;
749         }
750
751         if (pos <= USAGE_OPTS_WIDTH)
752                 pad = USAGE_OPTS_WIDTH - pos;
753         else {
754                 fputc('\n', stderr);
755                 pad = USAGE_OPTS_WIDTH;
756         }
757         fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help);
758         if (opts->flags & PARSE_OPT_NOBUILD)
759                 fprintf(stderr, "%*s(not built-in because %s)\n",
760                         USAGE_OPTS_WIDTH + USAGE_GAP, "",
761                         opts->build_opt);
762 }
763
764 static int option__cmp(const void *va, const void *vb)
765 {
766         const struct option *a = va, *b = vb;
767         int sa = tolower(a->short_name), sb = tolower(b->short_name), ret;
768
769         if (sa == 0)
770                 sa = 'z' + 1;
771         if (sb == 0)
772                 sb = 'z' + 1;
773
774         ret = sa - sb;
775
776         if (ret == 0) {
777                 const char *la = a->long_name ?: "",
778                            *lb = b->long_name ?: "";
779                 ret = strcmp(la, lb);
780         }
781
782         return ret;
783 }
784
785 static struct option *options__order(const struct option *opts)
786 {
787         int nr_opts = 0, len;
788         const struct option *o = opts;
789         struct option *ordered;
790
791         for (o = opts; o->type != OPTION_END; o++)
792                 ++nr_opts;
793
794         len = sizeof(*o) * (nr_opts + 1);
795         ordered = malloc(len);
796         if (!ordered)
797                 goto out;
798         memcpy(ordered, opts, len);
799
800         qsort(ordered, nr_opts, sizeof(*o), option__cmp);
801 out:
802         return ordered;
803 }
804
805 static bool option__in_argv(const struct option *opt, const struct parse_opt_ctx_t *ctx)
806 {
807         int i;
808
809         for (i = 1; i < ctx->argc; ++i) {
810                 const char *arg = ctx->argv[i];
811
812                 if (arg[0] != '-') {
813                         if (arg[1] == '\0') {
814                                 if (arg[0] == opt->short_name)
815                                         return true;
816                                 continue;
817                         }
818
819                         if (opt->long_name && strcmp(opt->long_name, arg) == 0)
820                                 return true;
821
822                         if (opt->help && strcasestr(opt->help, arg) != NULL)
823                                 return true;
824
825                         continue;
826                 }
827
828                 if (arg[1] == opt->short_name ||
829                     (arg[1] == '-' && opt->long_name && strcmp(opt->long_name, arg + 2) == 0))
830                         return true;
831         }
832
833         return false;
834 }
835
836 static int usage_with_options_internal(const char * const *usagestr,
837                                        const struct option *opts, int full,
838                                        struct parse_opt_ctx_t *ctx)
839 {
840         struct option *ordered;
841
842         if (!usagestr)
843                 return PARSE_OPT_HELP;
844
845         setup_pager();
846
847         if (error_buf) {
848                 fprintf(stderr, "  Error: %s\n", error_buf);
849                 zfree(&error_buf);
850         }
851
852         fprintf(stderr, "\n Usage: %s\n", *usagestr++);
853         while (*usagestr && **usagestr)
854                 fprintf(stderr, "    or: %s\n", *usagestr++);
855         while (*usagestr) {
856                 fprintf(stderr, "%s%s\n",
857                                 **usagestr ? "    " : "",
858                                 *usagestr);
859                 usagestr++;
860         }
861
862         if (opts->type != OPTION_GROUP)
863                 fputc('\n', stderr);
864
865         ordered = options__order(opts);
866         if (ordered)
867                 opts = ordered;
868
869         for (  ; opts->type != OPTION_END; opts++) {
870                 if (ctx && ctx->argc > 1 && !option__in_argv(opts, ctx))
871                         continue;
872                 print_option_help(opts, full);
873         }
874
875         fputc('\n', stderr);
876
877         free(ordered);
878
879         return PARSE_OPT_HELP;
880 }
881
882 void usage_with_options(const char * const *usagestr,
883                         const struct option *opts)
884 {
885         usage_with_options_internal(usagestr, opts, 0, NULL);
886         exit(129);
887 }
888
889 void usage_with_options_msg(const char * const *usagestr,
890                             const struct option *opts, const char *fmt, ...)
891 {
892         va_list ap;
893         char *tmp = error_buf;
894
895         va_start(ap, fmt);
896         if (vasprintf(&error_buf, fmt, ap) == -1)
897                 die("vasprintf failed");
898         va_end(ap);
899
900         free(tmp);
901
902         usage_with_options_internal(usagestr, opts, 0, NULL);
903         exit(129);
904 }
905
906 int parse_options_usage(const char * const *usagestr,
907                         const struct option *opts,
908                         const char *optstr, bool short_opt)
909 {
910         if (!usagestr)
911                 goto opt;
912
913         fprintf(stderr, "\n Usage: %s\n", *usagestr++);
914         while (*usagestr && **usagestr)
915                 fprintf(stderr, "    or: %s\n", *usagestr++);
916         while (*usagestr) {
917                 fprintf(stderr, "%s%s\n",
918                                 **usagestr ? "    " : "",
919                                 *usagestr);
920                 usagestr++;
921         }
922         fputc('\n', stderr);
923
924 opt:
925         for (  ; opts->type != OPTION_END; opts++) {
926                 if (short_opt) {
927                         if (opts->short_name == *optstr) {
928                                 print_option_help(opts, 0);
929                                 break;
930                         }
931                         continue;
932                 }
933
934                 if (opts->long_name == NULL)
935                         continue;
936
937                 if (strstarts(opts->long_name, optstr))
938                         print_option_help(opts, 0);
939                 if (strstarts("no-", optstr) &&
940                     strstarts(opts->long_name, optstr + 3))
941                         print_option_help(opts, 0);
942         }
943
944         return PARSE_OPT_HELP;
945 }
946
947
948 int parse_opt_verbosity_cb(const struct option *opt,
949                            const char *arg __maybe_unused,
950                            int unset)
951 {
952         int *target = opt->value;
953
954         if (unset)
955                 /* --no-quiet, --no-verbose */
956                 *target = 0;
957         else if (opt->short_name == 'v') {
958                 if (*target >= 0)
959                         (*target)++;
960                 else
961                         *target = 1;
962         } else {
963                 if (*target <= 0)
964                         (*target)--;
965                 else
966                         *target = -1;
967         }
968         return 0;
969 }
970
971 static struct option *
972 find_option(struct option *opts, int shortopt, const char *longopt)
973 {
974         for (; opts->type != OPTION_END; opts++) {
975                 if ((shortopt && opts->short_name == shortopt) ||
976                     (opts->long_name && longopt &&
977                      !strcmp(opts->long_name, longopt)))
978                         return opts;
979         }
980         return NULL;
981 }
982
983 void set_option_flag(struct option *opts, int shortopt, const char *longopt,
984                      int flag)
985 {
986         struct option *opt = find_option(opts, shortopt, longopt);
987
988         if (opt)
989                 opt->flags |= flag;
990         return;
991 }
992
993 void set_option_nobuild(struct option *opts, int shortopt,
994                         const char *longopt,
995                         const char *build_opt,
996                         bool can_skip)
997 {
998         struct option *opt = find_option(opts, shortopt, longopt);
999
1000         if (!opt)
1001                 return;
1002
1003         opt->flags |= PARSE_OPT_NOBUILD;
1004         opt->flags |= can_skip ? PARSE_OPT_CANSKIP : 0;
1005         opt->build_opt = build_opt;
1006 }