aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2020-04-02 20:03:32 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2020-04-02 23:01:48 +0200
commitd76eb9dd46081279642d3353f51ebc09fe4bbe9f (patch)
tree1841a5e9016b760a6e0c6592dc85b0e4879d11c0
parenta772248e1a2f0886d8479b2f14392f020ea8c6e0 (diff)
Add a libcompat implementation of getopt
Limited to the subset actually needed. Vaguely inspired by the NetBSD libc implementation. Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r--configure.ac2
-rw-r--r--include/compat.h7
-rw-r--r--lib/compat/Makemodule.am2
-rw-r--r--lib/compat/getopt.c70
-rw-r--r--lib/compat/libcompat.vcxproj1
-rw-r--r--lib/compat/libcompat.vcxproj.filters3
6 files changed, 83 insertions, 2 deletions
diff --git a/configure.ac b/configure.ac
index 9da88e0..0162334 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 getsubopt])
+AC_CHECK_FUNCS([strndup getline getopt getsubopt])
##### generate output #####
diff --git a/include/compat.h b/include/compat.h
index 5d7a052..6f8a77d 100644
--- a/include/compat.h
+++ b/include/compat.h
@@ -197,6 +197,13 @@ char *strndup(const char *str, size_t max_len);
int getsubopt(char **opt, char *const *keys, char **val);
#endif
+#ifndef HAVE_GETOPT
+extern int optind;
+extern char *optarg;
+
+int getopt(int argc, char *const argv[], const char *optstr);
+#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 a54059e..f1bb2de 100644
--- a/lib/compat/Makemodule.am
+++ b/lib/compat/Makemodule.am
@@ -1,7 +1,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
+libcompat_a_SOURCES += lib/compat/path_to_windows.c lib/compat/getopt.c
noinst_LIBRARIES += libcompat.a
diff --git a/lib/compat/getopt.c b/lib/compat/getopt.c
new file mode 100644
index 0000000..23ede4c
--- /dev/null
+++ b/lib/compat/getopt.c
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+/*
+ * getopt.c
+ *
+ * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
+ */
+#include "config.h"
+#include "compat.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#ifndef HAVE_GETOPT
+static char *current = "";
+int optind = 1;
+char *optarg = NULL;
+
+int getopt(int argc, char *const argv[], const char *optstr)
+{
+ char optchr, *ptr;
+
+ if (*current == '\0') {
+ if (optind >= argc || argv[optind][0] != '-')
+ return -1;
+
+ if (argv[optind][1] == '-' && argv[optind][2] == '\0') {
+ ++optind;
+ return -1;
+ }
+
+ if (argv[optind][1] == '\0')
+ return -1;
+
+ current = argv[optind] + 1;
+ }
+
+ optchr = *(current++);
+ if (optchr == ':' || (ptr = strchr(optstr, optchr)) == NULL)
+ goto fail_unknown;
+
+ if (ptr[1] == ':') {
+ if (*current != '\0') {
+ optarg = current;
+ } else {
+ if (++optind >= argc)
+ goto fail_arg;
+
+ optarg = argv[optind];
+ }
+
+ current = "";
+ ++optind;
+ } else {
+ optarg = NULL;
+
+ if (*current == '\0')
+ ++optind;
+ }
+
+ return optchr;
+fail_unknown:
+ fprintf(stderr, "%s: unknown option `-%c`\n", argv[0], optchr);
+ return '?';
+fail_arg:
+ fprintf(stderr, "%s: missing argument for option `-%c`\n",
+ argv[0], optchr);
+ return '?';
+}
+#endif
diff --git a/lib/compat/libcompat.vcxproj b/lib/compat/libcompat.vcxproj
index b77a39c..307754e 100644
--- a/lib/compat/libcompat.vcxproj
+++ b/lib/compat/libcompat.vcxproj
@@ -156,6 +156,7 @@
<ItemGroup>
<ClCompile Include="chdir.c" />
<ClCompile Include="getline.c" />
+ <ClCompile Include="getopt.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 aa169a5..f2851d1 100644
--- a/lib/compat/libcompat.vcxproj.filters
+++ b/lib/compat/libcompat.vcxproj.filters
@@ -14,6 +14,9 @@
<ClCompile Include="getline.c">
<Filter>Source</Filter>
</ClCompile>
+ <ClCompile Include="getopt.c">
+ <Filter>Source</Filter>
+ </ClCompile>
<ClCompile Include="getsubopt.c">
<Filter>Source</Filter>
</ClCompile>