Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.15.
   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
  16char *error_buf;
  17
  18static 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
  30static 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
  36static 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
  46static 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
  67static 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
 318static int parse_short_opt(struct parse_opt_ctx_t *p, const struct option *options)
 319{
 320retry:
 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
 336static 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
 346retry:
 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)) {
 386is_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		}
 419match:
 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
 449static 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
 469static 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
 483static int usage_with_options_internal(const char * const *,
 484				       const struct option *, int,
 485				       struct parse_opt_ctx_t *);
 486
 487static 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;
 578unknown:
 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
 586exclusive:
 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
 598static 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
 605int 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
 659int 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
 669static 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
 758static 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
 779static 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);
 795out:
 796	return ordered;
 797}
 798
 799static 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
 830static 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
 876void 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
 883void 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
 900int 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
 918opt:
 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
 942int 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
 965static struct option *
 966find_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
 977void 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
 987void 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}