@@ -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
621648static 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