Browse Source

ccan: Update ccan modules to include incomplete option parsing

Signed-off-by: Christian Decker <@cdecker>
trytravis
Christian Decker 6 years ago
parent
commit
045f7ce7f7
  1. 2
      ccan/README
  2. 21
      ccan/ccan/opt/opt.c
  3. 24
      ccan/ccan/opt/opt.h
  4. 15
      ccan/ccan/opt/parse.c
  5. 2
      ccan/ccan/opt/private.h
  6. 37
      ccan/ccan/opt/test/run-early_incomplete.c
  7. 23
      ccan/ccan/opt/test/utils.c
  8. 1
      ccan/ccan/opt/test/utils.h

2
ccan/README

@ -1,3 +1,3 @@
CCAN imported from http://ccodearchive.net.
CCAN version: init-2451-gfedf5151
CCAN version: init-2454-gc656dceb

21
ccan/ccan/opt/opt.c

@ -207,14 +207,15 @@ bool opt_parse(int *argc, char *argv[], void (*errlog)(const char *fmt, ...))
/* This helps opt_usage. */
opt_argv0 = argv[0];
while ((ret = parse_one(argc, argv, 0, &offset, errlog)) == 1);
while ((ret = parse_one(argc, argv, 0, &offset, errlog, false)) == 1);
/* parse_one returns 0 on finish, -1 on error */
return (ret == 0);
}
bool opt_early_parse(int argc, char *argv[],
void (*errlog)(const char *fmt, ...))
static bool early_parse(int argc, char *argv[],
void (*errlog)(const char *fmt, ...),
bool ignore_unknown)
{
int ret;
unsigned off = 0;
@ -226,7 +227,7 @@ bool opt_early_parse(int argc, char *argv[],
/* This helps opt_usage. */
opt_argv0 = argv[0];
while ((ret = parse_one(&argc, tmpargv, OPT_EARLY, &off, errlog)) == 1);
while ((ret = parse_one(&argc, tmpargv, OPT_EARLY, &off, errlog, ignore_unknown)) == 1);
opt_alloc.free(tmpargv);
@ -234,6 +235,18 @@ bool opt_early_parse(int argc, char *argv[],
return (ret == 0);
}
bool opt_early_parse(int argc, char *argv[],
void (*errlog)(const char *fmt, ...))
{
return early_parse(argc, argv, errlog, false);
}
bool opt_early_parse_incomplete(int argc, char *argv[],
void (*errlog)(const char *fmt, ...))
{
return early_parse(argc, argv, errlog, true);
}
void opt_free_table(void)
{
opt_alloc.free(opt_table);

24
ccan/ccan/opt/opt.h

@ -286,6 +286,30 @@ bool opt_parse(int *argc, char *argv[], void (*errlog)(const char *fmt, ...));
bool opt_early_parse(int argc, char *argv[],
void (*errlog)(const char *fmt, ...));
/**
* opt_early_parse_incomplete - parse early arguments, ignoring unknown ones.
* @argc: argc
* @argv: argv array.
* @errlog: the function to print errors
*
* If you have plugins, you might need to do early parsing (eg. to find the
* plugin directory) but you don't know what options the plugins will want.
*
* Thus, this function is just like opt_early_parse, but ignores unknown options.
*
* Example:
* if (!opt_early_parse_incomplete(argc, argv, opt_log_stderr)) {
* printf("You screwed up, aborting!\n");
* exit(1);
* }
*
* See Also:
* opt_early_parse()
*/
bool opt_early_parse_incomplete(int argc, char *argv[],
void (*errlog)(const char *fmt, ...));
/**
* opt_free_table - reset the opt library.
*

15
ccan/ccan/opt/parse.c

@ -30,7 +30,7 @@ static void consume_option(int *argc, char *argv[], unsigned optnum)
/* Returns 1 if argument consumed, 0 if all done, -1 on error. */
int parse_one(int *argc, char *argv[], enum opt_type is_early, unsigned *offset,
void (*errlog)(const char *fmt, ...))
void (*errlog)(const char *fmt, ...), bool unknown_ok)
{
unsigned i, arg, len;
const char *o, *optarg = NULL;
@ -67,10 +67,13 @@ int parse_one(int *argc, char *argv[], enum opt_type is_early, unsigned *offset,
continue;
break;
}
if (!o)
if (!o) {
if (unknown_ok)
goto ok;
return parse_err(errlog, argv[0],
argv[arg], strlen(argv[arg]),
"unrecognized option");
}
/* For error messages, we include the leading '--' */
o -= 2;
len += 2;
@ -82,10 +85,15 @@ int parse_one(int *argc, char *argv[], enum opt_type is_early, unsigned *offset,
(*offset)++;
break;
}
if (!o)
if (!o) {
if (unknown_ok) {
(*offset)++;
goto ok;
}
return parse_err(errlog, argv[0],
argv[arg], strlen(argv[arg]),
"unrecognized option");
}
/* For error messages, we include the leading '-' */
o--;
len = 2;
@ -120,6 +128,7 @@ int parse_one(int *argc, char *argv[], enum opt_type is_early, unsigned *offset,
return -1;
}
ok:
/* If no more letters in that short opt, reset offset. */
if (*offset && !argv[arg][*offset + 1])
*offset = 0;

2
ccan/ccan/opt/private.h

@ -22,6 +22,6 @@ struct opt_alloc {
extern struct opt_alloc opt_alloc;
int parse_one(int *argc, char *argv[], enum opt_type is_early, unsigned *offset,
void (*errlog)(const char *fmt, ...));
void (*errlog)(const char *fmt, ...), bool unknown_ok);
#endif /* CCAN_OPT_PRIVATE_H */

37
ccan/ccan/opt/test/run-early_incomplete.c

@ -0,0 +1,37 @@
/* With errlog == NULL, we never get a "failure". */
#include <ccan/tap/tap.h>
#include <stdlib.h>
#include <ccan/opt/opt.c>
#include <ccan/opt/usage.c>
#include <ccan/opt/helpers.c>
#include <ccan/opt/parse.c>
#include "utils.h"
int main(int argc, char *argv[])
{
plan_tests(8);
/* Simple short args.*/
opt_register_noarg("-a", test_noarg, NULL, "All");
opt_register_early_noarg("-b|--blong", test_noarg, NULL, "All");
/* This is OK. */
ok1(parse_early_args_incomplete(&argc, &argv, "-c", NULL));
ok1(test_cb_called == 0);
/* Skips letters correctly */
ok1(parse_early_args_incomplete(&argc, &argv, "-ca", NULL));
ok1(test_cb_called == 0); /* a is not an early arg! */
test_cb_called = 0;
ok1(parse_early_args_incomplete(&argc, &argv, "-bca", NULL));
ok1(test_cb_called == 1);
test_cb_called = 0;
ok1(parse_early_args_incomplete(&argc, &argv, "--unknown", "--also-unknown", "--blong", NULL));
ok1(test_cb_called == 1);
/* parse_args allocates argv */
free(argv);
return exit_status();
}

23
ccan/ccan/opt/test/utils.c

@ -103,6 +103,29 @@ bool parse_early_args(int *argc, char ***argv, ...)
return opt_early_parse(*argc, *argv, save_err_output);
}
bool parse_early_args_incomplete(int *argc, char ***argv, ...)
{
char **a;
va_list ap;
va_start(ap, argv);
*argc = 1;
a = malloc(sizeof(*a) * (*argc + 1));
a[0] = (*argv)[0];
while ((a[*argc] = va_arg(ap, char *)) != NULL) {
(*argc)++;
a = realloc(a, sizeof(*a) * (*argc + 1));
}
if (allocated)
free(*argv);
*argv = a;
allocated = true;
return opt_early_parse_incomplete(*argc, *argv, save_err_output);
}
struct opt_table short_table[] = {
/* Short opts, different args. */
OPT_WITHOUT_ARG("-a", test_noarg, "a", "Description of a"),

1
ccan/ccan/opt/test/utils.h

@ -5,6 +5,7 @@
bool parse_args(int *argc, char ***argv, ...);
bool parse_early_args(int *argc, char ***argv, ...);
bool parse_early_args_incomplete(int *argc, char ***argv, ...);
extern char *err_output;
void save_err_output(const char *fmt, ...);
void reset_options(void);

Loading…
Cancel
Save