static enum parse_opt_result do_get_value()

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);
	}
}