in parse-options.c [71:266]
static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p,
const struct option *opt,
enum opt_parsed flags,
const char **argp)
{
const char *arg;
const int unset = flags & OPT_UNSET;
int err;
if (unset && p->opt)
return error(_("%s takes no value"), optname(opt, flags));
if (unset && (opt->flags & PARSE_OPT_NONEG))
return error(_("%s isn't available"), optname(opt, flags));
if (!(flags & OPT_SHORT) && p->opt && (opt->flags & PARSE_OPT_NOARG))
return error(_("%s takes no value"), optname(opt, flags));
switch (opt->type) {
case OPTION_LOWLEVEL_CALLBACK:
return opt->ll_callback(p, opt, NULL, unset);
case OPTION_BIT:
if (unset)
*(int *)opt->value &= ~opt->defval;
else
*(int *)opt->value |= opt->defval;
return 0;
case OPTION_NEGBIT:
if (unset)
*(int *)opt->value |= opt->defval;
else
*(int *)opt->value &= ~opt->defval;
return 0;
case OPTION_BITOP:
if (unset)
BUG("BITOP can't have unset form");
*(int *)opt->value &= ~opt->extra;
*(int *)opt->value |= opt->defval;
return 0;
case OPTION_COUNTUP:
if (*(int *)opt->value < 0)
*(int *)opt->value = 0;
*(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_STRING:
if (unset)
*(const char **)opt->value = NULL;
else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
*(const char **)opt->value = (const char *)opt->defval;
else
return get_arg(p, opt, flags, (const char **)opt->value);
return 0;
case OPTION_FILENAME:
{
const char *value;
FREE_AND_NULL(*(char **)opt->value);
err = 0;
if (unset)
value = NULL;
else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
value = (const char *) opt->defval;
else
err = get_arg(p, opt, flags, &value);
if (!err)
*(char **)opt->value = fix_filename(p->prefix, value);
return err;
}
case OPTION_CALLBACK:
{
const char *p_arg = NULL;
int p_unset;
if (unset)
p_unset = 1;
else if (opt->flags & PARSE_OPT_NOARG)
p_unset = 0;
else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
p_unset = 0;
else if (get_arg(p, opt, flags, &arg))
return -1;
else {
p_unset = 0;
p_arg = arg;
}
if (opt->flags & PARSE_OPT_CMDMODE)
*argp = p_arg;
if (opt->callback)
return (*opt->callback)(opt, p_arg, p_unset) ? (-1) : 0;
else
return (*opt->ll_callback)(p, opt, p_arg, p_unset);
}
case OPTION_INTEGER:
{
intmax_t upper_bound = INTMAX_MAX >> (bitsizeof(intmax_t) - CHAR_BIT * opt->precision);
intmax_t lower_bound = -upper_bound - 1;
intmax_t value;
if (unset) {
value = 0;
} else if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
value = opt->defval;
} else if (get_arg(p, opt, flags, &arg)) {
return -1;
} else if (!*arg) {
return error(_("%s expects a numerical value"),
optname(opt, flags));
} else if (!git_parse_signed(arg, &value, upper_bound)) {
if (errno == ERANGE)
return error(_("value %s for %s not in range [%"PRIdMAX",%"PRIdMAX"]"),
arg, optname(opt, flags), lower_bound, upper_bound);
return error(_("%s expects an integer value with an optional k/m/g suffix"),
optname(opt, flags));
}
if (value < lower_bound)
return error(_("value %s for %s not in range [%"PRIdMAX",%"PRIdMAX"]"),
arg, optname(opt, flags), (intmax_t)lower_bound, (intmax_t)upper_bound);
switch (opt->precision) {
case 1:
*(int8_t *)opt->value = value;
return 0;
case 2:
*(int16_t *)opt->value = value;
return 0;
case 4:
*(int32_t *)opt->value = value;
return 0;
case 8:
*(int64_t *)opt->value = value;
return 0;
default:
BUG("invalid precision for option %s",
optname(opt, flags));
}
}
case OPTION_UNSIGNED:
{
uintmax_t upper_bound = UINTMAX_MAX >> (bitsizeof(uintmax_t) - CHAR_BIT * opt->precision);
uintmax_t value;
if (unset) {
value = 0;
} else if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
value = opt->defval;
} else if (get_arg(p, opt, flags, &arg)) {
return -1;
} else if (!*arg) {
return error(_("%s expects a numerical value"),
optname(opt, flags));
} else if (!git_parse_unsigned(arg, &value, upper_bound)) {
if (errno == ERANGE)
return error(_("value %s for %s not in range [%"PRIdMAX",%"PRIdMAX"]"),
arg, optname(opt, flags), (uintmax_t) 0, upper_bound);
return error(_("%s expects a non-negative integer value"
" with an optional k/m/g suffix"),
optname(opt, flags));
}
switch (opt->precision) {
case 1:
*(uint8_t *)opt->value = value;
return 0;
case 2:
*(uint16_t *)opt->value = value;
return 0;
case 4:
*(uint32_t *)opt->value = value;
return 0;
case 8:
*(uint64_t *)opt->value = value;
return 0;
default:
BUG("invalid precision for option %s",
optname(opt, flags));
}
}
default:
BUG("opt->type %d should not happen", opt->type);
}
}