On Mon, Apr 22, 2019 at 7:23 PM Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> wrote: > @@ -574,6 +615,70 @@ static int show_gitcomp(struct parse_opt_ctx_t *ctx, > return PARSE_OPT_COMPLETE; > } > > +/* > + * Scan and may produce a new option[] array, which should be used > + * instead of the original 'options'. > + * > + * Right now this is only used to preprocess and substitue > + * OPTION_ALIAS. > + */ > +static struct option *preprocess_options(struct parse_opt_ctx_t *ctx, > + const struct option *options) > +{ > + struct option *newopt; > + int i, nr, alias; > + int nr_aliases = 0; > + > + for (nr = 0; options[nr].type != OPTION_END; nr++) { > + if (options[nr].type == OPTION_ALIAS) > + nr_aliases++; > + } > + > + if (!nr_aliases) > + return NULL; > + > + ALLOC_ARRAY(newopt, nr + 1); > + COPY_ARRAY(newopt, options, nr + 1); > + > + /* each alias has two string pointers and NULL */ > + CALLOC_ARRAY(ctx->alias_groups, 3 * (nr_aliases + 1)); > + > + for (alias = 0, i = 0; i < nr; i++) { > + const char *source; > + int j; > + > + if (newopt[i].type != OPTION_ALIAS) > + continue; > + > + if (!newopt[i].long_name) > + BUG("An alias must have long option name"); > + > + source = newopt[i].value; > + > + for (j = 0; j < nr; j++) { > + const char *name = options[j].long_name; > + > + if (!name || strcmp(name, source)) > + continue; > + > + if (options[j].type == OPTION_ALIAS) > + BUG("No please. Nested aliases are not supported."); > + > + memcpy(newopt + i, options + j, sizeof(*newopt)); Eck. I need to restore newopt[i].long_name and .short_name after this memcpy, or we'll just have two --recurse-submodules instead. Luckily it still works after this bug is gone. > + break; > + } -- Duy