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 
9 char* optarg;
10 int optind = 1, opterr = 1, optopt, __optpos, __optreset = 0;
11 
12 #define optpos __optpos
13 weak_alias(__optreset, optreset);
14 
__getopt_msg(const char * a,const char * b,const char * c,size_t l)15 void __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 
getopt(int argc,char * const argv[],const char * optstring)23 int 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 
103 weak_alias(getopt, __posix_getopt);
104