/*
 * Copyright (c) 2017 - 2020, Arm Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <assert.h>

#include "win_posix.h"

/*
 * This variable is set by getopt to the index of the next element of the
 * argv array to be processed. Once getopt has found all of the option
 * arguments, you can use this variable to determine where the remaining
 * non-option arguments begin. The initial value of this variable is 1.
 */
int optind = 1;

/*
 * If the value of this variable is nonzero, then getopt prints an error
 * message to the standard error stream if it encounters an unknown option
 * default character or an option with a missing required argument.
 * If you set this variable to zero, getopt does not print any messages,
 * but it still returns the character ? to indicate an error.
 */
const int opterr; /* = 0; */
/* const because we do not implement error printing.*/
/* Not initialised to conform with the coding standard. */

/*
 * When getopt encounters an unknown option character or an option with a
 * missing required argument, it stores that option character in this
 * variable.
 */
int optopt;	/* = 0; */

/*
 * This variable is set by getopt to point at the value of the option
 * argument, for those options that accept arguments.
 */
char *optarg;	/* = 0; */

enum return_flags {
	RET_ERROR = -1,
	RET_END_OPT_LIST = -1,
	RET_NO_PARAM = '?',
	RET_NO_PARAM2 = ':',
	RET_UNKNOWN_OPT = '?'
};

/*
 * Common initialisation on entry.
 */
static
void getopt_init(void)
{
	optarg = (char *)0;
	optopt = 0;
	/* optind may be zero with some POSIX uses.
	 * For our purposes we just change it to 1.
	 */
	if (optind == 0)
		optind = 1;
}

/*
 * Common handling for a single letter option.
 */
static
int getopt_1char(int argc,
		 char *const argv[],
		 const char *const opstring,
		 const int optchar)
{
	size_t nlen = (opstring == 0) ? 0 : strlen(opstring);
	size_t loptn;

	for (loptn = 0; loptn < nlen; loptn++) {
		if (optchar == opstring[loptn]) {
			if (opstring[loptn + 1] == ':') {
				/* Option has argument */
				if (optind < argc) {
					/* Found argument. */
					assert(argv != 0);
					optind++;
					optarg = argv[optind++];
					return optchar;
				}
				/* Missing argument. */
				if (opstring[loptn + 2] == ':') {
					/* OK if optional "x::". */
					optind++;
					return optchar;
				}
				/* Actual missing value. */
				optopt = optchar;
				return ((opstring[0] == ':')
					? RET_NO_PARAM2
					: RET_NO_PARAM);
			}
			/* No argument, just return option char */
			optind++;
			return optchar;
		}
	}
	/*
	 * If getopt finds an option character in argv that was not included in
	 * options, ... it returns '?' and sets the external variable optopt to
	 * the actual option character.
	 */
	optopt = optchar;
	return RET_UNKNOWN_OPT;
}

int getopt(int argc,
	   char *argv[],
	   char *opstring)
{
	int result = RET_END_OPT_LIST;
	size_t argn = 0;
	size_t nlen = strlen(opstring);

	getopt_init();
	/* If we have an argument left to play with */
	if ((argc > optind) && (argv != 0)) {
		const char *arg = (const char *)argv[optind];

		if ((arg != 0) && (arg[0] == '-'))
			result = getopt_1char(argc, argv, opstring, arg[1]);
	}

	return result;
}

/*
 * Match an argument value against an option name.
 * Note that we only match over the shorter length of the pair, to allow
 * for abbreviation or say --match=value
 * Long option names may be abbreviated if the abbreviation is unique or an
 * exact match for some defined option. This function does not check that the
 * abbreviations are unique and should be handled by the caller.
 * A long option may take a parameter, of the form --opt=param or --opt param.
*/
static
int optmatch(const char *argval, const char *optname)
{
	int result = 0;

	while ((result == 0) && (*optname != 0) && (*argval != 0))
		result = (*argval++) - (*optname++);
	return result;
}

