static opt_type check_for_long_option()

in fabtests/common/windows/getopt.c [226:307]


static opt_type check_for_long_option(const struct option *longopts, int *longindex,
				      const char* str, const char** arg)
{
	assert(longindex);
	assert(str);

	*arg = 0;

	if (!longopts)
		return opt_not_found;

	/* looking for '=' in string... */
	int i;
	for (i = 0; str[i] && str[i] != '='; i++);
	assert(str[i] == '=' || !str[i]);

	int len = i; /* len used for detecting length of option name in string */

	if (str[i] == '=' && str[i+1]) /* ok, symbol '=' detected... */
		*arg = str + i + 1; /* set potential option name substring length */

	/* detecting the nearest option name to string */
	int index = 1;
	const char* opt = longopts->name;

	if (!opt)
		return opt_not_found;

	int diff = string_diff(opt, str, len);
	int selected = diff >= 0 ? 0 : -1;
	int ambiguous = 0;

	while (longopts[index].name) {
		opt = longopts[index].name;

		int _diff = string_diff(opt, str, len);
		if (!_diff) {
			diff = 0;
			selected = index;
			break;
		}

		if (_diff > 0 && diff > 0) {
			ambiguous = 1; /* detected 2 or more options which are confirms string */
		}
		else if (_diff > 0 && (_diff < diff || diff < 0)) {
			diff = _diff;
			selected = index;
		}
		index++;
	}

	if (ambiguous && diff > 0) /* if detected multiple confirms and no exact match - return error */
		return opt_err_ambiguous;

	if (selected >= 0) {
		if (longopts[selected].has_arg == no_argument && *arg) {
			return opt_err_no_arg; /* argument is not required but specified */
		}
		else if (longopts[selected].has_arg == no_argument /*&& !arg*/) {
			*longindex = index;
			return opt_single; // option without argument
		}
		else if (longopts[selected].has_arg == required_argument && *arg) {
			*longindex = index;
			return opt_inplace_arg;
		}
		else if (longopts[selected].has_arg == required_argument /*&& !arg*/) {
			*longindex = index;
			return opt_has_arg;
		}
		else if (longopts[selected].has_arg == optional_argument && *arg) {
			*longindex = index;
			return opt_inplace_arg;
		}
		else if (longopts[selected].has_arg == optional_argument /*&& !arg*/) {
			*longindex = index;
			return opt_single; // option without argument
		}
	}
	return opt_not_found;
}