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>
This commit is contained in:
Evan Lloyd 2017-05-25 19:16:53 +01:00
parent 4468442933
commit a1ee383626
3 changed files with 475 additions and 0 deletions

View File

@ -23,6 +23,7 @@
# else
/* Visual Studio. */
# include "win_posix.h"
# endif

287
tools/fiptool/win_posix.c Normal file
View File

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

187
tools/fiptool/win_posix.h Normal file
View File

@ -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__ */