1#include "libc.h" 2#include "locale_impl.h" 3#include <limits.h> 4#include <stdlib.h> 5#include <string.h> 6#include <unistd.h> 7#include <wchar.h> 8 9char* optarg; 10int optind = 1, opterr = 1, optopt, __optpos, __optreset = 0; 11 12#define optpos __optpos 13weak_alias(__optreset, optreset); 14 15void __getopt_msg(const char* a, const char* b, const char* c, size_t l) { 16 FILE* f = stderr; 17 b = __lctrans_cur(b); 18 flockfile(f); 19 (void)(fputs(a, f) >= 0 && fwrite(b, strlen(b), 1, f) && fwrite(c, 1, l, f) == l && putc('\n', f)); 20 funlockfile(f); 21} 22 23int getopt(int argc, char* const argv[], const char* optstring) { 24 int i; 25 wchar_t c, d; 26 int k, l; 27 char* optchar; 28 29 if (!optind || __optreset) { 30 __optreset = 0; 31 __optpos = 0; 32 optind = 1; 33 } 34 35 if (optind >= argc || !argv[optind]) 36 return -1; 37 38 if (argv[optind][0] != '-') { 39 if (optstring[0] == '-') { 40 optarg = argv[optind++]; 41 return 1; 42 } 43 return -1; 44 } 45 46 if (!argv[optind][1]) 47 return -1; 48 49 if (argv[optind][1] == '-' && !argv[optind][2]) 50 return optind++, -1; 51 52 if (!optpos) 53 optpos++; 54 if ((k = mbtowc(&c, argv[optind] + optpos, MB_LEN_MAX)) < 0) { 55 k = 1; 56 c = 0xfffd; /* replacement char */ 57 } 58 optchar = argv[optind] + optpos; 59 optopt = c; 60 optpos += k; 61 62 if (!argv[optind][optpos]) { 63 optind++; 64 optpos = 0; 65 } 66 67 if (optstring[0] == '-' || optstring[0] == '+') 68 optstring++; 69 70 i = 0; 71 d = 0; 72 do { 73 l = mbtowc(&d, optstring + i, MB_LEN_MAX); 74 if (l > 0) 75 i += l; 76 else 77 i++; 78 } while (l && d != c); 79 80 if (d != c) { 81 if (optstring[0] != ':' && opterr) 82 __getopt_msg(argv[0], ": unrecognized option: ", optchar, k); 83 return '?'; 84 } 85 if (optstring[i] == ':') { 86 if (optstring[i + 1] == ':') 87 optarg = 0; 88 else if (optind >= argc) { 89 if (optstring[0] == ':') 90 return ':'; 91 if (opterr) 92 __getopt_msg(argv[0], ": option requires an argument: ", optchar, k); 93 return '?'; 94 } 95 if (optstring[i + 1] != ':' || optpos) { 96 optarg = argv[optind++] + optpos; 97 optpos = 0; 98 } 99 } 100 return c; 101} 102 103weak_alias(getopt, __posix_getopt); 104