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