Skip to content

Commit db7244b

Browse files
MadCodergitster
authored andcommitted
parse-options new features.
options flags: ~~~~~~~~~~~~~ PARSE_OPT_NONEG allow the caller to disallow the negated option to exists. option types: ~~~~~~~~~~~~ OPTION_BIT: ORs (or NANDs) a mask. OPTION_SET_INT: force the value to be set to this integer. OPTION_SET_PTR: force the value to be set to this pointer. helper: ~~~~~~ HAS_MULTI_BITS (in git-compat-util.h) is a bit-hack to check if an unsigned integer has more than one bit set, useful to check if conflicting options have been used. Signed-off-by: Pierre Habouzit <madcoder@debian.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 40e2524 commit db7244b

File tree

3 files changed

+59
-18
lines changed

3 files changed

+59
-18
lines changed

git-compat-util.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#endif
2121

2222
#define MSB(x, bits) ((x) & TYPEOF(x)(~0ULL << (sizeof(x) * 8 - (bits))))
23+
#define HAS_MULTI_BITS(i) ((i) & ((i) - 1)) /* checks if an integer has more than 1 bit set */
2324

2425
/* Approximation of the length of the decimal representation of this type. */
2526
#define decimal_length(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1)

parse-options.c

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -40,24 +40,53 @@ static int get_value(struct optparse_t *p,
4040
const struct option *opt, int flags)
4141
{
4242
const char *s, *arg;
43-
arg = p->opt ? p->opt : (p->argc > 1 ? p->argv[1] : NULL);
43+
const int unset = flags & OPT_UNSET;
4444

45-
if (p->opt && (flags & OPT_UNSET))
45+
if (unset && p->opt)
4646
return opterror(opt, "takes no value", flags);
47+
if (unset && (opt->flags & PARSE_OPT_NONEG))
48+
return opterror(opt, "isn't available", flags);
4749

48-
switch (opt->type) {
49-
case OPTION_BOOLEAN:
50-
if (!(flags & OPT_SHORT) && p->opt)
50+
if (!(flags & OPT_SHORT) && p->opt) {
51+
switch (opt->type) {
52+
case OPTION_CALLBACK:
53+
if (!(opt->flags & PARSE_OPT_NOARG))
54+
break;
55+
/* FALLTHROUGH */
56+
case OPTION_BOOLEAN:
57+
case OPTION_BIT:
58+
case OPTION_SET_INT:
59+
case OPTION_SET_PTR:
5160
return opterror(opt, "takes no value", flags);
52-
if (flags & OPT_UNSET)
53-
*(int *)opt->value = 0;
61+
default:
62+
break;
63+
}
64+
}
65+
66+
arg = p->opt ? p->opt : (p->argc > 1 ? p->argv[1] : NULL);
67+
switch (opt->type) {
68+
case OPTION_BIT:
69+
if (unset)
70+
*(int *)opt->value &= ~opt->defval;
5471
else
55-
(*(int *)opt->value)++;
72+
*(int *)opt->value |= opt->defval;
73+
return 0;
74+
75+
case OPTION_BOOLEAN:
76+
*(int *)opt->value = unset ? 0 : *(int *)opt->value + 1;
77+
return 0;
78+
79+
case OPTION_SET_INT:
80+
*(int *)opt->value = unset ? 0 : opt->defval;
81+
return 0;
82+
83+
case OPTION_SET_PTR:
84+
*(void **)opt->value = unset ? NULL : (void *)opt->defval;
5685
return 0;
5786

5887
case OPTION_STRING:
59-
if (flags & OPT_UNSET) {
60-
*(const char **)opt->value = (const char *)NULL;
88+
if (unset) {
89+
*(const char **)opt->value = NULL;
6190
return 0;
6291
}
6392
if (opt->flags & PARSE_OPT_OPTARG && (!arg || *arg == '-')) {
@@ -70,21 +99,18 @@ static int get_value(struct optparse_t *p,
7099
return 0;
71100

72101
case OPTION_CALLBACK:
73-
if (flags & OPT_UNSET)
102+
if (unset)
74103
return (*opt->callback)(opt, NULL, 1);
75-
if (opt->flags & PARSE_OPT_NOARG) {
76-
if (p->opt && !(flags & OPT_SHORT))
77-
return opterror(opt, "takes no value", flags);
104+
if (opt->flags & PARSE_OPT_NOARG)
78105
return (*opt->callback)(opt, NULL, 0);
79-
}
80106
if (opt->flags & PARSE_OPT_OPTARG && (!arg || *arg == '-'))
81107
return (*opt->callback)(opt, NULL, 0);
82108
if (!arg)
83109
return opterror(opt, "requires a value", flags);
84110
return (*opt->callback)(opt, get_arg(p), 0);
85111

86112
case OPTION_INTEGER:
87-
if (flags & OPT_UNSET) {
113+
if (unset) {
88114
*(int *)opt->value = 0;
89115
return 0;
90116
}
@@ -292,7 +318,7 @@ void usage_with_options(const char * const *usagestr,
292318
pos += fprintf(stderr, " ...");
293319
}
294320
break;
295-
default:
321+
default: /* OPTION_{BIT,BOOLEAN,SET_INT,SET_PTR} */
296322
break;
297323
}
298324

@@ -311,6 +337,7 @@ void usage_with_options(const char * const *usagestr,
311337

312338
/*----- some often used options -----*/
313339
#include "cache.h"
340+
314341
int parse_opt_abbrev_cb(const struct option *opt, const char *arg, int unset)
315342
{
316343
int v;

parse-options.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,15 @@
22
#define PARSE_OPTIONS_H
33

44
enum parse_opt_type {
5+
/* special types */
56
OPTION_END,
67
OPTION_GROUP,
7-
OPTION_BOOLEAN,
8+
/* options with no arguments */
9+
OPTION_BIT,
10+
OPTION_BOOLEAN, /* _INCR would have been a better name */
11+
OPTION_SET_INT,
12+
OPTION_SET_PTR,
13+
/* options with arguments (usually) */
814
OPTION_STRING,
915
OPTION_INTEGER,
1016
OPTION_CALLBACK,
@@ -17,6 +23,7 @@ enum parse_opt_flags {
1723
enum parse_opt_option_flags {
1824
PARSE_OPT_OPTARG = 1,
1925
PARSE_OPT_NOARG = 2,
26+
PARSE_OPT_NONEG = 4,
2027
};
2128

2229
struct option;
@@ -49,12 +56,15 @@ typedef int parse_opt_cb(const struct option *, const char *arg, int unset);
4956
* mask of parse_opt_option_flags.
5057
* PARSE_OPT_OPTARG: says that the argument is optionnal (not for BOOLEANs)
5158
* PARSE_OPT_NOARG: says that this option takes no argument, for CALLBACKs
59+
* PARSE_OPT_NONEG: says that this option cannot be negated
5260
*
5361
* `callback`::
5462
* pointer to the callback to use for OPTION_CALLBACK.
5563
*
5664
* `defval`::
5765
* default value to fill (*->value) with for PARSE_OPT_OPTARG.
66+
* OPTION_{BIT,SET_INT,SET_PTR} store the {mask,integer,pointer} to put in
67+
* the value when met.
5868
* CALLBACKS can use it like they want.
5969
*/
6070
struct option {
@@ -72,7 +82,10 @@ struct option {
7282

7383
#define OPT_END() { OPTION_END }
7484
#define OPT_GROUP(h) { OPTION_GROUP, 0, NULL, NULL, NULL, (h) }
85+
#define OPT_BIT(s, l, v, h, b) { OPTION_BIT, (s), (l), (v), NULL, (h), 0, NULL, (b) }
7586
#define OPT_BOOLEAN(s, l, v, h) { OPTION_BOOLEAN, (s), (l), (v), NULL, (h) }
87+
#define OPT_SET_INT(s, l, v, h, i) { OPTION_SET_INT, (s), (l), (v), NULL, (h), 0, NULL, (i) }
88+
#define OPT_SET_PTR(s, l, v, h, p) { OPTION_SET_PTR, (s), (l), (v), NULL, (h), 0, NULL, (p) }
7689
#define OPT_INTEGER(s, l, v, h) { OPTION_INTEGER, (s), (l), (v), NULL, (h) }
7790
#define OPT_STRING(s, l, v, a, h) { OPTION_STRING, (s), (l), (v), (a), (h) }
7891
#define OPT_CALLBACK(s, l, v, a, h, f) \

0 commit comments

Comments
 (0)