/* Handling for a single long option. */
static
int getopt_1long(const int argc,
		 char *const argv[],
		 const struct option *const longopts,
		 const char *const optname,
		 int *const indexptr)
{
	int result = RET_UNKNOWN_OPT;
	size_t loptn = 0;
	bool match_found = false;

	/*
	 * Long option names may be abbreviated if the abbreviation
	 * is unique or an exact match for some defined option.
	 * To handle this:
	 * - First search for an exact match.
	 * - If exact match was not found search for a abbreviated match.
	 * By doing this an incorrect option selection can be avoided.
	 */

	/* 1. Search for an exact match. */
	while (longopts[loptn].name != NULL) {
		if (strcmp(optname, longopts[loptn].name) == 0) {
			match_found = true;
			break;
		}
		++loptn;
	}

	/* 2. If exact match was not found search for a abbreviated match. */
	if (!match_found) {
		loptn = 0;
		while (longopts[loptn].name != NULL) {
			if (optmatch(optname, longopts[loptn].name) == 0) {
				match_found = true;
				break;
			}
			++loptn;
		}
	}

	if (match_found) {
		/* We found a match. */
		result = longopts[loptn].val;
		if (indexptr != 0) {
			*indexptr = loptn;
		}
		switch (longopts[loptn].has_arg) {
		case required_argument:
			if ((optind + 1) >= argc) {
				/* Missing argument. */
				optopt = result;
				return RET_NO_PARAM;
			}
			/* Fallthrough to get option value. */

		case optional_argument:
			if ((argc - optind) > 0) {
				/* Found argument. */
				optarg = argv[++optind];
			}
			/* Fallthrough to handle flag. */

		case no_argument:
			optind++;
			if (longopts[loptn].flag != 0) {
				*longopts[loptn].flag = result;
				result = 0;
			}
			break;

		}
		return result;
	}

	/*
	 * If getopt finds an option character in argv that was not included
	 * in options, ... it returns '?' and sets the external variable
	 * optopt to the actual option character.
	 */
	return RET_UNKNOWN_OPT;
}

/*
 * getopt_long gets the next option argument from the argument list
 * specified by the argv and argc arguments.  Options may be either short
 * (single letter) as for getopt, or longer names (preceded by --).
 */
int getopt_long(int argc,
		char *argv[],
		const char *shortopts,
		const struct option *longopts,
		int *indexptr)
{
	int result = RET_END_OPT_LIST;

	getopt_init();
	/* If we have an argument left to play with */
	if ((argc > optind) && (argv != 0)) {
		const char *arg = argv[optind];

		if ((arg != 0) && (arg[0] == '-')) {
			if (arg[1] == '-') {
				/* Looks like a long option. */
				result = getopt_1long(argc,
						      argv,
						      longopts,
						      &arg[2],
						      indexptr);
			} else {
				result = getopt_1char(argc,
						      argv,
						      shortopts,
						      arg[1]);
			}
		}
	}
	return result;
}

/*
 * getopt_long_only gets the next option argument from the argument list
 * specified by the argv and argc arguments.  Options may be either short
 * or long as for getopt_long, but the long names may have a single '-'
 * prefix too.
 */
int getopt_long_only(int argc,
		     char *argv[],
		     const char *shortopts,
		     const struct option *longopts,
		     int *indexptr)
{
	int result = RET_END_OPT_LIST;

	getopt_init();
	/* If we have an argument left to play with */
	if ((argc > optind) && (argv != 0)) {
		const char *arg = argv[optind];

		if ((arg != 0) && (arg[0] == '-')) {
			if (arg[1] == '-') {
				/* Looks like a long option. */
				result = getopt_1long(argc,
						      argv,
						      longopts,
						      &arg[2],
						      indexptr);
			} else {
				result = getopt_1long(argc,
						      argv,
						      longopts,
						      &arg[1],
						      indexptr);
				if (result == RET_UNKNOWN_OPT) {
					result = getopt_1char(argc,
							      argv,
							      shortopts,
							      arg[1]);
				}
			}
		}
	}
	return result;
}
