+/* Licensed under GPLv2+ - see LICENSE file for details */
/* Actual code to parse commandline. */
#include <ccan/opt/opt.h>
#include <string.h>
}
/* Returns 1 if argument consumed, 0 if all done, -1 on error. */
-int parse_one(int *argc, char *argv[], unsigned *offset,
- void (*errlog)(const char *fmt, ...))
+int parse_one(int *argc, char *argv[], enum opt_type is_early, unsigned *offset,
+ void (*errlog)(const char *fmt, ...), bool unknown_ok)
{
unsigned i, arg, len;
const char *o, *optarg = NULL;
- char *problem;
+ char *problem = NULL;
if (getenv("POSIXLY_CORRECT")) {
/* Don't find options after non-options. */
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;
(*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;
}
- if (opt_table[i].type == OPT_NOARG) {
+ if ((opt_table[i].type & ~OPT_EARLY) == OPT_NOARG) {
if (optarg)
return parse_err(errlog, argv[0], o, len,
"doesn't allow an argument");
- problem = opt_table[i].cb(opt_table[i].u.arg);
+ if ((opt_table[i].type & OPT_EARLY) == is_early)
+ problem = opt_table[i].cb(opt_table[i].u.arg);
} else {
if (!optarg) {
/* Swallow any short options as optarg, eg -afile */
if (!optarg)
return parse_err(errlog, argv[0], o, len,
"requires an argument");
- problem = opt_table[i].cb_arg(optarg, opt_table[i].u.arg);
+ if ((opt_table[i].type & OPT_EARLY) == is_early)
+ problem = opt_table[i].cb_arg(optarg,
+ opt_table[i].u.arg);
}
if (problem) {
parse_err(errlog, argv[0], o, len, problem);
- free(problem);
+ opt_alloc.free(problem);
return -1;
}
+ok:
/* If no more letters in that short opt, reset offset. */
if (*offset && !argv[arg][*offset + 1])
*offset = 0;