aboutsummaryrefslogtreecommitdiff
path: root/lib/compat/getopt_long.c
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2021-03-24 16:21:24 +0100
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2021-03-24 23:35:30 +0100
commitcad65de2a9a9b7d29b98f0d2997772c057f92e29 (patch)
treef3ad209f389acb6499cd3b352e061fe730daa760 /lib/compat/getopt_long.c
parent87713e563f0005553f8d075d3839d3960d7f17cb (diff)
Provide Musl derived fallbacks for getopt/getopt_long/getsubopt
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib/compat/getopt_long.c')
-rw-r--r--lib/compat/getopt_long.c95
1 files changed, 95 insertions, 0 deletions
diff --git a/lib/compat/getopt_long.c b/lib/compat/getopt_long.c
new file mode 100644
index 0000000..58354c3
--- /dev/null
+++ b/lib/compat/getopt_long.c
@@ -0,0 +1,95 @@
+#include "compat.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifndef HAVE_GETOPT_LONG
+static void permute(char *const *argv, int dest, int src)
+{
+ char **av = (char **)argv;
+ char *tmp = av[src];
+ int i;
+ for (i=src; i>dest; i--)
+ av[i] = av[i-1];
+ av[dest] = tmp;
+}
+
+int getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx)
+{
+ optarg = 0;
+ if (longopts && argv[optind][0] == '-' &&
+ (argv[optind][1] == '-' && argv[optind][2]))
+ {
+ int colon = optstring[optstring[0]=='+'||optstring[0]=='-']==':';
+ int i, cnt, match;
+ char *arg, *opt, *start = argv[optind]+1;
+ for (cnt=i=0; longopts[i].name; i++) {
+ const char *name = longopts[i].name;
+ opt = start;
+ if (*opt == '-') opt++;
+ while (*opt && *opt != '=' && *opt == *name)
+ name++, opt++;
+ if (*opt && *opt != '=') continue;
+ arg = opt;
+ match = i;
+ if (!*name) {
+ cnt = 1;
+ break;
+ }
+ cnt++;
+ }
+ if (cnt==1) {
+ i = match;
+ opt = arg;
+ optind++;
+ if (*opt == '=') {
+ if (!longopts[i].has_arg) {
+ optopt = longopts[i].val;
+ if (colon || !opterr)
+ return '?';
+ __getopt_msg(argv[0],
+ ": option does not take an argument: ",
+ longopts[i].name,
+ strlen(longopts[i].name));
+ return '?';
+ }
+ optarg = opt+1;
+ } else if (longopts[i].has_arg == required_argument) {
+ if (!(optarg = argv[optind])) {
+ optopt = longopts[i].val;
+ if (colon) return ':';
+ if (!opterr) return '?';
+ __getopt_msg(argv[0],
+ ": option requires an argument: ",
+ longopts[i].name,
+ strlen(longopts[i].name));
+ return '?';
+ }
+ optind++;
+ }
+ if (idx) *idx = i;
+ if (longopts[i].flag) {
+ *longopts[i].flag = longopts[i].val;
+ return 0;
+ }
+ return longopts[i].val;
+ }
+ if (argv[optind][1] == '-') {
+ optopt = 0;
+ if (!colon && opterr)
+ __getopt_msg(argv[0], cnt ?
+ ": option is ambiguous: " :
+ ": unrecognized option: ",
+ argv[optind]+2,
+ strlen(argv[optind]+2));
+ optind++;
+ return '?';
+ }
+ }
+ return getopt(argc, argv, optstring);
+}
+#endif