aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2020-04-02 23:03:30 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2020-04-02 23:08:00 +0200
commitd68a600d005d9c110145310dc249daaf73653436 (patch)
tree2c3cc0dc394ac50430d11f45a074845c52b53f3d
parentd76eb9dd46081279642d3353f51ebc09fe4bbe9f (diff)
Add a libcompat implementation for getopt_long
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r--configure.ac2
-rw-r--r--include/compat.h14
-rw-r--r--lib/compat/Makemodule.am1
-rw-r--r--lib/compat/getopt_long.c72
-rw-r--r--lib/compat/libcompat.vcxproj1
-rw-r--r--lib/compat/libcompat.vcxproj.filters3
6 files changed, 92 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac
index 0162334..79d48c0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -236,7 +236,7 @@ AX_COMPILE_CHECK_SIZEOF(long long)
AC_CHECK_HEADERS([sys/xattr.h], [], [])
AC_CHECK_HEADERS([sys/sysinfo.h], [], [])
-AC_CHECK_FUNCS([strndup getline getopt getsubopt])
+AC_CHECK_FUNCS([strndup getline getopt getsubopt getopt_long])
##### generate output #####
diff --git a/include/compat.h b/include/compat.h
index 6f8a77d..cb5ff23 100644
--- a/include/compat.h
+++ b/include/compat.h
@@ -204,6 +204,20 @@ extern char *optarg;
int getopt(int argc, char *const argv[], const char *optstr);
#endif
+#ifndef HAVE_GETOPT_LONG
+struct option {
+ const char *name;
+ int has_arg;
+ int val;
+};
+
+#define no_argument 0
+#define required_argument 1
+
+int getopt_long(int argc, char *const argv[], const char *optstr,
+ const struct option *longopts, int *longindex);
+#endif
+
#if defined(_WIN32) || defined(__WINDOWS__)
WCHAR *path_to_windows(const char *input);
#endif
diff --git a/lib/compat/Makemodule.am b/lib/compat/Makemodule.am
index f1bb2de..b7649ef 100644
--- a/lib/compat/Makemodule.am
+++ b/lib/compat/Makemodule.am
@@ -2,6 +2,7 @@ libcompat_a_SOURCES = lib/compat/getline.c lib/compat/getsubopt.c
libcompat_a_SOURCES += lib/compat/strndup.c lib/compat/mockups.c
libcompat_a_SOURCES += lib/compat/chdir.c include/compat.h
libcompat_a_SOURCES += lib/compat/path_to_windows.c lib/compat/getopt.c
+libcompat_a_SOURCES += lib/compat/getopt_long.c
noinst_LIBRARIES += libcompat.a
diff --git a/lib/compat/getopt_long.c b/lib/compat/getopt_long.c
new file mode 100644
index 0000000..24f5864
--- /dev/null
+++ b/lib/compat/getopt_long.c
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+/*
+ * getopt_long.c
+ *
+ * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
+ */
+#include "config.h"
+#include "compat.h"
+
+#ifdef HAVE_GETOPT
+#include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#ifndef HAVE_GETOPT_LONG
+int getopt_long(int argc, char *const argv[], const char *optstr,
+ const struct option *longopts, int *longindex)
+{
+ size_t i, len;
+ char *ptr;
+ (void)longindex;
+
+ if (optind >= argc || argv[optind][0] != '-' ||
+ argv[optind][1] != '-' || argv[optind][2] == '\0')
+ return getopt(argc, argv, optstr);
+
+ optarg = NULL;
+ ptr = argv[optind] + 2;
+
+ for (len = 0; ptr[len] != '\0' && ptr[len] != '='; ++len)
+ ;
+
+ for (i = 0; longopts[i].name != NULL; ++i) {
+ if (strncmp(longopts[i].name, ptr, len) != 0)
+ continue;
+
+ if (longopts[i].name[len] == '\0')
+ break;
+ }
+
+ if (longopts[i].name == NULL)
+ goto fail_unknown;
+
+ if (ptr[len] == '=') {
+ if (!longopts[i].has_arg)
+ goto fail_arg;
+
+ optarg = ptr + len + 1;
+ } else if (longopts[i].has_arg) {
+ if (++optind >= argc)
+ goto fail_no_arg;
+
+ optarg = argv[optind];
+ }
+
+ ++optind;
+ return longopts[i].val;
+fail_unknown:
+ fprintf(stderr, "%s: unknown option `--%s`\n", argv[0], ptr);
+ return '?';
+fail_arg:
+ fprintf(stderr, "%s: no argument expected for option `--%s`\n",
+ argv[0], ptr);
+ return '?';
+fail_no_arg:
+ fprintf(stderr, "%s: missing argument for option `--%s`\n",
+ argv[0], ptr);
+ return '?';
+}
+#endif
diff --git a/lib/compat/libcompat.vcxproj b/lib/compat/libcompat.vcxproj
index 307754e..0dada12 100644
--- a/lib/compat/libcompat.vcxproj
+++ b/lib/compat/libcompat.vcxproj
@@ -157,6 +157,7 @@
<ClCompile Include="chdir.c" />
<ClCompile Include="getline.c" />
<ClCompile Include="getopt.c" />
+ <ClCompile Include="getopt_long.c" />
<ClCompile Include="getsubopt.c" />
<ClCompile Include="mockups.c" />
<ClCompile Include="path_to_windows.c" />
diff --git a/lib/compat/libcompat.vcxproj.filters b/lib/compat/libcompat.vcxproj.filters
index f2851d1..2eb9cfb 100644
--- a/lib/compat/libcompat.vcxproj.filters
+++ b/lib/compat/libcompat.vcxproj.filters
@@ -17,6 +17,9 @@
<ClCompile Include="getopt.c">
<Filter>Source</Filter>
</ClCompile>
+ <ClCompile Include="getopt_long.c">
+ <Filter>Source</Filter>
+ </ClCompile>
<ClCompile Include="getsubopt.c">
<Filter>Source</Filter>
</ClCompile>