@matheusbsbs / matheus-bagliano / commits / e0319ff5ed
Fork 0

parseopt: add OPT_NUMBER_CALLBACK

Add a way to recognize numerical options. The number is passed to a callback function as a string. Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx> Signed-off-by: Junio C Hamano <gitster@pobox.com>

René Scharfe committed May 7, 2009 at 21:45 UTC e0319ff5ed2b7927302389181449dcd029a26622
5 files changed +63 -1
Documentation/technical/api-parse-options.txt
+8
@@ -170,6 +170,14 @@ There are some macros to easily define options:
170 `OPT_ARGUMENT(long, description)`::
171 Introduce a long-option argument that will be kept in `argv[]`.
172
173 +`OPT_NUMBER_CALLBACK(&var, description, func_ptr)`::
174 + Recognize numerical options like -123 and feed the integer as
175 + if it was an argument to the function given by `func_ptr`.
176 + The result will be put into `var`. There can be only one such
177 + option definition. It cannot be negated and it takes no
178 + arguments. Short options that happen to be digits take
179 + precedence over it.
180 +
181
182 The last element of the array must be `OPT_END()`.
183
parse-options.c
+25 -1
@@ -129,11 +129,33 @@ static int get_value(struct parse_opt_ctx_t *p,
129
130 static int parse_short_opt(struct parse_opt_ctx_t *p, const struct option *options)
131 {
132 + const struct option *numopt = NULL;
133 +
134 for (; options->type != OPTION_END; options++) {
135 if (options->short_name == *p->opt) {
136 p->opt = p->opt[1] ? p->opt + 1 : NULL;
137 return get_value(p, options, OPT_SHORT);
138 }
139 +
140 + /*
141 + * Handle the numerical option later, explicit one-digit
142 + * options take precedence over it.
143 + */
144 + if (options->type == OPTION_NUMBER)
145 + numopt = options;
146 + }
147 + if (numopt && isdigit(*p->opt)) {
148 + size_t len = 1;
149 + char *arg;
150 + int rc;
151 +
152 + while (isdigit(p->opt[len]))
153 + len++;
154 + arg = xmemdupz(p->opt, len);
155 + p->opt = p->opt[len] ? p->opt + len : NULL;
156 + rc = (*numopt->callback)(numopt, arg, 0) ? (-1) : 0;
157 + free(arg);
158 + return rc;
159 }
160 return -2;
161 }
@@ -411,6 +433,8 @@ int usage_with_options_internal(const char * const *usagestr,
433 pos += fprintf(stderr, ", ");
434 if (opts->long_name)
435 pos += fprintf(stderr, "--%s", opts->long_name);
436 + if (opts->type == OPTION_NUMBER)
437 + pos += fprintf(stderr, "-NUM");
438
439 switch (opts->type) {
440 case OPTION_ARGUMENT:
@@ -447,7 +471,7 @@ int usage_with_options_internal(const char * const *usagestr,
471 pos += fprintf(stderr, " ...");
472 }
473 break;
450 - default: /* OPTION_{BIT,BOOLEAN,SET_INT,SET_PTR} */
474 + default: /* OPTION_{BIT,BOOLEAN,NUMBER,SET_INT,SET_PTR} */
475 break;
476 }
477
parse-options.h
+4
@@ -6,6 +6,7 @@ enum parse_opt_type {
6 OPTION_END,
7 OPTION_ARGUMENT,
8 OPTION_GROUP,
9 + OPTION_NUMBER,
10 /* options with no arguments */
11 OPTION_BIT,
12 OPTION_NEGBIT,
@@ -105,6 +106,9 @@ struct option {
106 parse_opt_approxidate_cb }
107 #define OPT_CALLBACK(s, l, v, a, h, f) \
108 { OPTION_CALLBACK, (s), (l), (v), (a), (h), 0, (f) }
109 +#define OPT_NUMBER_CALLBACK(v, h, f) \
110 + { OPTION_NUMBER, 0, NULL, (v), NULL, (h), \
111 + PARSE_OPT_NOARG | PARSE_OPT_NONEG, (f) }
112
113 /* parse_options() will filter out the processed options and leave the
114 * non-option arguments in argv[].
t/t0040-parse-options.sh
+18
@@ -30,6 +30,7 @@ String options
30
31 Magic arguments
32 --quux means --quux
33 + -NUM set integer to NUM
34
35 Standard options
36 --abbrev[=<n>] use <n> digits to display SHA-1s
@@ -275,4 +276,21 @@ test_expect_success 'OPT_NEGBIT() works' '
276 test_cmp expect output
277 '
278
279 +cat > expect <<EOF
280 +boolean: 0
281 +integer: 12345
282 +timestamp: 0
283 +string: (not set)
284 +abbrev: 7
285 +verbose: 0
286 +quiet: no
287 +dry run: no
288 +EOF
289 +
290 +test_expect_success 'OPT_NUMBER_CALLBACK() works' '
291 + test-parse-options -12345 > output 2> output.err &&
292 + test ! -s output.err &&
293 + test_cmp expect output
294 +'
295 +
296 test_done
test-parse-options.c
+8
@@ -19,6 +19,12 @@ int length_callback(const struct option *opt, const char *arg, int unset)
19 return 0;
20 }
21
22 +int number_callback(const struct option *opt, const char *arg, int unset)
23 +{
24 + *(int *)opt->value = strtol(arg, NULL, 10);
25 + return 0;
26 +}
27 +
28 int main(int argc, const char **argv)
29 {
30 const char *usage[] = {
@@ -46,6 +52,8 @@ int main(int argc, const char **argv)
52 "set string to default", (unsigned long)"default"),
53 OPT_GROUP("Magic arguments"),
54 OPT_ARGUMENT("quux", "means --quux"),
55 + OPT_NUMBER_CALLBACK(&integer, "set integer to NUM",
56 + number_callback),
57 OPT_GROUP("Standard options"),
58 OPT__ABBREV(&abbrev),
59 OPT__VERBOSE(&verbose),