diff options
author | Luca Deri <deri@ntop.org> | 2023-10-05 12:24:39 +0200 |
---|---|---|
committer | Luca Deri <deri@ntop.org> | 2023-10-05 12:24:39 +0200 |
commit | e1e6a01d6ae09f3d74155df84b8e1f41c01b3896 (patch) | |
tree | 019e18a8f1f25dfc5241ac1fd87a810969dfacf5 /windows | |
parent | 3881d162f7bb6b1b6a27ddfd5f1617fd7406fbfe (diff) |
Windows code rework
Diffstat (limited to 'windows')
-rw-r--r-- | windows/src/dirent.h | 1239 | ||||
l---------[-rw-r--r--] | windows/src/getopt.c | 973 | ||||
l---------[-rw-r--r--] | windows/src/getopt.h | 137 | ||||
l---------[-rw-r--r--] | windows/src/win-gettimeofday.c | 56 |
4 files changed, 3 insertions, 2402 deletions
diff --git a/windows/src/dirent.h b/windows/src/dirent.h deleted file mode 100644 index fd1e81354..000000000 --- a/windows/src/dirent.h +++ /dev/null @@ -1,1239 +0,0 @@ -/* - * Dirent interface for Microsoft Visual Studio - * - * Copyright (C) 1998-2019 Toni Ronkko - * This file is part of dirent. Dirent may be freely distributed - * under the MIT license. For all details and documentation, see - * https://github.com/tronkko/dirent - */ -#ifndef DIRENT_H -#define DIRENT_H - -/* Hide warnings about unreferenced local functions */ -#if defined(__clang__) -# pragma clang diagnostic ignored "-Wunused-function" -#elif defined(_MSC_VER) -# pragma warning(disable:4505) -#elif defined(__GNUC__) -# pragma GCC diagnostic ignored "-Wunused-function" -#endif - -/* - * Include windows.h without Windows Sockets 1.1 to prevent conflicts with - * Windows Sockets 2.0. - */ -#ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -#endif -#include <windows.h> - -#include <stdio.h> -#include <stdarg.h> -#include <wchar.h> -#include <string.h> -#include <stdlib.h> -#include <malloc.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <errno.h> -#include <ctype.h> - -/* Indicates that d_type field is available in dirent structure */ -#define _DIRENT_HAVE_D_TYPE - -/* Indicates that d_namlen field is available in dirent structure */ -#define _DIRENT_HAVE_D_NAMLEN - -/* Entries missing from MSVC 6.0 */ -#if !defined(FILE_ATTRIBUTE_DEVICE) -# define FILE_ATTRIBUTE_DEVICE 0x40 -#endif - -/* File type and permission flags for stat(), general mask */ -#if !defined(S_IFMT) -# define S_IFMT _S_IFMT -#endif - -/* Directory bit */ -#if !defined(S_IFDIR) -# define S_IFDIR _S_IFDIR -#endif - -/* Character device bit */ -#if !defined(S_IFCHR) -# define S_IFCHR _S_IFCHR -#endif - -/* Pipe bit */ -#if !defined(S_IFFIFO) -# define S_IFFIFO _S_IFFIFO -#endif - -/* Regular file bit */ -#if !defined(S_IFREG) -# define S_IFREG _S_IFREG -#endif - -/* Read permission */ -#if !defined(S_IREAD) -# define S_IREAD _S_IREAD -#endif - -/* Write permission */ -#if !defined(S_IWRITE) -# define S_IWRITE _S_IWRITE -#endif - -/* Execute permission */ -#if !defined(S_IEXEC) -# define S_IEXEC _S_IEXEC -#endif - -/* Pipe */ -#if !defined(S_IFIFO) -# define S_IFIFO _S_IFIFO -#endif - -/* Block device */ -#if !defined(S_IFBLK) -# define S_IFBLK 0 -#endif - -/* - * Symbolic link. Be ware that S_IFLNK value and S_ISLNK() macro are only - * usable with dirent - they do not work with stat() function call! - */ -#if !defined(S_IFLNK) -# define S_IFLNK (_S_IFDIR | _S_IFREG) -#endif - -/* Socket */ -#if !defined(S_IFSOCK) -# define S_IFSOCK 0 -#endif - -/* Read user permission */ -#if !defined(S_IRUSR) -# define S_IRUSR S_IREAD -#endif - -/* Write user permission */ -#if !defined(S_IWUSR) -# define S_IWUSR S_IWRITE -#endif - -/* Execute user permission */ -#if !defined(S_IXUSR) -# define S_IXUSR 0 -#endif - -/* User full permissions */ -#if !defined(S_IRWXU) -# define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR) -#endif - -/* Read group permission */ -#if !defined(S_IRGRP) -# define S_IRGRP 0 -#endif - -/* Write group permission */ -#if !defined(S_IWGRP) -# define S_IWGRP 0 -#endif - -/* Execute group permission */ -#if !defined(S_IXGRP) -# define S_IXGRP 0 -#endif - -/* Group full permissions */ -#if !defined(S_IRWXG) -# define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP) -#endif - -/* Read others permission */ -#if !defined(S_IROTH) -# define S_IROTH 0 -#endif - -/* Write others permission */ -#if !defined(S_IWOTH) -# define S_IWOTH 0 -#endif - -/* Execute others permission */ -#if !defined(S_IXOTH) -# define S_IXOTH 0 -#endif - -/* Other full permissions */ -#if !defined(S_IRWXO) -# define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH) -#endif - -/* Maximum length of file name */ -#if !defined(PATH_MAX) -# define PATH_MAX MAX_PATH -#endif -#if !defined(FILENAME_MAX) -# define FILENAME_MAX MAX_PATH -#endif -#if !defined(NAME_MAX) -# define NAME_MAX FILENAME_MAX -#endif - -/* File type flags for d_type */ -#define DT_UNKNOWN 0 -#define DT_REG S_IFREG -#define DT_DIR S_IFDIR -#define DT_FIFO S_IFIFO -#define DT_SOCK S_IFSOCK -#define DT_CHR S_IFCHR -#define DT_BLK S_IFBLK -#define DT_LNK S_IFLNK - -/* Macros for converting between st_mode and d_type */ -#define IFTODT(mode) ((mode) & S_IFMT) -#define DTTOIF(type) (type) - -/* - * File type macros. Note that block devices and sockets cannot be - * distinguished on Windows, and the macros S_ISBLK and S_ISSOCK are only - * defined for compatibility. These macros should always return false on - * Windows. - */ -#if !defined(S_ISFIFO) -# define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) -#endif -#if !defined(S_ISDIR) -# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) -#endif -#if !defined(S_ISREG) -# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) -#endif -#if !defined(S_ISLNK) -# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) -#endif -#if !defined(S_ISSOCK) -# define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) -#endif -#if !defined(S_ISCHR) -# define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) -#endif -#if !defined(S_ISBLK) -# define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) -#endif - -/* Return the exact length of the file name without zero terminator */ -#define _D_EXACT_NAMLEN(p) ((p)->d_namlen) - -/* Return the maximum size of a file name */ -#define _D_ALLOC_NAMLEN(p) ((PATH_MAX)+1) - - -#ifdef __cplusplus -extern "C" { -#endif - - -/* Wide-character version */ -struct _wdirent { - /* Always zero */ - long d_ino; - - /* Position of next file in a directory stream */ - long d_off; - - /* Structure size */ - unsigned short d_reclen; - - /* Length of name without \0 */ - size_t d_namlen; - - /* File type */ - int d_type; - - /* File name */ - wchar_t d_name[PATH_MAX+1]; -}; -typedef struct _wdirent _wdirent; - -struct _WDIR { - /* Current directory entry */ - struct _wdirent ent; - - /* Private file data */ - WIN32_FIND_DATAW data; - - /* True if data is valid */ - int cached; - - /* True if next entry is invalid */ - int invalid; - - /* Win32 search handle */ - HANDLE handle; - - /* Initial directory name */ - wchar_t *patt; -}; -typedef struct _WDIR _WDIR; - -/* Multi-byte character version */ -struct dirent { - /* Always zero */ - long d_ino; - - /* Position of next file in a directory stream */ - long d_off; - - /* Structure size */ - unsigned short d_reclen; - - /* Length of name without \0 */ - size_t d_namlen; - - /* File type */ - int d_type; - - /* File name */ - char d_name[PATH_MAX+1]; -}; -typedef struct dirent dirent; - -struct DIR { - struct dirent ent; - struct _WDIR *wdirp; -}; -typedef struct DIR DIR; - - -/* Dirent functions */ -static DIR *opendir(const char *dirname); -static _WDIR *_wopendir(const wchar_t *dirname); - -static struct dirent *readdir(DIR *dirp); -static struct _wdirent *_wreaddir(_WDIR *dirp); - -static int readdir_r( - DIR *dirp, struct dirent *entry, struct dirent **result); -static int _wreaddir_r( - _WDIR *dirp, struct _wdirent *entry, struct _wdirent **result); - -static int closedir(DIR *dirp); -static int _wclosedir(_WDIR *dirp); - -static void rewinddir(DIR *dirp); -static void _wrewinddir(_WDIR *dirp); - -static long telldir(DIR *dirp); -static long _wtelldir(_WDIR *dirp); - -static void seekdir(DIR *dirp, long loc); -static void _wseekdir(_WDIR *dirp, long loc); - -static int scandir(const char *dirname, struct dirent ***namelist, - int (*filter)(const struct dirent*), - int (*compare)(const struct dirent**, const struct dirent**)); - -static int alphasort(const struct dirent **a, const struct dirent **b); - -static int versionsort(const struct dirent **a, const struct dirent **b); - -static int strverscmp(const char *a, const char *b); - -/* For compatibility with Symbian */ -#define wdirent _wdirent -#define WDIR _WDIR -#define wopendir _wopendir -#define wreaddir _wreaddir -#define wclosedir _wclosedir -#define wrewinddir _wrewinddir -#define wtelldir _wtelldir -#define wseekdir _wseekdir - -/* Compatibility with older Microsoft compilers and non-Microsoft compilers */ -#if !defined(_MSC_VER) || _MSC_VER < 1400 -# define wcstombs_s dirent_wcstombs_s -# define mbstowcs_s dirent_mbstowcs_s -#endif - -/* Optimize dirent_set_errno() away on modern Microsoft compilers */ -#if defined(_MSC_VER) && _MSC_VER >= 1400 -# define dirent_set_errno _set_errno -#endif - - -/* Internal utility functions */ -static WIN32_FIND_DATAW *dirent_first(_WDIR *dirp); -static WIN32_FIND_DATAW *dirent_next(_WDIR *dirp); -static long dirent_hash(WIN32_FIND_DATAW *datap); - -#if !defined(_MSC_VER) || _MSC_VER < 1400 -static int dirent_mbstowcs_s( - size_t *pReturnValue, wchar_t *wcstr, size_t sizeInWords, - const char *mbstr, size_t count); -#endif - -#if !defined(_MSC_VER) || _MSC_VER < 1400 -static int dirent_wcstombs_s( - size_t *pReturnValue, char *mbstr, size_t sizeInBytes, - const wchar_t *wcstr, size_t count); -#endif - -#if !defined(_MSC_VER) || _MSC_VER < 1400 -static void dirent_set_errno(int error); -#endif - - -/* - * Open directory stream DIRNAME for read and return a pointer to the - * internal working area that is used to retrieve individual directory - * entries. - */ -static _WDIR * -_wopendir(const wchar_t *dirname) -{ - wchar_t *p; - - /* Must have directory name */ - if (dirname == NULL || dirname[0] == '\0') { - dirent_set_errno(ENOENT); - return NULL; - } - - /* Allocate new _WDIR structure */ - _WDIR *dirp = (_WDIR*) malloc(sizeof(struct _WDIR)); - if (!dirp) - return NULL; - - /* Reset _WDIR structure */ - dirp->handle = INVALID_HANDLE_VALUE; - dirp->patt = NULL; - dirp->cached = 0; - dirp->invalid = 0; - - /* - * Compute the length of full path plus zero terminator - * - * Note that on WinRT there's no way to convert relative paths - * into absolute paths, so just assume it is an absolute path. - */ -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) - /* Desktop */ - DWORD n = GetFullPathNameW(dirname, 0, NULL, NULL); -#else - /* WinRT */ - size_t n = wcslen(dirname); -#endif - - /* Allocate room for absolute directory name and search pattern */ - dirp->patt = (wchar_t*) malloc(sizeof(wchar_t) * n + 16); - if (dirp->patt == NULL) - goto exit_closedir; - - /* - * Convert relative directory name to an absolute one. This - * allows rewinddir() to function correctly even when current - * working directory is changed between opendir() and rewinddir(). - * - * Note that on WinRT there's no way to convert relative paths - * into absolute paths, so just assume it is an absolute path. - */ -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) - /* Desktop */ - n = GetFullPathNameW(dirname, n, dirp->patt, NULL); - if (n <= 0) - goto exit_closedir; -#else - /* WinRT */ - wcsncpy_s(dirp->patt, n+1, dirname, n); -#endif - - /* Append search pattern \* to the directory name */ - p = dirp->patt + n; - switch (p[-1]) { - case '\\': - case '/': - case ':': - /* Directory ends in path separator, e.g. c:\temp\ */ - /*NOP*/; - break; - - default: - /* Directory name doesn't end in path separator */ - *p++ = '\\'; - } - *p++ = '*'; - *p = '\0'; - - /* Open directory stream and retrieve the first entry */ - if (!dirent_first(dirp)) - goto exit_closedir; - - /* Success */ - return dirp; - - /* Failure */ -exit_closedir: - _wclosedir(dirp); - return NULL; -} - -/* - * Read next directory entry. - * - * Returns pointer to static directory entry which may be overwritten by - * subsequent calls to _wreaddir(). - */ -static struct _wdirent * -_wreaddir(_WDIR *dirp) -{ - /* - * Read directory entry to buffer. We can safely ignore the return - * value as entry will be set to NULL in case of error. - */ - struct _wdirent *entry; - (void) _wreaddir_r(dirp, &dirp->ent, &entry); - - /* Return pointer to statically allocated directory entry */ - return entry; -} - -/* - * Read next directory entry. - * - * Returns zero on success. If end of directory stream is reached, then sets - * result to NULL and returns zero. - */ -static int -_wreaddir_r( - _WDIR *dirp, struct _wdirent *entry, struct _wdirent **result) -{ - /* Validate directory handle */ - if (!dirp || dirp->handle == INVALID_HANDLE_VALUE || !dirp->patt) { - dirent_set_errno(EBADF); - *result = NULL; - return -1; - } - - /* Read next directory entry */ - WIN32_FIND_DATAW *datap = dirent_next(dirp); - if (!datap) { - /* Return NULL to indicate end of directory */ - *result = NULL; - return /*OK*/0; - } - - /* - * Copy file name as wide-character string. If the file name is too - * long to fit in to the destination buffer, then truncate file name - * to PATH_MAX characters and zero-terminate the buffer. - */ - size_t i = 0; - while (i < PATH_MAX && datap->cFileName[i] != 0) { - entry->d_name[i] = datap->cFileName[i]; - i++; - } - entry->d_name[i] = 0; - - /* Length of file name excluding zero terminator */ - entry->d_namlen = i; - - /* Determine file type */ - DWORD attr = datap->dwFileAttributes; - if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) - entry->d_type = DT_CHR; - else if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) != 0) - entry->d_type = DT_LNK; - else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) - entry->d_type = DT_DIR; - else - entry->d_type = DT_REG; - - /* Read the next directory entry to cache */ - datap = dirent_next(dirp); - if (datap) { - /* Compute 31-bit hash of the next directory entry */ - entry->d_off = dirent_hash(datap); - - /* Push the next directory entry back to cache */ - dirp->cached = 1; - } else { - /* End of directory stream */ - entry->d_off = (long) ((~0UL) >> 1); - } - - /* Reset other fields */ - entry->d_ino = 0; - entry->d_reclen = sizeof(struct _wdirent); - - /* Set result address */ - *result = entry; - return /*OK*/0; -} - -/* - * Close directory stream opened by opendir() function. This invalidates the - * DIR structure as well as any directory entry read previously by - * _wreaddir(). - */ -static int -_wclosedir(_WDIR *dirp) -{ - if (!dirp) { - dirent_set_errno(EBADF); - return /*failure*/-1; - } - - /* - * Release search handle if we have one. Being able to handle - * partially initialized _WDIR structure allows us to use this - * function to handle errors occuring within _wopendir. - */ - if (dirp->handle != INVALID_HANDLE_VALUE) { - FindClose(dirp->handle); - } - - /* - * Release search pattern. Note that we don't need to care if - * dirp->patt is NULL or not: function free is guaranteed to act - * appropriately. - */ - free(dirp->patt); - - /* Release directory structure */ - free(dirp); - return /*success*/0; -} - -/* - * Rewind directory stream such that _wreaddir() returns the very first - * file name again. - */ -static void _wrewinddir(_WDIR* dirp) -{ - /* Check directory pointer */ - if (!dirp || dirp->handle == INVALID_HANDLE_VALUE || !dirp->patt) - return; - - /* Release existing search handle */ - FindClose(dirp->handle); - - /* Open new search handle */ - dirent_first(dirp); -} - -/* Get first directory entry */ -static WIN32_FIND_DATAW * -dirent_first(_WDIR *dirp) -{ - /* Open directory and retrieve the first entry */ - dirp->handle = FindFirstFileExW( - dirp->patt, FindExInfoStandard, &dirp->data, - FindExSearchNameMatch, NULL, 0); - if (dirp->handle == INVALID_HANDLE_VALUE) - goto error; - - /* A directory entry is now waiting in memory */ - dirp->cached = 1; - return &dirp->data; - -error: - /* Failed to open directory: no directory entry in memory */ - dirp->cached = 0; - dirp->invalid = 1; - - /* Set error code */ - DWORD errorcode = GetLastError(); - switch (errorcode) { - case ERROR_ACCESS_DENIED: - /* No read access to directory */ - dirent_set_errno(EACCES); - break; - - case ERROR_DIRECTORY: - /* Directory name is invalid */ - dirent_set_errno(ENOTDIR); - break; - - case ERROR_PATH_NOT_FOUND: - default: - /* Cannot find the file */ - dirent_set_errno(ENOENT); - } - return NULL; -} - -/* Get next directory entry */ -static WIN32_FIND_DATAW * -dirent_next(_WDIR *dirp) -{ - /* Return NULL if seek position was invalid */ - if (dirp->invalid) - return NULL; - - /* Is the next directory entry already in cache? */ - if (dirp->cached) { - /* Yes, a valid directory entry found in memory */ - dirp->cached = 0; - return &dirp->data; - } - - /* Read the next directory entry from stream */ - if (FindNextFileW(dirp->handle, &dirp->data) == FALSE) { - /* End of directory stream */ - return NULL; - } - - /* Success */ - return &dirp->data; -} - -/* - * Compute 31-bit hash of file name. - * - * See djb2 at http://www.cse.yorku.ca/~oz/hash.html - */ -static long -dirent_hash(WIN32_FIND_DATAW *datap) -{ - unsigned long hash = 5381; - unsigned long c; - const wchar_t *p = datap->cFileName; - const wchar_t *e = p + MAX_PATH; - while (p != e && (c = *p++) != 0) { - hash = (hash << 5) + hash + c; - } - - return (long) (hash & ((~0UL) >> 1)); -} - -/* Open directory stream using plain old C-string */ -static DIR *opendir(const char *dirname) -{ - /* Must have directory name */ - if (dirname == NULL || dirname[0] == '\0') { - dirent_set_errno(ENOENT); - return NULL; - } - - /* Allocate memory for DIR structure */ - struct DIR *dirp = (DIR*) malloc(sizeof(struct DIR)); - if (!dirp) - return NULL; - - /* Convert directory name to wide-character string */ - wchar_t wname[PATH_MAX + 1]; - size_t n; - int error = mbstowcs_s(&n, wname, PATH_MAX + 1, dirname, PATH_MAX+1); - if (error) - goto exit_failure; - - /* Open directory stream using wide-character name */ - dirp->wdirp = _wopendir(wname); - if (!dirp->wdirp) - goto exit_failure; - - /* Success */ - return dirp; - - /* Failure */ -exit_failure: - free(dirp); - return NULL; -} - -/* Read next directory entry */ -static struct dirent * -readdir(DIR *dirp) -{ - /* - * Read directory entry to buffer. We can safely ignore the return - * value as entry will be set to NULL in case of error. - */ - struct dirent *entry; - (void) readdir_r(dirp, &dirp->ent, &entry); - - /* Return pointer to statically allocated directory entry */ - return entry; -} - -/* - * Read next directory entry into called-allocated buffer. - * - * Returns zero on success. If the end of directory stream is reached, then - * sets result to NULL and returns zero. - */ -static int -readdir_r( - DIR *dirp, struct dirent *entry, struct dirent **result) -{ - /* Read next directory entry */ - WIN32_FIND_DATAW *datap = dirent_next(dirp->wdirp); - if (!datap) { - /* No more directory entries */ - *result = NULL; - return /*OK*/0; - } - - /* Attempt to convert file name to multi-byte string */ - size_t n; - int error = wcstombs_s( - &n, entry->d_name, PATH_MAX + 1, - datap->cFileName, PATH_MAX + 1); - - /* - * If the file name cannot be represented by a multi-byte string, then - * attempt to use old 8+3 file name. This allows the program to - * access files although file names may seem unfamiliar to the user. - * - * Be ware that the code below cannot come up with a short file name - * unless the file system provides one. At least VirtualBox shared - * folders fail to do this. - */ - if (error && datap->cAlternateFileName[0] != '\0') { - error = wcstombs_s( - &n, entry->d_name, PATH_MAX + 1, - datap->cAlternateFileName, PATH_MAX + 1); - } - - if (!error) { - /* Length of file name excluding zero terminator */ - entry->d_namlen = n - 1; - - /* Determine file type */ - DWORD attr = datap->dwFileAttributes; - if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) - entry->d_type = DT_CHR; - else if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) != 0) - entry->d_type = DT_LNK; - else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) - entry->d_type = DT_DIR; - else - entry->d_type = DT_REG; - - /* Get offset of next file */ - datap = dirent_next(dirp->wdirp); - if (datap) { - /* Compute 31-bit hash of the next directory entry */ - entry->d_off = dirent_hash(datap); - - /* Push the next directory entry back to cache */ - dirp->wdirp->cached = 1; - } else { - /* End of directory stream */ - entry->d_off = (long) ((~0UL) >> 1); - } - - /* Reset fields */ - entry->d_ino = 0; - entry->d_reclen = sizeof(struct dirent); - } else { - /* - * Cannot convert file name to multi-byte string so construct - * an erroneous directory entry and return that. Note that - * we cannot return NULL as that would stop the processing - * of directory entries completely. - */ - entry->d_name[0] = '?'; - entry->d_name[1] = '\0'; - entry->d_namlen = 1; - entry->d_type = DT_UNKNOWN; - entry->d_ino = 0; - entry->d_off = -1; - entry->d_reclen = 0; - } - - /* Return pointer to directory entry */ - *result = entry; - return /*OK*/0; -} - -/* Close directory stream */ -static int -closedir(DIR *dirp) -{ - int ok; - - if (!dirp) - goto exit_failure; - - /* Close wide-character directory stream */ - ok = _wclosedir(dirp->wdirp); - dirp->wdirp = NULL; - - /* Release multi-byte character version */ - free(dirp); - return ok; - -exit_failure: - /* Invalid directory stream */ - dirent_set_errno(EBADF); - return /*failure*/-1; -} - -/* Rewind directory stream to beginning */ -static void -rewinddir(DIR *dirp) -{ - if (!dirp) - return; - - /* Rewind wide-character string directory stream */ - _wrewinddir(dirp->wdirp); -} - -/* Get position of directory stream */ -static long -_wtelldir(_WDIR *dirp) -{ - if (!dirp || dirp->handle == INVALID_HANDLE_VALUE) { - dirent_set_errno(EBADF); - return /*failure*/-1; - } - - /* Read next file entry */ - WIN32_FIND_DATAW *datap = dirent_next(dirp); - if (!datap) { - /* End of directory stream */ - return (long) ((~0UL) >> 1); - } - - /* Store file entry to cache for readdir() */ - dirp->cached = 1; - - /* Return the 31-bit hash code to be used as stream position */ - return dirent_hash(datap); -} - -/* Get position of directory stream */ -static long -telldir(DIR *dirp) -{ - if (!dirp) { - dirent_set_errno(EBADF); - return -1; - } - - return _wtelldir(dirp->wdirp); -} - -/* Seek directory stream to offset */ -static void -_wseekdir(_WDIR *dirp, long loc) -{ - if (!dirp) - return; - - /* Directory must be open */ - if (dirp->handle == INVALID_HANDLE_VALUE) - goto exit_failure; - - /* Ensure that seek position is valid */ - if (loc < 0) - goto exit_failure; - - /* Restart directory stream from the beginning */ - FindClose(dirp->handle); - if (!dirent_first(dirp)) - goto exit_failure; - - /* Reset invalid flag so that we can read from the stream again */ - dirp->invalid = 0; - - /* - * Read directory entries from the beginning until the hash matches a - * file name. Be ware that hash code is only 31 bits longs and - * duplicates are possible: the hash code cannot return the position - * with 100.00% accuracy! Moreover, the method is slow for large - * directories. - */ - long hash; - do { - /* Read next directory entry */ - WIN32_FIND_DATAW *datap = dirent_next(dirp); - if (!datap) { - /* - * End of directory stream was reached before finding - * the requested location. Perhaps the file in - * question was deleted or moved out of the directory. - */ - goto exit_failure; - } - - /* Does the file name match the hash? */ - hash = dirent_hash(datap); - } while (hash != loc); - - /* - * File name matches the hash! Push the directory entry back to cache - * from where next readdir() will return it. - */ - dirp->cached = 1; - dirp->invalid = 0; - return; - -exit_failure: - /* Ensure that readdir will return NULL */ - dirp->invalid = 1; -} - -/* Seek directory stream to offset */ -static void -seekdir(DIR *dirp, long loc) -{ - if (!dirp) - return; - - _wseekdir(dirp->wdirp, loc); -} - -/* Scan directory for entries */ -static int -scandir( - const char *dirname, struct dirent ***namelist, - int (*filter)(const struct dirent*), - int (*compare)(const struct dirent**, const struct dirent**)) -{ - int result; - - /* Open directory stream */ - DIR *dir = opendir(dirname); - if (!dir) { - /* Cannot open directory */ - return /*Error*/ -1; - } - - /* Read directory entries to memory */ - struct dirent *tmp = NULL; - struct dirent **files = NULL; - size_t size = 0; - size_t allocated = 0; - while (1) { - /* Allocate room for a temporary directory entry */ - if (!tmp) { - tmp = (struct dirent*) malloc(sizeof(struct dirent)); - if (!tmp) - goto exit_failure; - } - - /* Read directory entry to temporary area */ - struct dirent *entry; - if (readdir_r(dir, tmp, &entry) != /*OK*/0) - goto exit_failure; - - /* Stop if we already read the last directory entry */ - if (entry == NULL) - goto exit_success; - - /* Determine whether to include the entry in results */ - if (filter && !filter(tmp)) - continue; - - /* Enlarge pointer table to make room for another pointer */ - if (size >= allocated) { - /* Compute number of entries in the new table */ - size_t num_entries = size * 2 + 16; - - /* Allocate new pointer table or enlarge existing */ - void *p = realloc(files, sizeof(void*) * num_entries); - if (!p) - goto exit_failure; - - /* Got the memory */ - files = (dirent**) p; - allocated = num_entries; - } - - /* Store the temporary entry to ptr table */ - files[size++] = tmp; - tmp = NULL; - } - -exit_failure: - /* Release allocated entries */ - for (size_t i = 0; i < size; i++) { - free(files[i]); - } - - /* Release the pointer table */ - free(files); - files = NULL; - - /* Exit with error code */ - result = /*error*/ -1; - goto exit_status; - -exit_success: - /* Sort directory entries */ - if (size > 1 && compare) { - qsort(files, size, sizeof(void*), - (int (*) (const void*, const void*)) compare); - } - - /* Pass pointer table to caller */ - if (namelist) - *namelist = files; - - /* Return the number of directory entries read */ - result = (int) size; - -exit_status: - /* Release temporary directory entry, if we had one */ - free(tmp); - - /* Close directory stream */ - closedir(dir); - return result; -} - -/* Alphabetical sorting */ -static int -alphasort(const struct dirent **a, const struct dirent **b) -{ - return strcoll((*a)->d_name, (*b)->d_name); -} - -/* Sort versions */ -static int -versionsort(const struct dirent **a, const struct dirent **b) -{ - return strverscmp((*a)->d_name, (*b)->d_name); -} - -/* Compare strings */ -static int -strverscmp(const char *a, const char *b) -{ - size_t i = 0; - size_t j; - - /* Find first difference */ - while (a[i] == b[i]) { - if (a[i] == '\0') { - /* No difference */ - return 0; - } - ++i; - } - - /* Count backwards and find the leftmost digit */ - j = i; - while (j > 0 && isdigit(a[j-1])) { - --j; - } - - /* Determine mode of comparison */ - if (a[j] == '0' || b[j] == '0') { - /* Find the next non-zero digit */ - while (a[j] == '0' && a[j] == b[j]) { - j++; - } - - /* String with more digits is smaller, e.g 002 < 01 */ - if (isdigit(a[j])) { - if (!isdigit(b[j])) { - return -1; - } - } else if (isdigit(b[j])) { - return 1; - } - } else if (isdigit(a[j]) && isdigit(b[j])) { - /* Numeric comparison */ - size_t k1 = j; - size_t k2 = j; - - /* Compute number of digits in each string */ - while (isdigit(a[k1])) { - k1++; - } - while (isdigit(b[k2])) { - k2++; - } - - /* Number with more digits is bigger, e.g 999 < 1000 */ - if (k1 < k2) - return -1; - else if (k1 > k2) - return 1; - } - - /* Alphabetical comparison */ - return (int) ((unsigned char) a[i]) - ((unsigned char) b[i]); -} - -/* Convert multi-byte string to wide character string */ -#if !defined(_MSC_VER) || _MSC_VER < 1400 -static int -dirent_mbstowcs_s( - size_t *pReturnValue, wchar_t *wcstr, - size_t sizeInWords, const char *mbstr, size_t count) -{ - /* Older Visual Studio or non-Microsoft compiler */ - size_t n = mbstowcs(wcstr, mbstr, sizeInWords); - if (wcstr && n >= count) - return /*error*/ 1; - - /* Zero-terminate output buffer */ - if (wcstr && sizeInWords) { - if (n >= sizeInWords) - n = sizeInWords - 1; - wcstr[n] = 0; - } - - /* Length of multi-byte string with zero terminator */ - if (pReturnValue) { - *pReturnValue = n + 1; - } - - /* Success */ - return 0; -} -#endif - -/* Convert wide-character string to multi-byte string */ -#if !defined(_MSC_VER) || _MSC_VER < 1400 -static int -dirent_wcstombs_s( - size_t *pReturnValue, char *mbstr, - size_t sizeInBytes, const wchar_t *wcstr, size_t count) -{ - /* Older Visual Studio or non-Microsoft compiler */ - size_t n = wcstombs(mbstr, wcstr, sizeInBytes); - if (mbstr && n >= count) - return /*error*/1; - - /* Zero-terminate output buffer */ - if (mbstr && sizeInBytes) { - if (n >= sizeInBytes) { - n = sizeInBytes - 1; - } - mbstr[n] = '\0'; - } - - /* Length of resulting multi-bytes string WITH zero-terminator */ - if (pReturnValue) { - *pReturnValue = n + 1; - } - - /* Success */ - return 0; -} -#endif - -/* Set errno variable */ -#if !defined(_MSC_VER) || _MSC_VER < 1400 -static void -dirent_set_errno(int error) -{ - /* Non-Microsoft compiler or older Microsoft compiler */ - errno = error; -} -#endif - -#ifdef __cplusplus -} -#endif -#endif /*DIRENT_H*/ diff --git a/windows/src/getopt.c b/windows/src/getopt.c index ddd7104e0..d70905d9c 100644..120000 --- a/windows/src/getopt.c +++ b/windows/src/getopt.c @@ -1,972 +1 @@ -/* Getopt for Microsoft C -This code is a modification of the Free Software Foundation, Inc. -Getopt library for parsing command line argument the purpose was -to provide a Microsoft Visual C friendly derivative. This code -provides functionality for both Unicode and Multibyte builds. - -Date: 02/03/2011 - Ludvik Jerabek - Initial Release -Version: 1.0 -Comment: Supports getopt, getopt_long, and getopt_long_only -and POSIXLY_CORRECT environment flag -License: LGPL - -Revisions: - -02/03/2011 - Ludvik Jerabek - Initial Release -02/20/2011 - Ludvik Jerabek - Fixed compiler warnings at Level 4 -07/05/2011 - Ludvik Jerabek - Added no_argument, required_argument, optional_argument defs -08/03/2011 - Ludvik Jerabek - Fixed non-argument runtime bug which caused runtime exception -08/09/2011 - Ludvik Jerabek - Added code to export functions for DLL and LIB -02/15/2012 - Ludvik Jerabek - Fixed _GETOPT_THROW definition missing in implementation file -08/01/2012 - Ludvik Jerabek - Created separate functions for char and wchar_t characters so single dll can do both unicode and ansi -10/15/2012 - Ludvik Jerabek - Modified to match latest GNU features -06/19/2015 - Ludvik Jerabek - Fixed maximum option limitation caused by option_a (255) and option_w (65535) structure val variable - -**DISCLAIMER** -THIS MATERIAL IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, -EITHER EXPRESS OR IMPLIED, INCLUDING, BUT Not LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE, OR NON-INFRINGEMENT. SOME JURISDICTIONS DO NOT ALLOW THE -EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY NOT -APPLY TO YOU. IN NO EVENT WILL I BE LIABLE TO ANY PARTY FOR ANY -DIRECT, INDIRECT, SPECIAL OR OTHER CONSEQUENTIAL DAMAGES FOR ANY -USE OF THIS MATERIAL INCLUDING, WITHOUT LIMITATION, ANY LOST -PROFITS, BUSINESS INTERRUPTION, LOSS OF PROGRAMS OR OTHER DATA ON -YOUR INFORMATION HANDLING SYSTEM OR OTHERWISE, EVEN If WE ARE -EXPRESSLY ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. -*/ -#include <stdlib.h> -#include <stdio.h> -#include <malloc.h> -#include "getopt.h" - -#ifdef __cplusplus - #define _GETOPT_THROW throw() -#else - #define _GETOPT_THROW -#endif - -int optind = 1; -int opterr = 1; -int optopt = '?'; -enum ENUM_ORDERING { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER }; - -// -// -// Ansi structures and functions follow -// -// - -static struct _getopt_data_a -{ - int optind; - int opterr; - int optopt; - char *optarg; - int __initialized; - char *__nextchar; - enum ENUM_ORDERING __ordering; - int __posixly_correct; - int __first_nonopt; - int __last_nonopt; -} getopt_data_a; -char *optarg_a; - -static void exchange_a(char **argv, struct _getopt_data_a *d) -{ - int bottom = d->__first_nonopt; - int middle = d->__last_nonopt; - int top = d->optind; - char *tem; - while (top > middle && middle > bottom) - { - if (top - middle > middle - bottom) - { - int len = middle - bottom; - register int i; - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[top - (middle - bottom) + i]; - argv[top - (middle - bottom) + i] = tem; - } - top -= len; - } - else - { - int len = top - middle; - register int i; - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[middle + i]; - argv[middle + i] = tem; - } - bottom += len; - } - } - d->__first_nonopt += (d->optind - d->__last_nonopt); - d->__last_nonopt = d->optind; -} -static const char *_getopt_initialize_a (const char *optstring, struct _getopt_data_a *d, int posixly_correct) -{ - d->__first_nonopt = d->__last_nonopt = d->optind; - d->__nextchar = NULL; - d->__posixly_correct = posixly_correct | !!getenv("POSIXLY_CORRECT"); - if (optstring[0] == '-') - { - d->__ordering = RETURN_IN_ORDER; - ++optstring; - } - else if (optstring[0] == '+') - { - d->__ordering = REQUIRE_ORDER; - ++optstring; - } - else if (d->__posixly_correct) - d->__ordering = REQUIRE_ORDER; - else - d->__ordering = PERMUTE; - return optstring; -} -int _getopt_internal_r_a (int argc, char *const *argv, const char *optstring, const struct option_a *longopts, int *longind, int long_only, struct _getopt_data_a *d, int posixly_correct) -{ - int print_errors = d->opterr; - if (argc < 1) - return -1; - d->optarg = NULL; - if (d->optind == 0 || !d->__initialized) - { - if (d->optind == 0) - d->optind = 1; - optstring = _getopt_initialize_a (optstring, d, posixly_correct); - d->__initialized = 1; - } - else if (optstring[0] == '-' || optstring[0] == '+') - optstring++; - if (optstring[0] == ':') - print_errors = 0; - if (d->__nextchar == NULL || *d->__nextchar == '\0') - { - if (d->__last_nonopt > d->optind) - d->__last_nonopt = d->optind; - if (d->__first_nonopt > d->optind) - d->__first_nonopt = d->optind; - if (d->__ordering == PERMUTE) - { - if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind) - exchange_a ((char **) argv, d); - else if (d->__last_nonopt != d->optind) - d->__first_nonopt = d->optind; - while (d->optind < argc && (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0')) - d->optind++; - d->__last_nonopt = d->optind; - } - if (d->optind != argc && !strcmp(argv[d->optind], "--")) - { - d->optind++; - if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind) - exchange_a((char **) argv, d); - else if (d->__first_nonopt == d->__last_nonopt) - d->__first_nonopt = d->optind; - d->__last_nonopt = argc; - d->optind = argc; - } - if (d->optind == argc) - { - if (d->__first_nonopt != d->__last_nonopt) - d->optind = d->__first_nonopt; - return -1; - } - if ((argv[d->optind][0] != '-' || argv[d->optind][1] == '\0')) - { - if (d->__ordering == REQUIRE_ORDER) - return -1; - d->optarg = argv[d->optind++]; - return 1; - } - d->__nextchar = (argv[d->optind] + 1 + (longopts != NULL && argv[d->optind][1] == '-')); - } - if (longopts != NULL && (argv[d->optind][1] == '-' || (long_only && (argv[d->optind][2] || !strchr(optstring, argv[d->optind][1]))))) - { - char *nameend; - unsigned int namelen; - const struct option_a *p; - const struct option_a *pfound = NULL; - struct option_list - { - const struct option_a *p; - struct option_list *next; - } *ambig_list = NULL; - int exact = 0; - int indfound = -1; - int option_index; - for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++); - namelen = (unsigned int)(nameend - d->__nextchar); - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp(p->name, d->__nextchar, namelen)) - { - if (namelen == (unsigned int)strlen(p->name)) - { - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - pfound = p; - indfound = option_index; - } - else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val) - { - struct option_list *newp = (struct option_list*)alloca(sizeof(*newp)); - newp->p = p; - newp->next = ambig_list; - ambig_list = newp; - } - } - if (ambig_list != NULL && !exact) - { - if (print_errors) - { - struct option_list first; - first.p = pfound; - first.next = ambig_list; - ambig_list = &first; - fprintf (stderr, "%s: option '%s' is ambiguous; possibilities:", argv[0], argv[d->optind]); - do - { - fprintf (stderr, " '--%s'", ambig_list->p->name); - ambig_list = ambig_list->next; - } - while (ambig_list != NULL); - fputc ('\n', stderr); - } - d->__nextchar += strlen(d->__nextchar); - d->optind++; - d->optopt = 0; - return '?'; - } - if (pfound != NULL) - { - option_index = indfound; - d->optind++; - if (*nameend) - { - if (pfound->has_arg) - d->optarg = nameend + 1; - else - { - if (print_errors) - { - if (argv[d->optind - 1][1] == '-') - { - fprintf(stderr, "%s: option '--%s' doesn't allow an argument\n",argv[0], pfound->name); - } - else - { - fprintf(stderr, "%s: option '%c%s' doesn't allow an argument\n",argv[0], argv[d->optind - 1][0],pfound->name); - } - } - d->__nextchar += strlen(d->__nextchar); - d->optopt = pfound->val; - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (d->optind < argc) - d->optarg = argv[d->optind++]; - else - { - if (print_errors) - { - fprintf(stderr,"%s: option '--%s' requires an argument\n",argv[0], pfound->name); - } - d->__nextchar += strlen(d->__nextchar); - d->optopt = pfound->val; - return optstring[0] == ':' ? ':' : '?'; - } - } - d->__nextchar += strlen(d->__nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - if (!long_only || argv[d->optind][1] == '-' || strchr(optstring, *d->__nextchar) == NULL) - { - if (print_errors) - { - if (argv[d->optind][1] == '-') - { - fprintf(stderr, "%s: unrecognized option '--%s'\n",argv[0], d->__nextchar); - } - else - { - fprintf(stderr, "%s: unrecognized option '%c%s'\n",argv[0], argv[d->optind][0], d->__nextchar); - } - } - d->__nextchar = (char *)""; - d->optind++; - d->optopt = 0; - return '?'; - } - } - { - char c = *d->__nextchar++; - char *temp = (char*)strchr(optstring, c); - if (*d->__nextchar == '\0') - ++d->optind; - if (temp == NULL || c == ':' || c == ';') - { - if (print_errors) - { - fprintf(stderr, "%s: invalid option -- '%c'\n", argv[0], c); - } - d->optopt = c; - return '?'; - } - if (temp[0] == 'W' && temp[1] == ';') - { - char *nameend; - const struct option_a *p; - const struct option_a *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = 0; - int option_index; - if (longopts == NULL) - goto no_longs; - if (*d->__nextchar != '\0') - { - d->optarg = d->__nextchar; - d->optind++; - } - else if (d->optind == argc) - { - if (print_errors) - { - fprintf(stderr,"%s: option requires an argument -- '%c'\n",argv[0], c); - } - d->optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - return c; - } - else - d->optarg = argv[d->optind++]; - for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '='; nameend++); - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp(p->name, d->__nextchar, nameend - d->__nextchar)) - { - if ((unsigned int) (nameend - d->__nextchar) == strlen(p->name)) - { - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - pfound = p; - indfound = option_index; - } - else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val) - ambig = 1; - } - if (ambig && !exact) - { - if (print_errors) - { - fprintf(stderr, "%s: option '-W %s' is ambiguous\n",argv[0], d->optarg); - } - d->__nextchar += strlen(d->__nextchar); - d->optind++; - return '?'; - } - if (pfound != NULL) - { - option_index = indfound; - if (*nameend) - { - if (pfound->has_arg) - d->optarg = nameend + 1; - else - { - if (print_errors) - { - fprintf(stderr, "%s: option '-W %s' doesn't allow an argument\n",argv[0], pfound->name); - } - d->__nextchar += strlen(d->__nextchar); - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (d->optind < argc) - d->optarg = argv[d->optind++]; - else - { - if (print_errors) - { - fprintf(stderr, "%s: option '-W %s' requires an argument\n",argv[0], pfound->name); - } - d->__nextchar += strlen(d->__nextchar); - return optstring[0] == ':' ? ':' : '?'; - } - } - else - d->optarg = NULL; - d->__nextchar += strlen(d->__nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } -no_longs: - d->__nextchar = NULL; - return 'W'; - } - if (temp[1] == ':') - { - if (temp[2] == ':') - { - if (*d->__nextchar != '\0') - { - d->optarg = d->__nextchar; - d->optind++; - } - else - d->optarg = NULL; - d->__nextchar = NULL; - } - else - { - if (*d->__nextchar != '\0') - { - d->optarg = d->__nextchar; - d->optind++; - } - else if (d->optind == argc) - { - if (print_errors) - { - fprintf(stderr,"%s: option requires an argument -- '%c'\n",argv[0], c); - } - d->optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - } - else - d->optarg = argv[d->optind++]; - d->__nextchar = NULL; - } - } - return c; - } -} -int _getopt_internal_a (int argc, char *const *argv, const char *optstring, const struct option_a *longopts, int *longind, int long_only, int posixly_correct) -{ - int result; - getopt_data_a.optind = optind; - getopt_data_a.opterr = opterr; - result = _getopt_internal_r_a (argc, argv, optstring, longopts,longind, long_only, &getopt_data_a,posixly_correct); - optind = getopt_data_a.optind; - optarg_a = getopt_data_a.optarg; - optopt = getopt_data_a.optopt; - return result; -} -int getopt_a (int argc, char *const *argv, const char *optstring) _GETOPT_THROW -{ - return _getopt_internal_a (argc, argv, optstring, (const struct option_a *) 0, (int *) 0, 0, 0); -} -int getopt_long_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW -{ - return _getopt_internal_a (argc, argv, options, long_options, opt_index, 0, 0); -} -int getopt_long_only_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW -{ - return _getopt_internal_a (argc, argv, options, long_options, opt_index, 1, 0); -} -int _getopt_long_r_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index, struct _getopt_data_a *d) -{ - return _getopt_internal_r_a (argc, argv, options, long_options, opt_index,0, d, 0); -} -int _getopt_long_only_r_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index, struct _getopt_data_a *d) -{ - return _getopt_internal_r_a (argc, argv, options, long_options, opt_index, 1, d, 0); -} - -// -// -// Unicode Structures and Functions -// -// - -static struct _getopt_data_w -{ - int optind; - int opterr; - int optopt; - wchar_t *optarg; - int __initialized; - wchar_t *__nextchar; - enum ENUM_ORDERING __ordering; - int __posixly_correct; - int __first_nonopt; - int __last_nonopt; -} getopt_data_w; -wchar_t *optarg_w; - -static void exchange_w(wchar_t **argv, struct _getopt_data_w *d) -{ - int bottom = d->__first_nonopt; - int middle = d->__last_nonopt; - int top = d->optind; - wchar_t *tem; - while (top > middle && middle > bottom) - { - if (top - middle > middle - bottom) - { - int len = middle - bottom; - register int i; - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[top - (middle - bottom) + i]; - argv[top - (middle - bottom) + i] = tem; - } - top -= len; - } - else - { - int len = top - middle; - register int i; - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[middle + i]; - argv[middle + i] = tem; - } - bottom += len; - } - } - d->__first_nonopt += (d->optind - d->__last_nonopt); - d->__last_nonopt = d->optind; -} -static const wchar_t *_getopt_initialize_w (const wchar_t *optstring, struct _getopt_data_w *d, int posixly_correct) -{ - d->__first_nonopt = d->__last_nonopt = d->optind; - d->__nextchar = NULL; - d->__posixly_correct = posixly_correct | !!_wgetenv(L"POSIXLY_CORRECT"); - if (optstring[0] == L'-') - { - d->__ordering = RETURN_IN_ORDER; - ++optstring; - } - else if (optstring[0] == L'+') - { - d->__ordering = REQUIRE_ORDER; - ++optstring; - } - else if (d->__posixly_correct) - d->__ordering = REQUIRE_ORDER; - else - d->__ordering = PERMUTE; - return optstring; -} -int _getopt_internal_r_w (int argc, wchar_t *const *argv, const wchar_t *optstring, const struct option_w *longopts, int *longind, int long_only, struct _getopt_data_w *d, int posixly_correct) -{ - int print_errors = d->opterr; - if (argc < 1) - return -1; - d->optarg = NULL; - if (d->optind == 0 || !d->__initialized) - { - if (d->optind == 0) - d->optind = 1; - optstring = _getopt_initialize_w (optstring, d, posixly_correct); - d->__initialized = 1; - } - else if (optstring[0] == L'-' || optstring[0] == L'+') - optstring++; - if (optstring[0] == L':') - print_errors = 0; - if (d->__nextchar == NULL || *d->__nextchar == L'\0') - { - if (d->__last_nonopt > d->optind) - d->__last_nonopt = d->optind; - if (d->__first_nonopt > d->optind) - d->__first_nonopt = d->optind; - if (d->__ordering == PERMUTE) - { - if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind) - exchange_w((wchar_t **) argv, d); - else if (d->__last_nonopt != d->optind) - d->__first_nonopt = d->optind; - while (d->optind < argc && (argv[d->optind][0] != L'-' || argv[d->optind][1] == L'\0')) - d->optind++; - d->__last_nonopt = d->optind; - } - if (d->optind != argc && !wcscmp(argv[d->optind], L"--")) - { - d->optind++; - if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind) - exchange_w((wchar_t **) argv, d); - else if (d->__first_nonopt == d->__last_nonopt) - d->__first_nonopt = d->optind; - d->__last_nonopt = argc; - d->optind = argc; - } - if (d->optind == argc) - { - if (d->__first_nonopt != d->__last_nonopt) - d->optind = d->__first_nonopt; - return -1; - } - if ((argv[d->optind][0] != L'-' || argv[d->optind][1] == L'\0')) - { - if (d->__ordering == REQUIRE_ORDER) - return -1; - d->optarg = argv[d->optind++]; - return 1; - } - d->__nextchar = (argv[d->optind] + 1 + (longopts != NULL && argv[d->optind][1] == L'-')); - } - if (longopts != NULL && (argv[d->optind][1] == L'-' || (long_only && (argv[d->optind][2] || !wcschr(optstring, argv[d->optind][1]))))) - { - wchar_t *nameend; - unsigned int namelen; - const struct option_w *p; - const struct option_w *pfound = NULL; - struct option_list - { - const struct option_w *p; - struct option_list *next; - } *ambig_list = NULL; - int exact = 0; - int indfound = -1; - int option_index; - for (nameend = d->__nextchar; *nameend && *nameend != L'='; nameend++); - namelen = (unsigned int)(nameend - d->__nextchar); - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!wcsncmp(p->name, d->__nextchar, namelen)) - { - if (namelen == (unsigned int)wcslen(p->name)) - { - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - pfound = p; - indfound = option_index; - } - else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val) - { - struct option_list *newp = (struct option_list*)alloca(sizeof(*newp)); - newp->p = p; - newp->next = ambig_list; - ambig_list = newp; - } - } - if (ambig_list != NULL && !exact) - { - if (print_errors) - { - struct option_list first; - first.p = pfound; - first.next = ambig_list; - ambig_list = &first; - fwprintf(stderr, L"%s: option '%s' is ambiguous; possibilities:", argv[0], argv[d->optind]); - do - { - fwprintf (stderr, L" '--%s'", ambig_list->p->name); - ambig_list = ambig_list->next; - } - while (ambig_list != NULL); - fputwc (L'\n', stderr); - } - d->__nextchar += wcslen(d->__nextchar); - d->optind++; - d->optopt = 0; - return L'?'; - } - if (pfound != NULL) - { - option_index = indfound; - d->optind++; - if (*nameend) - { - if (pfound->has_arg) - d->optarg = nameend + 1; - else - { - if (print_errors) - { - if (argv[d->optind - 1][1] == L'-') - { - fwprintf(stderr, L"%s: option '--%s' doesn't allow an argument\n",argv[0], pfound->name); - } - else - { - fwprintf(stderr, L"%s: option '%c%s' doesn't allow an argument\n",argv[0], argv[d->optind - 1][0],pfound->name); - } - } - d->__nextchar += wcslen(d->__nextchar); - d->optopt = pfound->val; - return L'?'; - } - } - else if (pfound->has_arg == 1) - { - if (d->optind < argc) - d->optarg = argv[d->optind++]; - else - { - if (print_errors) - { - fwprintf(stderr,L"%s: option '--%s' requires an argument\n",argv[0], pfound->name); - } - d->__nextchar += wcslen(d->__nextchar); - d->optopt = pfound->val; - return optstring[0] == L':' ? L':' : L'?'; - } - } - d->__nextchar += wcslen(d->__nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - if (!long_only || argv[d->optind][1] == L'-' || wcschr(optstring, *d->__nextchar) == NULL) - { - if (print_errors) - { - if (argv[d->optind][1] == L'-') - { - fwprintf(stderr, L"%s: unrecognized option '--%s'\n",argv[0], d->__nextchar); - } - else - { - fwprintf(stderr, L"%s: unrecognized option '%c%s'\n",argv[0], argv[d->optind][0], d->__nextchar); - } - } - d->__nextchar = (wchar_t *)L""; - d->optind++; - d->optopt = 0; - return L'?'; - } - } - { - wchar_t c = *d->__nextchar++; - wchar_t *temp = (wchar_t*)wcschr(optstring, c); - if (*d->__nextchar == L'\0') - ++d->optind; - if (temp == NULL || c == L':' || c == L';') - { - if (print_errors) - { - fwprintf(stderr, L"%s: invalid option -- '%c'\n", argv[0], c); - } - d->optopt = c; - return L'?'; - } - if (temp[0] == L'W' && temp[1] == L';') - { - wchar_t *nameend; - const struct option_w *p; - const struct option_w *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = 0; - int option_index; - if (longopts == NULL) - goto no_longs; - if (*d->__nextchar != L'\0') - { - d->optarg = d->__nextchar; - d->optind++; - } - else if (d->optind == argc) - { - if (print_errors) - { - fwprintf(stderr,L"%s: option requires an argument -- '%c'\n",argv[0], c); - } - d->optopt = c; - if (optstring[0] == L':') - c = L':'; - else - c = L'?'; - return c; - } - else - d->optarg = argv[d->optind++]; - for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != L'='; nameend++); - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!wcsncmp(p->name, d->__nextchar, nameend - d->__nextchar)) - { - if ((unsigned int) (nameend - d->__nextchar) == wcslen(p->name)) - { - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - pfound = p; - indfound = option_index; - } - else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val) - ambig = 1; - } - if (ambig && !exact) - { - if (print_errors) - { - fwprintf(stderr, L"%s: option '-W %s' is ambiguous\n",argv[0], d->optarg); - } - d->__nextchar += wcslen(d->__nextchar); - d->optind++; - return L'?'; - } - if (pfound != NULL) - { - option_index = indfound; - if (*nameend) - { - if (pfound->has_arg) - d->optarg = nameend + 1; - else - { - if (print_errors) - { - fwprintf(stderr, L"%s: option '-W %s' doesn't allow an argument\n",argv[0], pfound->name); - } - d->__nextchar += wcslen(d->__nextchar); - return L'?'; - } - } - else if (pfound->has_arg == 1) - { - if (d->optind < argc) - d->optarg = argv[d->optind++]; - else - { - if (print_errors) - { - fwprintf(stderr, L"%s: option '-W %s' requires an argument\n",argv[0], pfound->name); - } - d->__nextchar += wcslen(d->__nextchar); - return optstring[0] == L':' ? L':' : L'?'; - } - } - else - d->optarg = NULL; - d->__nextchar += wcslen(d->__nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } -no_longs: - d->__nextchar = NULL; - return L'W'; - } - if (temp[1] == L':') - { - if (temp[2] == L':') - { - if (*d->__nextchar != L'\0') - { - d->optarg = d->__nextchar; - d->optind++; - } - else - d->optarg = NULL; - d->__nextchar = NULL; - } - else - { - if (*d->__nextchar != L'\0') - { - d->optarg = d->__nextchar; - d->optind++; - } - else if (d->optind == argc) - { - if (print_errors) - { - fwprintf(stderr,L"%s: option requires an argument -- '%c'\n",argv[0], c); - } - d->optopt = c; - if (optstring[0] == L':') - c = L':'; - else - c = L'?'; - } - else - d->optarg = argv[d->optind++]; - d->__nextchar = NULL; - } - } - return c; - } -} -int _getopt_internal_w (int argc, wchar_t *const *argv, const wchar_t *optstring, const struct option_w *longopts, int *longind, int long_only, int posixly_correct) -{ - int result; - getopt_data_w.optind = optind; - getopt_data_w.opterr = opterr; - result = _getopt_internal_r_w (argc, argv, optstring, longopts,longind, long_only, &getopt_data_w,posixly_correct); - optind = getopt_data_w.optind; - optarg_w = getopt_data_w.optarg; - optopt = getopt_data_w.optopt; - return result; -} -int getopt_w (int argc, wchar_t *const *argv, const wchar_t *optstring) _GETOPT_THROW -{ - return _getopt_internal_w (argc, argv, optstring, (const struct option_w *) 0, (int *) 0, 0, 0); -} -int getopt_long_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW -{ - return _getopt_internal_w (argc, argv, options, long_options, opt_index, 0, 0); -} -int getopt_long_only_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW -{ - return _getopt_internal_w (argc, argv, options, long_options, opt_index, 1, 0); -} -int _getopt_long_r_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index, struct _getopt_data_w *d) -{ - return _getopt_internal_r_w (argc, argv, options, long_options, opt_index,0, d, 0); -} -int _getopt_long_only_r_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index, struct _getopt_data_w *d) -{ - return _getopt_internal_r_w (argc, argv, options, long_options, opt_index, 1, d, 0); -}
\ No newline at end of file +../../src/lib/third_party/src/windows/getopt.c
\ No newline at end of file diff --git a/windows/src/getopt.h b/windows/src/getopt.h index 5e33682de..7ace9a428 100644..120000 --- a/windows/src/getopt.h +++ b/windows/src/getopt.h @@ -1,136 +1 @@ -/* Getopt for Microsoft C -This code is a modification of the Free Software Foundation, Inc. -Getopt library for parsing command line argument the purpose was -to provide a Microsoft Visual C friendly derivative. This code -provides functionality for both Unicode and Multibyte builds. - -Date: 02/03/2011 - Ludvik Jerabek - Initial Release -Version: 1.0 -Comment: Supports getopt, getopt_long, and getopt_long_only -and POSIXLY_CORRECT environment flag -License: LGPL - -Revisions: - -02/03/2011 - Ludvik Jerabek - Initial Release -02/20/2011 - Ludvik Jerabek - Fixed compiler warnings at Level 4 -07/05/2011 - Ludvik Jerabek - Added no_argument, required_argument, optional_argument defs -08/03/2011 - Ludvik Jerabek - Fixed non-argument runtime bug which caused runtime exception -08/09/2011 - Ludvik Jerabek - Added code to export functions for DLL and LIB -02/15/2012 - Ludvik Jerabek - Fixed _GETOPT_THROW definition missing in implementation file -08/01/2012 - Ludvik Jerabek - Created separate functions for char and wchar_t characters so single dll can do both unicode and ansi -10/15/2012 - Ludvik Jerabek - Modified to match latest GNU features -06/19/2015 - Ludvik Jerabek - Fixed maximum option limitation caused by option_a (255) and option_w (65535) structure val variable - -**DISCLAIMER** -THIS MATERIAL IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, -EITHER EXPRESS OR IMPLIED, INCLUDING, BUT Not LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE, OR NON-INFRINGEMENT. SOME JURISDICTIONS DO NOT ALLOW THE -EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY NOT -APPLY TO YOU. IN NO EVENT WILL I BE LIABLE TO ANY PARTY FOR ANY -DIRECT, INDIRECT, SPECIAL OR OTHER CONSEQUENTIAL DAMAGES FOR ANY -USE OF THIS MATERIAL INCLUDING, WITHOUT LIMITATION, ANY LOST -PROFITS, BUSINESS INTERRUPTION, LOSS OF PROGRAMS OR OTHER DATA ON -YOUR INFORMATION HANDLING SYSTEM OR OTHERWISE, EVEN If WE ARE -EXPRESSLY ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. -*/ -#ifndef __GETOPT_H_ - #define __GETOPT_H_ - - #ifdef _GETOPT_API - #undef _GETOPT_API - #endif - - #if defined(EXPORTS_GETOPT) && defined(STATIC_GETOPT) - #error "The preprocessor definitions of EXPORTS_GETOPT and STATIC_GETOPT can only be used individually" - #elif defined(STATIC_GETOPT) - #pragma message("Warning static builds of getopt violate the Lesser GNU Public License") - #define _GETOPT_API - #elif defined(EXPORTS_GETOPT) - #pragma message("Exporting getopt library") - #define _GETOPT_API __declspec(dllexport) - #else - #pragma message("Importing getopt library") - #define _GETOPT_API __declspec(dllimport) - #endif - - // Change behavior for C\C++ - #ifdef __cplusplus - #define _GETOPT_BEGIN_EXTERN_C extern "C" { - #define _GETOPT_END_EXTERN_C } - #define _GETOPT_THROW throw() - #else - #define _GETOPT_BEGIN_EXTERN_C - #define _GETOPT_END_EXTERN_C - #define _GETOPT_THROW - #endif - - // Standard GNU options - #define null_argument 0 /*Argument Null*/ - #define no_argument 0 /*Argument Switch Only*/ - #define required_argument 1 /*Argument Required*/ - #define optional_argument 2 /*Argument Optional*/ - - // Shorter Options - #define ARG_NULL 0 /*Argument Null*/ - #define ARG_NONE 0 /*Argument Switch Only*/ - #define ARG_REQ 1 /*Argument Required*/ - #define ARG_OPT 2 /*Argument Optional*/ - - #include <string.h> - #include <wchar.h> - -_GETOPT_BEGIN_EXTERN_C - - extern _GETOPT_API int optind; - extern _GETOPT_API int opterr; - extern _GETOPT_API int optopt; - - // Ansi - struct option_a - { - const char* name; - int has_arg; - int *flag; - int val; - }; - extern _GETOPT_API char *optarg_a; - extern _GETOPT_API int getopt_a(int argc, char *const *argv, const char *optstring) _GETOPT_THROW; - extern _GETOPT_API int getopt_long_a(int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW; - extern _GETOPT_API int getopt_long_only_a(int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW; - - // Unicode - struct option_w - { - const wchar_t* name; - int has_arg; - int *flag; - int val; - }; - extern _GETOPT_API wchar_t *optarg_w; - extern _GETOPT_API int getopt_w(int argc, wchar_t *const *argv, const wchar_t *optstring) _GETOPT_THROW; - extern _GETOPT_API int getopt_long_w(int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW; - extern _GETOPT_API int getopt_long_only_w(int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW; - -_GETOPT_END_EXTERN_C - - #undef _GETOPT_BEGIN_EXTERN_C - #undef _GETOPT_END_EXTERN_C - #undef _GETOPT_THROW - #undef _GETOPT_API - - #ifdef _UNICODE - #define getopt getopt_w - #define getopt_long getopt_long_w - #define getopt_long_only getopt_long_only_w - #define option option_w - #define optarg optarg_w - #else - #define getopt getopt_a - #define getopt_long getopt_long_a - #define getopt_long_only getopt_long_only_a - #define option option_a - #define optarg optarg_a - #endif -#endif // __GETOPT_H_ +../../src/lib/third_party/include/windows/getopt.h
\ No newline at end of file diff --git a/windows/src/win-gettimeofday.c b/windows/src/win-gettimeofday.c index c921b3325..c545b3933 100644..120000 --- a/windows/src/win-gettimeofday.c +++ b/windows/src/win-gettimeofday.c @@ -1,55 +1 @@ -/* -* Author: Ugo Varetto - ugovaretto@gmail.com -* This code is distributed under the terms of the Apache Software License version 2.0 -* https://opensource.org/licenses/Apache-2.0 -*/ - -#include <time.h> -#include <windows.h> - -#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) -#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 -#else -#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL -#endif - -struct timezone -{ - int tz_minuteswest; /* minutes W of Greenwich */ - int tz_dsttime; /* type of dst correction */ -}; - -int gettimeofday(struct timeval *tv, struct timezone *tz) -{ - FILETIME ft; - unsigned __int64 tmpres = 0; - static int tzflag = 0; - - if (NULL != tv) - { - GetSystemTimeAsFileTime(&ft); - - tmpres |= ft.dwHighDateTime; - tmpres <<= 32; - tmpres |= ft.dwLowDateTime; - - tmpres /= 10; /*convert into microseconds*/ - /*converting file time to unix epoch*/ - tmpres -= DELTA_EPOCH_IN_MICROSECS; - tv->tv_sec = (long)(tmpres / 1000000UL); - tv->tv_usec = (long)(tmpres % 1000000UL); - } - - if (NULL != tz) - { - if (!tzflag) - { - _tzset(); - tzflag++; - } - tz->tz_minuteswest = _timezone / 60; - tz->tz_dsttime = _daylight; - } - - return 0; -} +../../src/lib/third_party/src/windows/gettimeofday.c
\ No newline at end of file |