Browse Source

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>
maint
René Scharfe 16 years ago committed by Junio C Hamano
parent
commit
e0319ff5ed
  1. 8
      Documentation/technical/api-parse-options.txt
  2. 26
      parse-options.c
  3. 4
      parse-options.h
  4. 18
      t/t0040-parse-options.sh
  5. 8
      test-parse-options.c

8
Documentation/technical/api-parse-options.txt

@ -170,6 +170,14 @@ There are some macros to easily define options: @@ -170,6 +170,14 @@ There are some macros to easily define options:
`OPT_ARGUMENT(long, description)`::
Introduce a long-option argument that will be kept in `argv[]`.

`OPT_NUMBER_CALLBACK(&var, description, func_ptr)`::
Recognize numerical options like -123 and feed the integer as
if it was an argument to the function given by `func_ptr`.
The result will be put into `var`. There can be only one such
option definition. It cannot be negated and it takes no
arguments. Short options that happen to be digits take
precedence over it.


The last element of the array must be `OPT_END()`.


26
parse-options.c

@ -129,11 +129,33 @@ static int get_value(struct parse_opt_ctx_t *p, @@ -129,11 +129,33 @@ static int get_value(struct parse_opt_ctx_t *p,

static int parse_short_opt(struct parse_opt_ctx_t *p, const struct option *options)
{
const struct option *numopt = NULL;

for (; options->type != OPTION_END; options++) {
if (options->short_name == *p->opt) {
p->opt = p->opt[1] ? p->opt + 1 : NULL;
return get_value(p, options, OPT_SHORT);
}

/*
* Handle the numerical option later, explicit one-digit
* options take precedence over it.
*/
if (options->type == OPTION_NUMBER)
numopt = options;
}
if (numopt && isdigit(*p->opt)) {
size_t len = 1;
char *arg;
int rc;

while (isdigit(p->opt[len]))
len++;
arg = xmemdupz(p->opt, len);
p->opt = p->opt[len] ? p->opt + len : NULL;
rc = (*numopt->callback)(numopt, arg, 0) ? (-1) : 0;
free(arg);
return rc;
}
return -2;
}
@ -411,6 +433,8 @@ int usage_with_options_internal(const char * const *usagestr, @@ -411,6 +433,8 @@ int usage_with_options_internal(const char * const *usagestr,
pos += fprintf(stderr, ", ");
if (opts->long_name)
pos += fprintf(stderr, "--%s", opts->long_name);
if (opts->type == OPTION_NUMBER)
pos += fprintf(stderr, "-NUM");

switch (opts->type) {
case OPTION_ARGUMENT:
@ -447,7 +471,7 @@ int usage_with_options_internal(const char * const *usagestr, @@ -447,7 +471,7 @@ int usage_with_options_internal(const char * const *usagestr,
pos += fprintf(stderr, " ...");
}
break;
default: /* OPTION_{BIT,BOOLEAN,SET_INT,SET_PTR} */
default: /* OPTION_{BIT,BOOLEAN,NUMBER,SET_INT,SET_PTR} */
break;
}


4
parse-options.h

@ -6,6 +6,7 @@ enum parse_opt_type { @@ -6,6 +6,7 @@ enum parse_opt_type {
OPTION_END,
OPTION_ARGUMENT,
OPTION_GROUP,
OPTION_NUMBER,
/* options with no arguments */
OPTION_BIT,
OPTION_NEGBIT,
@ -105,6 +106,9 @@ struct option { @@ -105,6 +106,9 @@ struct option {
parse_opt_approxidate_cb }
#define OPT_CALLBACK(s, l, v, a, h, f) \
{ OPTION_CALLBACK, (s), (l), (v), (a), (h), 0, (f) }
#define OPT_NUMBER_CALLBACK(v, h, f) \
{ OPTION_NUMBER, 0, NULL, (v), NULL, (h), \
PARSE_OPT_NOARG | PARSE_OPT_NONEG, (f) }

/* parse_options() will filter out the processed options and leave the
* non-option arguments in argv[].

18
t/t0040-parse-options.sh

@ -30,6 +30,7 @@ String options @@ -30,6 +30,7 @@ String options

Magic arguments
--quux means --quux
-NUM set integer to NUM

Standard options
--abbrev[=<n>] use <n> digits to display SHA-1s
@ -275,4 +276,21 @@ test_expect_success 'OPT_NEGBIT() works' ' @@ -275,4 +276,21 @@ test_expect_success 'OPT_NEGBIT() works' '
test_cmp expect output
'

cat > expect <<EOF
boolean: 0
integer: 12345
timestamp: 0
string: (not set)
abbrev: 7
verbose: 0
quiet: no
dry run: no
EOF

test_expect_success 'OPT_NUMBER_CALLBACK() works' '
test-parse-options -12345 > output 2> output.err &&
test ! -s output.err &&
test_cmp expect output
'

test_done

8
test-parse-options.c

@ -19,6 +19,12 @@ int length_callback(const struct option *opt, const char *arg, int unset) @@ -19,6 +19,12 @@ int length_callback(const struct option *opt, const char *arg, int unset)
return 0;
}

int number_callback(const struct option *opt, const char *arg, int unset)
{
*(int *)opt->value = strtol(arg, NULL, 10);
return 0;
}

int main(int argc, const char **argv)
{
const char *usage[] = {
@ -46,6 +52,8 @@ int main(int argc, const char **argv) @@ -46,6 +52,8 @@ int main(int argc, const char **argv)
"set string to default", (unsigned long)"default"),
OPT_GROUP("Magic arguments"),
OPT_ARGUMENT("quux", "means --quux"),
OPT_NUMBER_CALLBACK(&integer, "set integer to NUM",
number_callback),
OPT_GROUP("Standard options"),
OPT__ABBREV(&abbrev),
OPT__VERBOSE(&verbose),

Loading…
Cancel
Save