35880a090719e8f3913bbcd63c0238214490826a
[musl] / src / misc / getopt.c
1 #include <unistd.h>
2 #include <wchar.h>
3 #include <string.h>
4 #include <limits.h>
5 #include <stdlib.h>
6 #include "libc.h"
7
8 char *optarg;
9 int optind=1, opterr=1, optopt, __optpos, __optreset=0;
10
11 #define optpos __optpos
12 weak_alias(__optreset, optreset);
13
14 int getopt(int argc, char * const argv[], const char *optstring)
15 {
16         int i;
17         wchar_t c, d;
18         int k, l;
19         char *optchar;
20
21         if (!optind || __optreset) {
22                 __optreset = 0;
23                 __optpos = 0;
24                 optind = 1;
25         }
26
27         if (optind >= argc || !argv[optind] || argv[optind][0] != '-' || !argv[optind][1])
28                 return -1;
29         if (argv[optind][1] == '-' && !argv[optind][2])
30                 return optind++, -1;
31
32         if (!optpos) optpos++;
33         if ((k = mbtowc(&c, argv[optind]+optpos, MB_LEN_MAX)) < 0) {
34                 k = 1;
35                 c = 0xfffd; /* replacement char */
36         }
37         optchar = argv[optind]+optpos;
38         optopt = c;
39         optpos += k;
40
41         if (!argv[optind][optpos]) {
42                 optind++;
43                 optpos = 0;
44         }
45
46         for (i=0; (l = mbtowc(&d, optstring+i, MB_LEN_MAX)) && d!=c; i+=l>0?l:1);
47
48         if (d != c) {
49                 if (optstring[0] != ':' && opterr) {
50                         write(2, argv[0], strlen(argv[0]));
51                         write(2, ": illegal option: ", 18);
52                         write(2, optchar, k);
53                         write(2, "\n", 1);
54                 }
55                 return '?';
56         }
57         if (optstring[i+1] == ':') {
58                 if (optind >= argc) {
59                         if (optstring[0] == ':') return ':';
60                         if (opterr) {
61                                 write(2, argv[0], strlen(argv[0]));
62                                 write(2, ": option requires an argument: ", 31);
63                                 write(2, optchar, k);
64                                 write(2, "\n", 1);
65                         }
66                         return '?';
67                 }
68                 optarg = argv[optind++] + optpos;
69                 optpos = 0;
70         }
71         return c;
72 }