const struct option *opt, int flags)
{
const char *s, *arg;
- arg = p->opt ? p->opt : (p->argc > 1 ? p->argv[1] : NULL);
+ const int unset = flags & OPT_UNSET;
- if (p->opt && (flags & OPT_UNSET))
+ if (unset && p->opt)
return opterror(opt, "takes no value", flags);
+ if (unset && (opt->flags & PARSE_OPT_NONEG))
+ return opterror(opt, "isn't available", flags);
- switch (opt->type) {
- case OPTION_BOOLEAN:
- if (!(flags & OPT_SHORT) && p->opt)
+ if (!(flags & OPT_SHORT) && p->opt) {
+ switch (opt->type) {
+ case OPTION_CALLBACK:
+ if (!(opt->flags & PARSE_OPT_NOARG))
+ break;
+ /* FALLTHROUGH */
+ case OPTION_BOOLEAN:
+ case OPTION_BIT:
+ case OPTION_SET_INT:
+ case OPTION_SET_PTR:
return opterror(opt, "takes no value", flags);
- if (flags & OPT_UNSET)
- *(int *)opt->value = 0;
+ default:
+ break;
+ }
+ }
+
+ arg = p->opt ? p->opt : (p->argc > 1 ? p->argv[1] : NULL);
+ switch (opt->type) {
+ case OPTION_BIT:
+ if (unset)
+ *(int *)opt->value &= ~opt->defval;
else
- (*(int *)opt->value)++;
+ *(int *)opt->value |= opt->defval;
+ return 0;
+
+ case OPTION_BOOLEAN:
+ *(int *)opt->value = unset ? 0 : *(int *)opt->value + 1;
+ return 0;
+
+ case OPTION_SET_INT:
+ *(int *)opt->value = unset ? 0 : opt->defval;
+ return 0;
+
+ case OPTION_SET_PTR:
+ *(void **)opt->value = unset ? NULL : (void *)opt->defval;
return 0;
case OPTION_STRING:
- if (flags & OPT_UNSET) {
- *(const char **)opt->value = (const char *)NULL;
+ if (unset) {
+ *(const char **)opt->value = NULL;
return 0;
}
- if (opt->flags & PARSE_OPT_OPTARG && (!arg || *arg == '-')) {
+ if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
*(const char **)opt->value = (const char *)opt->defval;
return 0;
}
return 0;
case OPTION_CALLBACK:
- if (flags & OPT_UNSET)
+ if (unset)
return (*opt->callback)(opt, NULL, 1);
- if (opt->flags & PARSE_OPT_NOARG) {
- if (p->opt && !(flags & OPT_SHORT))
- return opterror(opt, "takes no value", flags);
+ if (opt->flags & PARSE_OPT_NOARG)
return (*opt->callback)(opt, NULL, 0);
- }
- if (opt->flags & PARSE_OPT_OPTARG && (!arg || *arg == '-'))
+ if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
return (*opt->callback)(opt, NULL, 0);
if (!arg)
return opterror(opt, "requires a value", flags);
return (*opt->callback)(opt, get_arg(p), 0);
case OPTION_INTEGER:
- if (flags & OPT_UNSET) {
+ if (unset) {
*(int *)opt->value = 0;
return 0;
}
- if (opt->flags & PARSE_OPT_OPTARG && (!arg || !isdigit(*arg))) {
+ if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
*(int *)opt->value = opt->defval;
return 0;
}
return error("unknown option `%s'", arg);
}
+static NORETURN void usage_with_options_internal(const char * const *,
+ const struct option *, int);
+
int parse_options(int argc, const char **argv, const struct option *options,
const char * const usagestr[], int flags)
{
break;
}
+ if (!strcmp(arg + 2, "help-all"))
+ usage_with_options_internal(usagestr, options, 1);
if (!strcmp(arg + 2, "help"))
usage_with_options(usagestr, options);
if (parse_long_opt(&args, arg + 2, options))
#define USAGE_OPTS_WIDTH 24
#define USAGE_GAP 2
-void usage_with_options(const char * const *usagestr,
- const struct option *opts)
+void usage_with_options_internal(const char * const *usagestr,
+ const struct option *opts, int full)
{
fprintf(stderr, "usage: %s\n", *usagestr++);
while (*usagestr && **usagestr)
fprintf(stderr, "%s\n", opts->help);
continue;
}
+ if (!full && (opts->flags & PARSE_OPT_HIDDEN))
+ continue;
pos = fprintf(stderr, " ");
if (opts->short_name)
pos += fprintf(stderr, " ...");
}
break;
- default:
+ default: /* OPTION_{BIT,BOOLEAN,SET_INT,SET_PTR} */
break;
}
exit(129);
}
+void usage_with_options(const char * const *usagestr,
+ const struct option *opts)
+{
+ usage_with_options_internal(usagestr, opts, 0);
+}
+
/*----- some often used options -----*/
#include "cache.h"
+
int parse_opt_abbrev_cb(const struct option *opt, const char *arg, int unset)
{
int v;