| #include <unistd.h> |
| #include <wchar.h> |
| #include <string.h> |
| #include <limits.h> |
| #include <stdlib.h> |
| #include "libc.h" |
| #include "locale_impl.h" |
| |
| char *optarg; |
| int optind=1, opterr=1, optopt, __optpos, __optreset=0; |
| |
| #define optpos __optpos |
| weak_alias(__optreset, optreset); |
| |
| void __getopt_msg(const char *a, const char *b, const char *c, size_t l) |
| { |
| FILE *f = stderr; |
| b = __lctrans_cur(b); |
| flockfile(f); |
| fwrite(a, strlen(a), 1, f) |
| && fwrite(b, strlen(b), 1, f) |
| && fwrite(c, l, 1, f) |
| && putc('\n', f); |
| funlockfile(f); |
| } |
| |
| 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; |
| optopt = c; |
| 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) { |
| if (optstring[0] != ':' && opterr) |
| __getopt_msg(argv[0], ": unrecognized option: ", optchar, k); |
| return '?'; |
| } |
| if (optstring[i] == ':') { |
| if (optstring[i+1] == ':') optarg = 0; |
| else if (optind >= argc) { |
| if (optstring[0] == ':') return ':'; |
| if (opterr) __getopt_msg(argv[0], |
| ": option requires an argument: ", |
| optchar, k); |
| return '?'; |
| } |
| if (optstring[i+1] != ':' || optpos) { |
| optarg = argv[optind++] + optpos; |
| optpos = 0; |
| } |
| } |
| return c; |
| } |
| |
| weak_alias(getopt, __posix_getopt); |