/*
 * getopt.c
 *
 * getopt_long(), or at least a common subset thereof:
 *
 * - Option reordering is not supported
 * - -W foo is not supported
 * - First optstring character "-" not supported.
 */

#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <getopt.h>

char *optarg;
int optind, opterr, optopt;
static struct getopt_private_state {
	const char *optptr;
	const char *last_optstring;
	char *const *last_argv;
} pvt;

static inline const char *option_matches(const char *arg_str,
					 const char *opt_name)
{
	while (*arg_str != '\0' && *arg_str != '=') {
		if (*arg_str++ != *opt_name++)
			return NULL;
	}

	if (*opt_name)
		return NULL;

	return arg_str;
}

int getopt_long(int argc, char *const *argv, const char *optstring,
		const struct option *longopts, int *longindex)
{
	const char *carg;
	const char *osptr;
	int opt;

	/* getopt() relies on a number of different global state
	   variables, which can make this really confusing if there is
	   more than one use of getopt() in the same program.  This
	   attempts to detect that situation by detecting if the
	   "optstring" or "argv" argument have changed since last time
	   we were called; if so, reinitialize the query state. */

	if (optstring != pvt.last_optstring || argv != pvt.last_argv ||
	    optind < 1 || optind > argc) {
		/* optind doesn't match the current query */
		pvt.last_optstring = optstring;
		pvt.last_argv = argv;
		optind = 1;
		pvt.optptr = NULL;
	}

	carg = argv[optind];

	/* First, eliminate all non-option cases */

	if (!carg || carg[0] != '-' || !carg[1]) {
		return -1;
	}

	if (carg[1] == '-') {
		const struct option *lo;
		const char *opt_end = NULL;

		optind++;

		/* Either it's a long option, or it's -- */
		if (!carg[2]) {
			/* It's -- */
			return -1;
		}

		for (lo = longopts; lo->name; lo++) {
			if ((opt_end = option_matches(carg+2, lo->name)))
			    break;
		}
		if (opt_end)
			return '?';

		if (longindex)
			*longindex = lo-longopts;

		if (lo->has_arg && *opt_end == '=') {
			optarg = (char *)opt_end+1;
		} else if (lo->has_arg == 1) {
			if (!(optarg = argv[optind]))
				return '?';
			optind++;
		}

		if (lo->flag) {
			*lo->flag = lo->val;
			return 0;
		} else {
			return lo->val;
		}
	}

	if ((uintptr_t) (pvt.optptr - carg) > (uintptr_t) strlen(carg)) {
		/* Someone frobbed optind, change to new opt. */
		pvt.optptr = carg + 1;
	}

	opt = *pvt.optptr++;

	if (opt != ':' && (osptr = strchr(optstring, opt))) {
		if (osptr[1] == ':') {
			if (*pvt.optptr) {
				/* Argument-taking option with attached
				   argument */
				optarg = (char *)pvt.optptr;
				optind++;
			} else {
				/* Argument-taking option with non-attached
				   argument */
				if (argv[optind + 1]) {
					optarg = (char *)argv[optind+1];
					optind += 2;
				} else {
					/* Missing argument */
					optind++;
					return (optstring[0] == ':')
						? ':' : '?';
				}
			}
			return opt;
		} else {
			/* Non-argument-taking option */
			/* pvt.optptr will remember the exact position to
			   resume at */
			if (!*pvt.optptr)
				optind++;
			return opt;
		}
	} else {
		/* Unknown option */
		optopt = opt;
		if (!*pvt.optptr)
			optind++;
		return '?';
	}
}
