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