Skip to content

Commit 580d5bf

Browse files
MadCodergitster
authored andcommitted
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>
1 parent ff962a3 commit 580d5bf

File tree

4 files changed

+39
-7
lines changed

4 files changed

+39
-7
lines changed

parse-options.c

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66

77
struct optparse_t {
88
const char **argv;
9-
int argc;
9+
const char **out;
10+
int argc, cpidx;
1011
const char *opt;
1112
};
1213

@@ -159,6 +160,16 @@ static int parse_long_opt(struct optparse_t *p, const char *arg,
159160
continue;
160161

161162
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+
}
162173
if (!rest) {
163174
/* abbreviated? */
164175
if (!strncmp(options->long_name, arg, arg_end - arg)) {
@@ -242,14 +253,13 @@ static NORETURN void usage_with_options_internal(const char * const *,
242253
int parse_options(int argc, const char **argv, const struct option *options,
243254
const char * const usagestr[], int flags)
244255
{
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 };
247257

248258
for (; args.argc; args.argc--, args.argv++) {
249259
const char *arg = args.argv[0];
250260

251261
if (*arg != '-' || !arg[1]) {
252-
argv[j++] = args.argv[0];
262+
args.out[args.cpidx++] = args.argv[0];
253263
continue;
254264
}
255265

@@ -286,9 +296,9 @@ int parse_options(int argc, const char **argv, const struct option *options,
286296
usage_with_options(usagestr, options);
287297
}
288298

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;
292302
}
293303

294304
#define USAGE_OPTS_WIDTH 24
@@ -328,6 +338,8 @@ void usage_with_options_internal(const char * const *usagestr,
328338
pos += fprintf(stderr, "--%s", opts->long_name);
329339

330340
switch (opts->type) {
341+
case OPTION_ARGUMENT:
342+
break;
331343
case OPTION_INTEGER:
332344
if (opts->flags & PARSE_OPT_OPTARG)
333345
pos += fprintf(stderr, " [<n>]");

parse-options.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
enum parse_opt_type {
55
/* special types */
66
OPTION_END,
7+
OPTION_ARGUMENT,
78
OPTION_GROUP,
89
/* options with no arguments */
910
OPTION_BIT,
@@ -84,6 +85,7 @@ struct option {
8485
};
8586

8687
#define OPT_END() { OPTION_END }
88+
#define OPT_ARGUMENT(l, h) { OPTION_ARGUMENT, 0, (l), NULL, NULL, (h) }
8789
#define OPT_GROUP(h) { OPTION_GROUP, 0, NULL, NULL, NULL, (h) }
8890
#define OPT_BIT(s, l, v, h, b) { OPTION_BIT, (s), (l), (v), NULL, (h), 0, NULL, (b) }
8991
#define OPT_BOOLEAN(s, l, v, h) { OPTION_BOOLEAN, (s), (l), (v), NULL, (h) }

t/t0040-parse-options.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ string options
2121
--st <st> get another string (pervert ordering)
2222
-o <str> get another string
2323
24+
magic arguments
25+
--quux means --quux
26+
2427
EOF
2528

2629
test_expect_success 'test help' '
@@ -114,4 +117,17 @@ test_expect_success 'detect possible typos' '
114117
git diff expect.err output.err
115118
'
116119

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+
117133
test_done

test-parse-options.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ int main(int argc, const char **argv)
2020
OPT_STRING(0, "string2", &string, "str", "get another string"),
2121
OPT_STRING(0, "st", &string, "st", "get another string (pervert ordering)"),
2222
OPT_STRING('o', NULL, &string, "str", "get another string"),
23+
OPT_GROUP("magic arguments"),
24+
OPT_ARGUMENT("quux", "means --quux"),
2325
OPT_END(),
2426
};
2527
int i;

0 commit comments

Comments
 (0)