From d68a600d005d9c110145310dc249daaf73653436 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Thu, 2 Apr 2020 23:03:30 +0200 Subject: Add a libcompat implementation for getopt_long Signed-off-by: David Oberhollenzer --- configure.ac | 2 +- include/compat.h | 14 +++++++ lib/compat/Makemodule.am | 1 + lib/compat/getopt_long.c | 72 ++++++++++++++++++++++++++++++++++++ lib/compat/libcompat.vcxproj | 1 + lib/compat/libcompat.vcxproj.filters | 3 ++ 6 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 lib/compat/getopt_long.c 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 + */ +#include "config.h" +#include "compat.h" + +#ifdef HAVE_GETOPT +#include +#endif + +#include +#include + +#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 @@ + 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 @@ Source + + Source + Source -- cgit v1.2.3