Linux Audio

Check our new training course

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