summaryrefslogtreecommitdiff
path: root/lib/compat/getopt.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.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.c')
-rw-r--r--lib/compat/getopt.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/lib/compat/getopt.c b/lib/compat/getopt.c
new file mode 100644
index 0000000..9876a87
--- /dev/null
+++ b/lib/compat/getopt.c
@@ -0,0 +1,96 @@
+#include "compat.h"
+
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#ifndef HAVE_GETOPT
+char *optarg;
+int optind=1, opterr=1, optopt, optpos, optreset=0;
+
+void __getopt_msg(const char *a, const char *b, const char *c, size_t l)
+{
+ fputs(a, stderr);
+ fwrite(b, strlen(b), 1, stderr);
+ fwrite(c, 1, l, stderr);
+ putc('\n', stderr);
+}
+
+int getopt(int argc, char * const argv[], const char *optstring)
+{
+ int i;
+ wchar_t c, d;
+ int k, l;
+ char *optchar;
+
+ if (!optind || __optreset) {
+ optreset = 0;
+ optpos = 0;
+ optind = 1;
+ }
+
+ if (optind >= argc || !argv[optind])
+ return -1;
+
+ if (argv[optind][0] != '-') {
+ if (optstring[0] == '-') {
+ optarg = argv[optind++];
+ return 1;
+ }
+ return -1;
+ }
+
+ if (!argv[optind][1])
+ return -1;
+
+ if (argv[optind][1] == '-' && !argv[optind][2])
+ return optind++, -1;
+
+ if (!optpos) optpos++;
+ if ((k = mbtowc(&c, argv[optind]+optpos, MB_LEN_MAX)) < 0) {
+ k = 1;
+ c = 0xfffd; /* replacement char */
+ }
+ optchar = argv[optind]+optpos;
+ optpos += k;
+
+ if (!argv[optind][optpos]) {
+ optind++;
+ optpos = 0;
+ }
+
+ if (optstring[0] == '-' || optstring[0] == '+')
+ optstring++;
+
+ i = 0;
+ d = 0;
+ do {
+ l = mbtowc(&d, optstring+i, MB_LEN_MAX);
+ if (l>0) i+=l; else i++;
+ } while (l && d != c);
+
+ if (d != c || c == ':') {
+ optopt = c;
+ if (optstring[0] != ':' && opterr)
+ __getopt_msg(argv[0], ": unrecognized option: ", optchar, k);
+ return '?';
+ }
+ if (optstring[i] == ':') {
+ optarg = 0;
+ if (optstring[i+1] != ':' || optpos) {
+ optarg = argv[optind++] + optpos;
+ optpos = 0;
+ }
+ if (optind > argc) {
+ optopt = c;
+ if (optstring[0] == ':') return ':';
+ if (opterr) __getopt_msg(argv[0],
+ ": option requires an argument: ",
+ optchar, k);
+ return '?';
+ }
+ }
+ return c;
+}
+#endif