static enum parse_opt_result usage_with_options_internal()

in parse-options.c [772:944]


static enum parse_opt_result usage_with_options_internal(struct parse_opt_ctx_t *,
							 const char * const *,
							 const struct option *,
							 int, int);

enum parse_opt_result parse_options_step(struct parse_opt_ctx_t *ctx,
					 const struct option *options,
					 const char * const usagestr[])
{
	int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP);

	/* we must reset ->opt, unknown short option leave it dangling */
	ctx->opt = NULL;

	for (; ctx->argc; ctx->argc--, ctx->argv++) {
		const char *arg = ctx->argv[0];

		if (ctx->flags & PARSE_OPT_ONE_SHOT &&
		    ctx->argc != ctx->total)
			break;

		if (*arg != '-' || !arg[1]) {
			if (parse_nodash_opt(ctx, arg, options) == 0)
				continue;
			if (!ctx->has_subcommands) {
				if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION)
					return PARSE_OPT_NON_OPTION;
				ctx->out[ctx->cpidx++] = ctx->argv[0];
				continue;
			}
			switch (parse_subcommand(arg, options)) {
			case PARSE_OPT_SUBCOMMAND:
				return PARSE_OPT_SUBCOMMAND;
			case PARSE_OPT_UNKNOWN:
				if (ctx->flags & PARSE_OPT_SUBCOMMAND_OPTIONAL)
					/*
					 * arg is neither a short or long
					 * option nor a subcommand.  Since
					 * this command has a default
					 * operation mode, we have to treat
					 * this arg and all remaining args
					 * as args meant to that default
					 * operation mode.
					 * So we are done parsing.
					 */
					return PARSE_OPT_DONE;
				error(_("unknown subcommand: `%s'"), arg);
				usage_with_options(usagestr, options);
			case PARSE_OPT_COMPLETE:
			case PARSE_OPT_HELP:
			case PARSE_OPT_ERROR:
			case PARSE_OPT_DONE:
			case PARSE_OPT_NON_OPTION:
				/* Impossible. */
				BUG("parse_subcommand() cannot return these");
			}
		}

		/* lone -h asks for help */
		if (internal_help && ctx->total == 1 && !strcmp(arg + 1, "h"))
			goto show_usage;

		/*
		 * lone --git-completion-helper and --git-completion-helper-all
		 * are asked by git-completion.bash
		 */
		if (ctx->total == 1 && !strcmp(arg, "--git-completion-helper"))
			return show_gitcomp(options, 0);
		if (ctx->total == 1 && !strcmp(arg, "--git-completion-helper-all"))
			return show_gitcomp(options, 1);

		if (arg[1] != '-') {
			ctx->opt = arg + 1;
			switch (parse_short_opt(ctx, options)) {
			case PARSE_OPT_ERROR:
				return PARSE_OPT_ERROR;
			case PARSE_OPT_UNKNOWN:
				if (ctx->opt)
					check_typos(arg + 1, options);
				if (internal_help && *ctx->opt == 'h')
					goto show_usage;
				goto unknown;
			case PARSE_OPT_NON_OPTION:
			case PARSE_OPT_SUBCOMMAND:
			case PARSE_OPT_HELP:
			case PARSE_OPT_COMPLETE:
				BUG("parse_short_opt() cannot return these");
			case PARSE_OPT_DONE:
				break;
			}
			if (ctx->opt)
				check_typos(arg + 1, options);
			while (ctx->opt) {
				switch (parse_short_opt(ctx, options)) {
				case PARSE_OPT_ERROR:
					return PARSE_OPT_ERROR;
				case PARSE_OPT_UNKNOWN:
					if (internal_help && *ctx->opt == 'h')
						goto show_usage;

					/* fake a short option thing to hide the fact that we may have
					 * started to parse aggregated stuff
					 *
					 * This is leaky, too bad.
					 */
					ctx->argv[0] = xstrdup(ctx->opt - 1);
					*(char *)ctx->argv[0] = '-';
					goto unknown;
				case PARSE_OPT_NON_OPTION:
				case PARSE_OPT_SUBCOMMAND:
				case PARSE_OPT_COMPLETE:
				case PARSE_OPT_HELP:
					BUG("parse_short_opt() cannot return these");
				case PARSE_OPT_DONE:
					break;
				}
			}
			continue;
		}

		if (!arg[2] /* "--" */ ||
		    !strcmp(arg + 2, "end-of-options")) {
			if (!(ctx->flags & PARSE_OPT_KEEP_DASHDASH)) {
				ctx->argc--;
				ctx->argv++;
			}
			break;
		}

		if (internal_help && !strcmp(arg + 2, "help-all"))
			return usage_with_options_internal(ctx, usagestr, options, 1, 0);
		if (internal_help && !strcmp(arg + 2, "help"))
			goto show_usage;
		switch (parse_long_opt(ctx, arg + 2, options)) {
		case PARSE_OPT_ERROR:
			return PARSE_OPT_ERROR;
		case PARSE_OPT_UNKNOWN:
			goto unknown;
		case PARSE_OPT_HELP:
			goto show_usage;
		case PARSE_OPT_NON_OPTION:
		case PARSE_OPT_SUBCOMMAND:
		case PARSE_OPT_COMPLETE:
			BUG("parse_long_opt() cannot return these");
		case PARSE_OPT_DONE:
			break;
		}
		continue;
unknown:
		if (ctx->flags & PARSE_OPT_ONE_SHOT)
			break;
		if (ctx->has_subcommands &&
		    (ctx->flags & PARSE_OPT_SUBCOMMAND_OPTIONAL) &&
		    (ctx->flags & PARSE_OPT_KEEP_UNKNOWN_OPT)) {
			/*
			 * Found an unknown option given to a command with
			 * subcommands that has a default operation mode:
			 * we treat this option and all remaining args as
			 * arguments meant to that default operation mode.
			 * So we are done parsing.
			 */
			return PARSE_OPT_DONE;
		}
		if (!(ctx->flags & PARSE_OPT_KEEP_UNKNOWN_OPT))
			return PARSE_OPT_UNKNOWN;
		ctx->out[ctx->cpidx++] = ctx->argv[0];
		ctx->opt = NULL;
	}
	return PARSE_OPT_DONE;

 show_usage:
	return usage_with_options_internal(ctx, usagestr, options, 0, 0);
}