Skip to content

Commit 386fe44

Browse files
barroitgitster
authored andcommitted
parseopt: extract subcommand handling from parse_options_step()
Move the subcommand branch out of parse_options_step() into a new handle_subcommand() helper. Also, make parse_subcommand() return a simple success/failure status. This removes the switch over impossible parse_opt_result values and makes the non-option path easier to follow and maintain. Signed-off-by: Jiamu Sun <39@barroit.sh> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent d181b93 commit 386fe44

1 file changed

Lines changed: 46 additions & 41 deletions

File tree

parse-options.c

Lines changed: 46 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -605,17 +605,44 @@ static enum parse_opt_result parse_nodash_opt(struct parse_opt_ctx_t *p,
605605
return PARSE_OPT_ERROR;
606606
}
607607

608-
static enum parse_opt_result parse_subcommand(const char *arg,
609-
const struct option *options)
608+
static int parse_subcommand(const char *arg, const struct option *options)
610609
{
611-
for (; options->type != OPTION_END; options++)
612-
if (options->type == OPTION_SUBCOMMAND &&
613-
!strcmp(options->long_name, arg)) {
614-
*(parse_opt_subcommand_fn **)options->value = options->subcommand_fn;
615-
return PARSE_OPT_SUBCOMMAND;
616-
}
610+
for (; options->type != OPTION_END; options++) {
611+
parse_opt_subcommand_fn **opt_val;
617612

618-
return PARSE_OPT_UNKNOWN;
613+
if (options->type != OPTION_SUBCOMMAND ||
614+
strcmp(options->long_name, arg))
615+
continue;
616+
617+
opt_val = options->value;
618+
*opt_val = options->subcommand_fn;
619+
return 0;
620+
}
621+
622+
return -1;
623+
}
624+
625+
static enum parse_opt_result handle_subcommand(struct parse_opt_ctx_t *ctx,
626+
const char *arg,
627+
const struct option *options,
628+
const char * const usagestr[])
629+
{
630+
int err = parse_subcommand(arg, options);
631+
632+
if (!err)
633+
return PARSE_OPT_SUBCOMMAND;
634+
635+
/*
636+
* arg is neither a short or long option nor a subcommand. Since this
637+
* command has a default operation mode, we have to treat this arg and
638+
* all remaining args as args meant to that default operation mode.
639+
* So we are done parsing.
640+
*/
641+
if (ctx->flags & PARSE_OPT_SUBCOMMAND_OPTIONAL)
642+
return PARSE_OPT_DONE;
643+
644+
error(_("unknown subcommand: `%s'"), arg);
645+
usage_with_options(usagestr, options);
619646
}
620647

621648
static void check_typos(const char *arg, const struct option *options)
@@ -990,38 +1017,16 @@ enum parse_opt_result parse_options_step(struct parse_opt_ctx_t *ctx,
9901017
if (*arg != '-' || !arg[1]) {
9911018
if (parse_nodash_opt(ctx, arg, options) == 0)
9921019
continue;
993-
if (!ctx->has_subcommands) {
994-
if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION)
995-
return PARSE_OPT_NON_OPTION;
996-
ctx->out[ctx->cpidx++] = ctx->argv[0];
997-
continue;
998-
}
999-
switch (parse_subcommand(arg, options)) {
1000-
case PARSE_OPT_SUBCOMMAND:
1001-
return PARSE_OPT_SUBCOMMAND;
1002-
case PARSE_OPT_UNKNOWN:
1003-
if (ctx->flags & PARSE_OPT_SUBCOMMAND_OPTIONAL)
1004-
/*
1005-
* arg is neither a short or long
1006-
* option nor a subcommand. Since
1007-
* this command has a default
1008-
* operation mode, we have to treat
1009-
* this arg and all remaining args
1010-
* as args meant to that default
1011-
* operation mode.
1012-
* So we are done parsing.
1013-
*/
1014-
return PARSE_OPT_DONE;
1015-
error(_("unknown subcommand: `%s'"), arg);
1016-
usage_with_options(usagestr, options);
1017-
case PARSE_OPT_COMPLETE:
1018-
case PARSE_OPT_HELP:
1019-
case PARSE_OPT_ERROR:
1020-
case PARSE_OPT_DONE:
1021-
case PARSE_OPT_NON_OPTION:
1022-
/* Impossible. */
1023-
BUG("parse_subcommand() cannot return these");
1024-
}
1020+
1021+
if (ctx->has_subcommands)
1022+
return handle_subcommand(ctx, arg, options,
1023+
usagestr);
1024+
1025+
if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION)
1026+
return PARSE_OPT_NON_OPTION;
1027+
1028+
ctx->out[ctx->cpidx++] = ctx->argv[0];
1029+
continue;
10251030
}
10261031

10271032
/* lone -h asks for help */

0 commit comments

Comments
 (0)