parse-options: new option type to treat an option-like parameter as an argument.
This is meant to be used to keep --not and --all during revision parsing. Signed-off-by: Pierre Habouzit <madcoder@debian.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Pierre Habouzit committed
Mar 2, 2008 at 11:35 UTC
580d5bffdea56dfae1e745dbda94f326bb161274
4 files changed
+39
-7
parse-options.c
+19
-7
@@ -6,7 +6,8 @@
6
7
struct optparse_t {
8
const char **argv;
9
- int argc;
9
+ const char **out;
10
+ int argc, cpidx;
11
const char *opt;
12
};
13
@@ -159,6 +160,16 @@ static int parse_long_opt(struct optparse_t *p, const char *arg,
160
continue;
161
162
rest = skip_prefix(arg, options->long_name);
163
+ if (options->type == OPTION_ARGUMENT) {
164
+ if (!rest)
165
+ continue;
166
+ if (*rest == '=')
167
+ return opterror(options, "takes no value", flags);
168
+ if (*rest)
169
+ continue;
170
+ p->out[p->cpidx++] = arg - 2;
171
+ return 0;
172
+ }
173
if (!rest) {
174
/* abbreviated? */
175
if (!strncmp(options->long_name, arg, arg_end - arg)) {
@@ -242,14 +253,13 @@ static NORETURN void usage_with_options_internal(const char * const *,
253
int parse_options(int argc, const char **argv, const struct option *options,
254
const char * const usagestr[], int flags)
255
{
245
- struct optparse_t args = { argv + 1, argc - 1, NULL };
246
- int j = 0;
256
+ struct optparse_t args = { argv + 1, argv, argc - 1, 0, NULL };
257
258
for (; args.argc; args.argc--, args.argv++) {
259
const char *arg = args.argv[0];
260
261
if (*arg != '-' || !arg[1]) {
252
- argv[j++] = args.argv[0];
262
+ args.out[args.cpidx++] = args.argv[0];
263
continue;
264
}
265
@@ -286,9 +296,9 @@ int parse_options(int argc, const char **argv, const struct option *options,
296
usage_with_options(usagestr, options);
297
}
298
289
- memmove(argv + j, args.argv, args.argc * sizeof(*argv));
290
- argv[j + args.argc] = NULL;
291
- return j + args.argc;
299
+ memmove(args.out + args.cpidx, args.argv, args.argc * sizeof(*args.out));
300
+ args.out[args.cpidx + args.argc] = NULL;
301
+ return args.cpidx + args.argc;
302
}
303
304
#define USAGE_OPTS_WIDTH 24
@@ -328,6 +338,8 @@ void usage_with_options_internal(const char * const *usagestr,
338
pos += fprintf(stderr, "--%s", opts->long_name);
339
340
switch (opts->type) {
341
+ case OPTION_ARGUMENT:
342
+ break;
343
case OPTION_INTEGER:
344
if (opts->flags & PARSE_OPT_OPTARG)
345
pos += fprintf(stderr, " [<n>]");
parse-options.h
+2
@@ -4,6 +4,7 @@
4
enum parse_opt_type {
5
/* special types */
6
OPTION_END,
7
+ OPTION_ARGUMENT,
8
OPTION_GROUP,
9
/* options with no arguments */
10
OPTION_BIT,
@@ -84,6 +85,7 @@ struct option {
85
};
86
87
#define OPT_END() { OPTION_END }
88
+#define OPT_ARGUMENT(l, h) { OPTION_ARGUMENT, 0, (l), NULL, NULL, (h) }
89
#define OPT_GROUP(h) { OPTION_GROUP, 0, NULL, NULL, NULL, (h) }
90
#define OPT_BIT(s, l, v, h, b) { OPTION_BIT, (s), (l), (v), NULL, (h), 0, NULL, (b) }
91
#define OPT_BOOLEAN(s, l, v, h) { OPTION_BOOLEAN, (s), (l), (v), NULL, (h) }
t/t0040-parse-options.sh
+16
@@ -21,6 +21,9 @@ string options
21
--st <st> get another string (pervert ordering)
22
-o <str> get another string
23
24
+magic arguments
25
+ --quux means --quux
26
+
27
EOF
28
29
test_expect_success 'test help' '
@@ -114,4 +117,17 @@ test_expect_success 'detect possible typos' '
117
git diff expect.err output.err
118
'
119
120
+cat > expect <<EOF
121
+boolean: 0
122
+integer: 0
123
+string: (not set)
124
+arg 00: --quux
125
+EOF
126
+
127
+test_expect_success 'keep some options as arguments' '
128
+ test-parse-options --quux > output 2> output.err &&
129
+ test ! -s output.err &&
130
+ git diff expect output
131
+'
132
+
133
test_done
test-parse-options.c
+2
@@ -20,6 +20,8 @@ int main(int argc, const char **argv)
20
OPT_STRING(0, "string2", &string, "str", "get another string"),
21
OPT_STRING(0, "st", &string, "st", "get another string (pervert ordering)"),
22
OPT_STRING('o', NULL, &string, "str", "get another string"),
23
+ OPT_GROUP("magic arguments"),
24
+ OPT_ARGUMENT("quux", "means --quux"),
25
OPT_END(),
26
};
27
int i;