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. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King committed
Jul 5, 2016 at 16:44 UTC
023ff39b2994804e4a7b2274b22336bdb37d4a54
3 files changed
+22
-22
builtin/revert.c
+4
-9
@@ -76,7 +76,7 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts)
76
const char * const * usage_str = revert_or_cherry_pick_usage(opts);
77
const char *me = action_name(opts);
78
int cmd = 0;
79
- struct option options[] = {
79
+ struct option base_options[] = {
80
OPT_CMDMODE(0, "quit", &cmd, N_("end revert or cherry-pick sequence"), 'q'),
81
OPT_CMDMODE(0, "continue", &cmd, N_("resume revert or cherry-pick sequence"), 'c'),
82
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)
91
N_("option for merge strategy"), option_parse_x),
92
{ OPTION_STRING, 'S', "gpg-sign", &opts->gpg_sign, N_("key-id"),
93
N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
94
- OPT_END(),
95
- OPT_END(),
96
- OPT_END(),
97
- OPT_END(),
98
- OPT_END(),
99
- OPT_END(),
94
+ OPT_END()
95
};
96
+ struct option *options = base_options;
97
98
if (opts->action == REPLAY_PICK) {
99
struct option cp_extra[] = {
@@ -108,8 +104,7 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts)
104
OPT_BOOL(0, "keep-redundant-commits", &opts->keep_redundant_commits, N_("keep redundant, empty commits")),
105
OPT_END(),
106
};
111
- if (parse_options_concat(options, ARRAY_SIZE(options), cp_extra))
112
- die(_("program error"));
107
+ options = parse_options_concat(options, cp_extra);
108
}
109
110
argc = parse_options(argc, argv, NULL, options, usage_str,
parse-options-cb.c
+17
-12
@@ -117,19 +117,24 @@ int parse_opt_tertiary(const struct option *opt, const char *arg, int unset)
117
return 0;
118
}
119
120
-int parse_options_concat(struct option *dst, size_t dst_size, struct option *src)
120
+struct option *parse_options_concat(struct option *a, struct option *b)
121
{
122
- int i, j;
123
-
124
- for (i = 0; i < dst_size; i++)
125
- if (dst[i].type == OPTION_END)
126
- break;
127
- for (j = 0; i < dst_size; i++, j++) {
128
- dst[i] = src[j];
129
- if (src[j].type == OPTION_END)
130
- return 0;
131
- }
132
- return -1;
122
+ struct option *ret;
123
+ size_t i, a_len = 0, b_len = 0;
124
+
125
+ for (i = 0; a[i].type != OPTION_END; i++)
126
+ a_len++;
127
+ for (i = 0; b[i].type != OPTION_END; i++)
128
+ b_len++;
129
+
130
+ ALLOC_ARRAY(ret, st_add3(a_len, b_len, 1));
131
+ for (i = 0; i < a_len; i++)
132
+ ret[i] = a[i];
133
+ for (i = 0; i < b_len; i++)
134
+ ret[a_len + i] = b[i];
135
+ ret[a_len + b_len] = b[b_len]; /* final OPTION_END */
136
+
137
+ return ret;
138
}
139
140
int parse_opt_string_list(const struct option *opt, const char *arg, int unset)
parse-options.h
+1
-1
@@ -215,7 +215,7 @@ extern int parse_options_step(struct parse_opt_ctx_t *ctx,
215
216
extern int parse_options_end(struct parse_opt_ctx_t *ctx);
217
218
-extern int parse_options_concat(struct option *dst, size_t, struct option *src);
218
+extern struct option *parse_options_concat(struct option *a, struct option *b);
219
220
/*----- some often used options -----*/
221
extern int parse_opt_abbrev_cb(const struct option *, const char *, int);