diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2020-04-02 23:03:30 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2020-04-02 23:08:00 +0200 |
commit | d68a600d005d9c110145310dc249daaf73653436 (patch) | |
tree | 2c3cc0dc394ac50430d11f45a074845c52b53f3d | |
parent | d76eb9dd46081279642d3353f51ebc09fe4bbe9f (diff) |
Add a libcompat implementation for getopt_long
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | include/compat.h | 14 | ||||
-rw-r--r-- | lib/compat/Makemodule.am | 1 | ||||
-rw-r--r-- | lib/compat/getopt_long.c | 72 | ||||
-rw-r--r-- | lib/compat/libcompat.vcxproj | 1 | ||||
-rw-r--r-- | lib/compat/libcompat.vcxproj.filters | 3 |
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> |