Skip to content

Commit

Permalink
parse_options: allocate a new array when concatenating
Browse files Browse the repository at this point in the history
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.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
peff authored and gitster committed Jul 6, 2016
1 parent 0b65a8d commit 023ff39
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 22 deletions.
13 changes: 4 additions & 9 deletions builtin/revert.c
Expand Up @@ -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'),
Expand All @@ -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[] = {
Expand All @@ -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,
Expand Down
29 changes: 17 additions & 12 deletions parse-options-cb.c
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion parse-options.h
Expand Up @@ -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);
Expand Down

0 comments on commit 023ff39

Please sign in to comment.