diff options
author | Peter Powell <petpow@saberuk.com> | 2019-12-08 19:39:02 +0000 |
---|---|---|
committer | Peter Powell <petpow@saberuk.com> | 2019-12-08 19:59:34 +0000 |
commit | a47e2df0ce833e06fa3e4034e64ec084a2bbb2d3 (patch) | |
tree | 51b20e031c52f135d927bc23643cbd831a0fddd4 | |
parent | 914d8140d98dd0adc54f739dfe550765cc466bac (diff) |
Replace our Windows getopt_long wrapper with ya_getopt.
Closes #546.
-rw-r--r-- | vendor/README.md | 10 | ||||
-rw-r--r-- | vendor/ya_getopt/ya_getopt.c | 318 | ||||
-rw-r--r-- | vendor/ya_getopt/ya_getopt.h | 77 | ||||
-rw-r--r-- | win/CMakeLists.txt | 7 | ||||
-rw-r--r-- | win/inspircd_win32wrapper.cpp | 75 | ||||
-rw-r--r-- | win/inspircd_win32wrapper.h | 18 | ||||
-rw-r--r-- | win/modules/CMakeLists.txt | 8 |
7 files changed, 416 insertions, 97 deletions
diff --git a/vendor/README.md b/vendor/README.md index 9d148c7b3..110245e6f 100644 --- a/vendor/README.md +++ b/vendor/README.md @@ -41,3 +41,13 @@ This directory contains vendored dependencies that are shipped with InspIRCd to **License** — Boost Software License **Website** — [https://github.com/nemtrif/utfcpp](https://github.com/nemtrif/utfcpp) + +## ya_getopt + +**Author** — Kubo Takehiro + +**Last Updated** — 2019-12-08 (6ce431085b81d9bb8639ed2f858c4f4fbc3ab988) + +**License** — 2-clause BSD License + +**Website** — [https://github.com/kubo/ya_getopt](https://github.com/kubo/ya_getopt) diff --git a/vendor/ya_getopt/ya_getopt.c b/vendor/ya_getopt/ya_getopt.c new file mode 100644 index 000000000..0c3ddf2ab --- /dev/null +++ b/vendor/ya_getopt/ya_getopt.c @@ -0,0 +1,318 @@ +/* -*- indent-tabs-mode: nil -*- + * + * ya_getopt - Yet another getopt + * https://github.com/kubo/ya_getopt + * + * Copyright 2015 Kubo Takehiro <kubo@jiubao.org> + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of the authors. + * + */ +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include "ya_getopt.h" + +char *ya_optarg = NULL; +int ya_optind = 1; +int ya_opterr = 1; +int ya_optopt = '?'; +static char *ya_optnext = NULL; +static int posixly_correct = -1; +static int handle_nonopt_argv = 0; + +static void ya_getopt_error(const char *optstring, const char *format, ...); +static void check_gnu_extension(const char *optstring); +static int ya_getopt_internal(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex, int long_only); +static int ya_getopt_shortopts(int argc, char * const argv[], const char *optstring, int long_only); +static int ya_getopt_longopts(int argc, char * const argv[], char *arg, const char *optstring, const struct option *longopts, int *longindex, int *long_only_flag); + +static void ya_getopt_error(const char *optstring, const char *format, ...) +{ + if (ya_opterr && optstring[0] != ':') { + va_list ap; + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); + } +} + +static void check_gnu_extension(const char *optstring) +{ + if (optstring[0] == '+' || getenv("POSIXLY_CORRECT") != NULL) { + posixly_correct = 1; + } else { + posixly_correct = 0; + } + if (optstring[0] == '-') { + handle_nonopt_argv = 1; + } else { + handle_nonopt_argv = 0; + } +} + +static int is_option(const char *arg) +{ + return arg[0] == '-' && arg[1] != '\0'; +} + +int ya_getopt(int argc, char * const argv[], const char *optstring) +{ + return ya_getopt_internal(argc, argv, optstring, NULL, NULL, 0); +} + +int ya_getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex) +{ + return ya_getopt_internal(argc, argv, optstring, longopts, longindex, 0); +} + +int ya_getopt_long_only(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex) +{ + return ya_getopt_internal(argc, argv, optstring, longopts, longindex, 1); +} + +static int ya_getopt_internal(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex, int long_only) +{ + static int start, end; + + if (ya_optopt == '?') { + ya_optopt = 0; + } + + if (posixly_correct == -1) { + check_gnu_extension(optstring); + } + + if (ya_optind == 0) { + check_gnu_extension(optstring); + ya_optind = 1; + ya_optnext = NULL; + } + + switch (optstring[0]) { + case '+': + case '-': + optstring++; + } + + if (ya_optnext == NULL && start != 0) { + int last_pos = ya_optind - 1; + + ya_optind -= end - start; + if (ya_optind <= 0) { + ya_optind = 1; + } + while (start < end--) { + int i; + char *arg = argv[end]; + + for (i = end; i < last_pos; i++) { + ((char **)argv)[i] = argv[i + 1]; + } + ((char const **)argv)[i] = arg; + last_pos--; + } + start = 0; + } + + if (ya_optind >= argc) { + ya_optarg = NULL; + return -1; + } + if (ya_optnext == NULL) { + const char *arg = argv[ya_optind]; + if (!is_option(arg)) { + if (handle_nonopt_argv) { + ya_optarg = argv[ya_optind++]; + start = 0; + return 1; + } else if (posixly_correct) { + ya_optarg = NULL; + return -1; + } else { + int i; + + start = ya_optind; + for (i = ya_optind + 1; i < argc; i++) { + if (is_option(argv[i])) { + end = i; + break; + } + } + if (i == argc) { + ya_optarg = NULL; + return -1; + } + ya_optind = i; + arg = argv[ya_optind]; + } + } + if (strcmp(arg, "--") == 0) { + ya_optind++; + return -1; + } + if (longopts != NULL && arg[1] == '-') { + return ya_getopt_longopts(argc, argv, argv[ya_optind] + 2, optstring, longopts, longindex, NULL); + } + } + + if (ya_optnext == NULL) { + ya_optnext = argv[ya_optind] + 1; + } + if (long_only) { + int long_only_flag = 0; + int rv = ya_getopt_longopts(argc, argv, ya_optnext, optstring, longopts, longindex, &long_only_flag); + if (!long_only_flag) { + ya_optnext = NULL; + return rv; + } + } + + return ya_getopt_shortopts(argc, argv, optstring, long_only); +} + +static int ya_getopt_shortopts(int argc, char * const argv[], const char *optstring, int long_only) +{ + int opt = *ya_optnext; + const char *os = strchr(optstring, opt); + + if (os == NULL) { + ya_optarg = NULL; + if (long_only) { + ya_getopt_error(optstring, "%s: unrecognized option '-%s'\n", argv[0], ya_optnext); + ya_optind++; + ya_optnext = NULL; + } else { + ya_optopt = opt; + ya_getopt_error(optstring, "%s: invalid option -- '%c'\n", argv[0], opt); + if (*(++ya_optnext) == 0) { + ya_optind++; + ya_optnext = NULL; + } + } + return '?'; + } + if (os[1] == ':') { + if (ya_optnext[1] == 0) { + ya_optind++; + ya_optnext = NULL; + if (os[2] == ':') { + /* optional argument */ + ya_optarg = NULL; + } else { + if (ya_optind == argc) { + ya_optarg = NULL; + ya_optopt = opt; + ya_getopt_error(optstring, "%s: option requires an argument -- '%c'\n", argv[0], opt); + if (optstring[0] == ':') { + return ':'; + } else { + return '?'; + } + } + ya_optarg = argv[ya_optind]; + ya_optind++; + } + } else { + ya_optarg = ya_optnext + 1; + ya_optind++; + } + ya_optnext = NULL; + } else { + ya_optarg = NULL; + if (ya_optnext[1] == 0) { + ya_optnext = NULL; + ya_optind++; + } else { + ya_optnext++; + } + } + return opt; +} + +static int ya_getopt_longopts(int argc, char * const argv[], char *arg, const char *optstring, const struct option *longopts, int *longindex, int *long_only_flag) +{ + char *val = NULL; + const struct option *opt; + size_t namelen; + int idx; + + for (idx = 0; longopts[idx].name != NULL; idx++) { + opt = &longopts[idx]; + namelen = strlen(opt->name); + if (strncmp(arg, opt->name, namelen) == 0) { + switch (arg[namelen]) { + case '\0': + switch (opt->has_arg) { + case ya_required_argument: + ya_optind++; + if (ya_optind == argc) { + ya_optarg = NULL; + ya_optopt = opt->val; + ya_getopt_error(optstring, "%s: option '--%s' requires an argument\n", argv[0], opt->name); + if (optstring[0] == ':') { + return ':'; + } else { + return '?'; + } + } + val = argv[ya_optind]; + break; + } + goto found; + case '=': + if (opt->has_arg == ya_no_argument) { + const char *hyphens = (argv[ya_optind][1] == '-') ? "--" : "-"; + + ya_optind++; + ya_optarg = NULL; + ya_optopt = opt->val; + ya_getopt_error(optstring, "%s: option '%s%s' doesn't allow an argument\n", argv[0], hyphens, opt->name); + return '?'; + } + val = arg + namelen + 1; + goto found; + } + } + } + if (long_only_flag) { + *long_only_flag = 1; + } else { + ya_getopt_error(optstring, "%s: unrecognized option '%s'\n", argv[0], argv[ya_optind]); + ya_optind++; + } + return '?'; +found: + ya_optarg = val; + ya_optind++; + if (opt->flag) { + *opt->flag = opt->val; + } + if (longindex) { + *longindex = idx; + } + return opt->flag ? 0 : opt->val; +} diff --git a/vendor/ya_getopt/ya_getopt.h b/vendor/ya_getopt/ya_getopt.h new file mode 100644 index 000000000..4244c67d0 --- /dev/null +++ b/vendor/ya_getopt/ya_getopt.h @@ -0,0 +1,77 @@ +/* -*- indent-tabs-mode: nil -*- + * + * ya_getopt - Yet another getopt + * https://github.com/kubo/ya_getopt + * + * Copyright 2015 Kubo Takehiro <kubo@jiubao.org> + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of the authors. + * + */ +#ifndef YA_GETOPT_H +#define YA_GETOPT_H 1 + +#if defined(__cplusplus) +extern "C" { +#endif + +#define ya_no_argument 0 +#define ya_required_argument 1 +#define ya_optional_argument 2 + +struct option { + const char *name; + int has_arg; + int *flag; + int val; +}; + +int ya_getopt(int argc, char * const argv[], const char *optstring); +int ya_getopt_long(int argc, char * const argv[], const char *optstring, + const struct option *longopts, int *longindex); +int ya_getopt_long_only(int argc, char * const argv[], const char *optstring, + const struct option *longopts, int *longindex); + +extern char *ya_optarg; +extern int ya_optind, ya_opterr, ya_optopt; + +#ifndef YA_GETOPT_NO_COMPAT_MACRO +#define getopt ya_getopt +#define getopt_long ya_getopt_long +#define getopt_long_only ya_getopt_long_only +#define optarg ya_optarg +#define optind ya_optind +#define opterr ya_opterr +#define optopt ya_optopt +#define no_argument ya_no_argument +#define required_argument ya_required_argument +#define optional_argument ya_optional_argument +#endif + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/win/CMakeLists.txt b/win/CMakeLists.txt index be6617b8b..2df48883f 100644 --- a/win/CMakeLists.txt +++ b/win/CMakeLists.txt @@ -48,6 +48,13 @@ file(GLOB INSPIRCD_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${INSPIRCD_BASE}/src/threadengines/threadengine_win32.cpp") list(SORT INSPIRCD_SOURCES) +file(GLOB INSPIRCD_VENDORS "${INSPIRCD_BASE}/vendor/**") +foreach(INSPIRCD_VENDOR ${INSPIRCD_VENDORS}) + if(IS_DIRECTORY ${INSPIRCD_VENDOR}) + include_directories(${INSPIRCD_VENDOR}) + endif() +endforeach() + include_directories("${INSPIRCD_BASE}/win" "${INSPIRCD_BASE}/include") include_directories(${EXTRA_INCLUDES}) diff --git a/win/inspircd_win32wrapper.cpp b/win/inspircd_win32wrapper.cpp index 8579103e9..1a7be09fe 100644 --- a/win/inspircd_win32wrapper.cpp +++ b/win/inspircd_win32wrapper.cpp @@ -27,80 +27,7 @@ #include "inspircd.h" #include "configreader.h" #include <string> -#include <errno.h> -#include <assert.h> - -int optind = 1; -char optarg[514]; -int getopt_long(int ___argc, char *const *___argv, const char *__shortopts, const struct option *__longopts, int *__longind) -{ - // burlex todo: handle the shortops, at the moment it only works with longopts. - - if (___argc == 1 || optind == ___argc) // No arguments (apart from filename) - return -1; - - const char * opt = ___argv[optind]; - optind++; - - // if we're not an option, return an error. - if (strnicmp(opt, "--", 2) != 0) - return 1; - else - opt += 2; - - - // parse argument list - int i = 0; - for (; __longopts[i].name != 0; ++i) - { - if (!strnicmp(__longopts[i].name, opt, strlen(__longopts[i].name))) - { - // woot, found a valid argument =) - char * par = 0; - if ((optind) != ___argc) - { - // grab the parameter from the next argument (if its not another argument) - if (strnicmp(___argv[optind], "--", 2) != 0) - { -// optind++; // Trash this next argument, we won't be needing it. - par = ___argv[optind-1]; - } - } - - // increment the argument for next time -// optind++; - - // determine action based on type - if (__longopts[i].has_arg == required_argument && !par) - { - // parameter missing and its a required parameter option - return 1; - } - - // store argument in optarg - if (par) - strncpy(optarg, par, 514); - - if (__longopts[i].flag != 0) - { - // this is a variable, we have to set it if this argument is found. - *__longopts[i].flag = 1; - return 0; - } - else - { - if (__longopts[i].val == -1 || par == 0) - return 1; - - return __longopts[i].val; - } - break; - } - } - - // return 1 (invalid argument) - return 1; -} +#include "ya_getopt.c" CWin32Exception::CWin32Exception() : exception() { diff --git a/win/inspircd_win32wrapper.h b/win/inspircd_win32wrapper.h index 964d3925d..e92339abf 100644 --- a/win/inspircd_win32wrapper.h +++ b/win/inspircd_win32wrapper.h @@ -60,6 +60,9 @@ #define _CRT_SECURE_NO_DEPRECATE #define _WINSOCK_DEPRECATED_NO_WARNINGS +// Windows doesn't support getopt_long so we use ya_getopt instead. +#include "ya_getopt.h" + /* Normal windows (platform-specific) includes */ #include <winsock2.h> #pragma comment(lib, "Ws2_32.lib") @@ -91,21 +94,6 @@ typedef SSIZE_T ssize_t; #define popen _popen #define pclose _pclose -/* getopt() wrapper */ -#define no_argument 0 -#define required_argument 1 -#define optional_argument 2 -struct option -{ - char *name; - int has_arg; - int *flag; - int val; -}; -extern int optind; -extern char optarg[514]; -int getopt_long(int ___argc, char *const *___argv, const char *__shortopts, const struct option *__longopts, int *__longind); - // warning: 'identifier' : class 'type' needs to have dll-interface to be used by clients of class 'type2' // Normally, this is a huge problem, but due to our new/delete remap, we can ignore it. #pragma warning(disable:4251) diff --git a/win/modules/CMakeLists.txt b/win/modules/CMakeLists.txt index 094078aab..2c2617e2b 100644 --- a/win/modules/CMakeLists.txt +++ b/win/modules/CMakeLists.txt @@ -7,13 +7,6 @@ list(SORT INSPIRCD_MODULES) add_definitions("-DDLL_BUILD")
-file(GLOB INSPIRCD_VENDORS "${INSPIRCD_BASE}/vendor/**")
-foreach(INSPIRCD_VENDOR ${INSPIRCD_VENDORS})
- if(NOT IS_DIRECTORY ${INSPIRCD_VENDOR})
- list(REMOVE_ITEM INSPIRCD_VENDORS ${INSPIRCD_VENDOR})
- endif()
-endforeach()
-
foreach(MODULE_NAME ${INSPIRCD_MODULES})
if(IS_DIRECTORY "${MODULE_NAME}")
string(REGEX REPLACE "^.*[/\\](.*)$" "\\1" BASE_NAME ${MODULE_NAME})
@@ -33,7 +26,6 @@ foreach(MODULE_NAME ${INSPIRCD_MODULES}) # Generate the module and set its linker flags, also set it to depend on the main executable to be built beforehand
target_link_libraries(${SO_NAME} inspircd)
add_dependencies(${SO_NAME} inspircd)
- target_include_directories(${SO_NAME} PRIVATE ${INSPIRCD_VENDORS})
if(MSVC)
target_link_libraries(${SO_NAME} win32_memory)
add_dependencies(${SO_NAME} win32_memory)
|