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