On Tue, Jul 5, 2016 at 1:44 PM, Jeff King <peff@xxxxxxxx> wrote: > On Tue, Jul 05, 2016 at 04:28:20PM -0400, Jeff King wrote: > >> I wonder if parse_options_concat should simply allocate a new list >> (after computing the total required size). I guess this is the only >> caller, though, so perhaps it's not the end of the world. In the >> meantime, your patch is certainly an improvement. > > Something like the patch below. > > I admit this isn't buggy _now_, so this is potentially just churn. It > does make further patches look nicer, though (they don't have to add > apparently meaningless OPT_END() slots). > > -- >8 -- > Subject: [PATCH] parse_options: allocate a new array when concatenating > > In exactly one callers (builtin/revert.c), we build up the > options list dynamically from multiple arrays. We do so by > manually inserting "filler" entries into one array, and then > copying the other array into the allocated space. > > This is tedious and error-prone, as you have to adjust the > filler any time the second array is modified (although we do > at least check and die() when the counts do not match up). > > Instead, let's just allocate a new array. This seems much preferable to me. > > Signed-off-by: Jeff King <peff@xxxxxxxx> > --- > builtin/revert.c | 13 ++++--------- > parse-options-cb.c | 29 +++++++++++++++++------------ > parse-options.h | 2 +- > 3 files changed, 22 insertions(+), 22 deletions(-) > > diff --git a/builtin/revert.c b/builtin/revert.c > index 56a2c36..4e69380 100644 > --- a/builtin/revert.c > +++ b/builtin/revert.c > @@ -76,7 +76,7 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts) > const char * const * usage_str = revert_or_cherry_pick_usage(opts); > const char *me = action_name(opts); > int cmd = 0; > - struct option options[] = { > + struct option base_options[] = { > OPT_CMDMODE(0, "quit", &cmd, N_("end revert or cherry-pick sequence"), 'q'), > OPT_CMDMODE(0, "continue", &cmd, N_("resume revert or cherry-pick sequence"), 'c'), > OPT_CMDMODE(0, "abort", &cmd, N_("cancel revert or cherry-pick sequence"), 'a'), > @@ -91,13 +91,9 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts) > N_("option for merge strategy"), option_parse_x), > { OPTION_STRING, 'S', "gpg-sign", &opts->gpg_sign, N_("key-id"), > N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" }, > - OPT_END(), > - OPT_END(), > - OPT_END(), > - OPT_END(), > - OPT_END(), > - OPT_END(), > + OPT_END() > }; > + struct option *options = base_options; > > if (opts->action == REPLAY_PICK) { > struct option cp_extra[] = { > @@ -108,8 +104,7 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts) > OPT_BOOL(0, "keep-redundant-commits", &opts->keep_redundant_commits, N_("keep redundant, empty commits")), > OPT_END(), > }; > - if (parse_options_concat(options, ARRAY_SIZE(options), cp_extra)) > - die(_("program error")); > + options = parse_options_concat(options, cp_extra); > } > > argc = parse_options(argc, argv, NULL, options, usage_str, > diff --git a/parse-options-cb.c b/parse-options-cb.c > index 239898d..2d87520 100644 > --- a/parse-options-cb.c > +++ b/parse-options-cb.c > @@ -117,19 +117,24 @@ int parse_opt_tertiary(const struct option *opt, const char *arg, int unset) > return 0; > } > > -int parse_options_concat(struct option *dst, size_t dst_size, struct option *src) > +struct option *parse_options_concat(struct option *a, struct option *b) > { > - int i, j; > - > - for (i = 0; i < dst_size; i++) > - if (dst[i].type == OPTION_END) > - break; > - for (j = 0; i < dst_size; i++, j++) { > - dst[i] = src[j]; > - if (src[j].type == OPTION_END) > - return 0; > - } > - return -1; > + struct option *ret; > + size_t i, a_len = 0, b_len = 0; > + > + for (i = 0; a[i].type != OPTION_END; i++) > + a_len++; > + for (i = 0; b[i].type != OPTION_END; i++) > + b_len++; > + > + ALLOC_ARRAY(ret, st_add3(a_len, b_len, 1)); > + for (i = 0; i < a_len; i++) > + ret[i] = a[i]; > + for (i = 0; i < b_len; i++) > + ret[a_len + i] = b[i]; > + ret[a_len + b_len] = b[b_len]; /* final OPTION_END */ > + > + return ret; > } > > int parse_opt_string_list(const struct option *opt, const char *arg, int unset) > diff --git a/parse-options.h b/parse-options.h > index ea4af92..78f8384 100644 > --- a/parse-options.h > +++ b/parse-options.h > @@ -215,7 +215,7 @@ extern int parse_options_step(struct parse_opt_ctx_t *ctx, > > extern int parse_options_end(struct parse_opt_ctx_t *ctx); > > -extern int parse_options_concat(struct option *dst, size_t, struct option *src); > +extern struct option *parse_options_concat(struct option *a, struct option *b); > > /*----- some often used options -----*/ > extern int parse_opt_abbrev_cb(const struct option *, const char *, int); > -- > 2.9.0.320.gd3e6182 > > -- > To unsubscribe from this list: send the line "unsubscribe git" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html