Index: fusl/src/misc/getopt_long.c |
diff --git a/fusl/src/misc/getopt_long.c b/fusl/src/misc/getopt_long.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..480c00139e08682fd15d5798d871be4c85111b76 |
--- /dev/null |
+++ b/fusl/src/misc/getopt_long.c |
@@ -0,0 +1,131 @@ |
+#define _GNU_SOURCE |
+#include <stddef.h> |
+#include <getopt.h> |
+#include <stdio.h> |
+#include <string.h> |
+ |
+extern int __optpos, __optreset; |
+ |
+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; |
+} |
+ |
+void __getopt_msg(const char *, const char *, const char *, size_t); |
+ |
+static int __getopt_long_core(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly); |
+ |
+static int __getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly) |
+{ |
+ int ret, skipped, resumed; |
+ if (!optind || __optreset) { |
+ __optreset = 0; |
+ __optpos = 0; |
+ optind = 1; |
+ } |
+ if (optind >= argc || !argv[optind]) return -1; |
+ skipped = optind; |
+ if (optstring[0] != '+' && optstring[0] != '-') { |
+ int i; |
+ for (i=optind; ; i++) { |
+ if (i >= argc || !argv[i]) return -1; |
+ if (argv[i][0] == '-' && argv[i][1]) break; |
+ } |
+ optind = i; |
+ } |
+ resumed = optind; |
+ ret = __getopt_long_core(argc, argv, optstring, longopts, idx, longonly); |
+ if (resumed > skipped) { |
+ int i, cnt = optind-resumed; |
+ for (i=0; i<cnt; i++) |
+ permute(argv, skipped, optind-1); |
+ optind = skipped + cnt; |
+ } |
+ return ret; |
+} |
+ |
+static int __getopt_long_core(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly) |
+{ |
+ optarg = 0; |
+ if (longopts && argv[optind][0] == '-' && |
+ ((longonly && argv[optind][1]) || |
+ (argv[optind][1] == '-' && argv[optind][2]))) |
+ { |
+ int colon = optstring[optstring[0]=='+'||optstring[0]=='-']==':'; |
+ int i, cnt, match; |
+ char *opt; |
+ for (cnt=i=0; longopts[i].name; i++) { |
+ const char *name = longopts[i].name; |
+ opt = argv[optind]+1; |
+ if (*opt == '-') opt++; |
+ for (; *name && *name == *opt; name++, opt++); |
+ if (*opt && *opt != '=') continue; |
+ match = i; |
+ if (!*name) { |
+ cnt = 1; |
+ break; |
+ } |
+ cnt++; |
+ } |
+ if (cnt==1) { |
+ i = match; |
+ optind++; |
+ optopt = longopts[i].val; |
+ if (*opt == '=') { |
+ if (!longopts[i].has_arg) { |
+ 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])) { |
+ 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] == '-') { |
+ 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); |
+} |
+ |
+int getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx) |
+{ |
+ return __getopt_long(argc, argv, optstring, longopts, idx, 0); |
+} |
+ |
+int getopt_long_only(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx) |
+{ |
+ return __getopt_long(argc, argv, optstring, longopts, idx, 1); |
+} |