summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Powell <petpow@saberuk.com>2019-12-08 19:39:02 +0000
committerPeter Powell <petpow@saberuk.com>2019-12-08 19:59:34 +0000
commita47e2df0ce833e06fa3e4034e64ec084a2bbb2d3 (patch)
tree51b20e031c52f135d927bc23643cbd831a0fddd4
parent914d8140d98dd0adc54f739dfe550765cc466bac (diff)
Replace our Windows getopt_long wrapper with ya_getopt.
Closes #546.
-rw-r--r--vendor/README.md10
-rw-r--r--vendor/ya_getopt/ya_getopt.c318
-rw-r--r--vendor/ya_getopt/ya_getopt.h77
-rw-r--r--win/CMakeLists.txt7
-rw-r--r--win/inspircd_win32wrapper.cpp75
-rw-r--r--win/inspircd_win32wrapper.h18
-rw-r--r--win/modules/CMakeLists.txt8
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** &mdash; Boost Software License
**Website** &mdash; [https://github.com/nemtrif/utfcpp](https://github.com/nemtrif/utfcpp)
+
+## ya_getopt
+
+**Author** &mdash; Kubo Takehiro
+
+**Last Updated** &mdash; 2019-12-08 (6ce431085b81d9bb8639ed2f858c4f4fbc3ab988)
+
+**License** &mdash; 2-clause BSD License
+
+**Website** &mdash; [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)