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