fiptool: Enable Visual Studio build

Updates are required to enable the fiptool utility to be built on a
Windows platform.  This change modifies the source files to enable
building with Visual Studio (detected via preprocessor settings).
The primary changes are:
  1.  Provide an implementation of the getopt_long function.  This does
      not exist in the Visual Studio CRT libraries because Windows
      commands normally use '/' not '-' as an option indicator.
  2.  Redirect some function names to match those supported by the
      Visual Studio libraries (when building with Visual Studio).
  2.  Modify a structure name (stat) to match that provided
      by the Visual Studio libraries (_stat).

Note - this change does not provide makefile updates.  It only modifies
       the sources to enable the fiptool to be built from a Visual
       Studio project.  In normal use the presence of FIPTOOL.EXE is
       enough to satisfy the make requirements.  A makefile change may
       be derived from the Visual Studio command line information at
       some point in the future.

Change-Id: I3ade77ea140246af3c030920b3f97c070087f111
Signed-off-by: Evan Lloyd <evan.lloyd@arm.com>
diff --git a/tools/fiptool/fiptool_platform.h b/tools/fiptool/fiptool_platform.h
index bfdd1ef..fd0a120 100644
--- a/tools/fiptool/fiptool_platform.h
+++ b/tools/fiptool/fiptool_platform.h
@@ -23,6 +23,7 @@
 #	else
 
 		/* Visual Studio. */
+#		include "win_posix.h"
 
 #	endif
 
diff --git a/tools/fiptool/win_posix.c b/tools/fiptool/win_posix.c
new file mode 100644
index 0000000..48feb16
--- /dev/null
+++ b/tools/fiptool/win_posix.c
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2017, 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.
+ * 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;
+
+	while (longopts[loptn].name != 0) {
+		if (optmatch(optname, longopts[loptn].name) == 0) {
+			/* 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;
+		}
+		++loptn;
+	}
+	/*
+	 * 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;
+}
diff --git a/tools/fiptool/win_posix.h b/tools/fiptool/win_posix.h
new file mode 100644
index 0000000..c3fc399
--- /dev/null
+++ b/tools/fiptool/win_posix.h
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __WINPOSIX_H__
+#	define __WINPOSIX_H__
+
+#	define _CRT_SECURE_NO_WARNINGS
+
+#	include <direct.h>
+#	include <io.h>
+#	include <stdint.h>
+#	include <stdlib.h>
+#	include <string.h>
+#	include <sys/stat.h>
+
+#	include "uuid.h"
+
+
+/* Derive or provide Windows equivalents of Posix/GCC/Unix stuff. */
+#	ifndef PATH_MAX
+#		ifdef MAX_PATH
+#			define PATH_MAX MAX_PATH
+#		else
+#			ifdef _MAX_PATH
+#				define MAX_PATH _MAX_PATH
+#				define PATH_MAX _MAX_PATH
+#			else
+#				define PATH_MAX 260
+#			endif
+#		endif
+#	endif
+
+#	ifndef _CRT_SECURE_NO_WARNINGS
+#		define _CRT_SECURE_NO_WARNINGS 1
+#	endif
+
+/*
+ * Platform specific names.
+ *
+ * Visual Studio deprecates a number of POSIX functions and only provides
+ * ISO C++ compliant alternatives (distinguished by their '_' prefix).
+ * These macros help provide a stopgap for that.
+ */
+
+/* fileno cannot be an inline function, because _fileno is a macro. */
+#	define fileno(fileptr) _fileno(fileptr)
+
+/* _fstat uses the _stat structure, not stat. */
+#	define BLD_PLAT_STAT	_stat
+
+/* Define flag values for _access. */
+#	define F_OK	0
+
+
+/* getopt implementation for Windows: Data. */
+
+/* Legitimate values for option.has_arg. */
+enum has_arg_values {
+	no_argument,		/* No argument value required */
+	required_argument,	/* value must be specified. */
+	optional_argument	/* value may be specified. */
+};
+
+/* Long option table entry for get_opt_long. */
+struct option {
+	/* The name of the option. */
+	const char *name;
+
+	/*
+	 * Indicates whether the option takes an argument.
+	 * Possible values: see has_arg_values above.
+	 */
+	int has_arg;
+
+	/* If not null, when option present, *flag is set to val. */
+	int *flag;
+
+	/*
+	 * The value associated with this option to return
+	 * (and save in *flag when not null)
+	 */
+	int val;
+};
+
+/*
+ * This variable is set by getopt to point at the value of the option
+ * argument, for those options that accept arguments.
+ */
+extern char *optarg;
+
+/*
+ * When this variable is not zero, getopt emits an error message to stderr
+ * if it encounters an unspecified option, or a missing argument.
+ * Otherwise no message is reported.
+ */
+extern const int opterr;	/* const as NOT used in this implementation. */
+
+/*
+ * 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.
+ */
+extern int optind;
+
+/*
+ * When getopt encounters an unknown option character or an option with a
+ * missing required argument, it stores that option character in this
+ * variable.
+ */
+extern int optopt;
+
+
+/*
+ * Platform specific names.
+ *
+ * Visual Studio deprecates a number of POSIX functions and only provides
+ * ISO C++ compliant alternatives (distinguished by their '_' prefix).
+ * These inline functions provide a stopgap for that.
+ */
+
+inline int access(const char *path, int mode)
+{
+	return _access(path, mode);
+}
+
+inline int chdir(const char *s)
+{
+	return _chdir(s);
+}
+
+inline int fstat(int fd, struct _stat *buffer)
+{
+	return _fstat(fd, buffer);
+}
+
+inline char *strdup(const char *s)
+{
+	return _strdup(s);
+}
+
+/*
+ * getopt implementation for Windows: Functions.
+ *
+ * Windows does not have the getopt family of functions, as it normally
+ * uses '/' instead of '-' as the command line option delimiter.
+ * These functions provide a Windows version that  uses '-', which precludes
+ * using '-' as the intial letter of a program argument.
+ * This is not seen as a problem in the specific instance of fiptool,
+ * and enables existing makefiles to work on a Windows build environment.
+ */
+
+/*
+ * The getopt function gets the next option argument from the argument list
+ * specified by the argv and argc arguments.
+ */
+int getopt(int argc,
+	   char *argv[],
+	   char *options);
+
+/*
+ * 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);
+
+/*
+ * 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);
+
+#endif /* __WINPOSIX_H__ */