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#include "locale_impl.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{
17	FILE *f = stderr;
18	b = __lctrans_cur(b);
19	flockfile(f);
20	fputs(a, f)>=0
21	&& fwrite(b, strlen(b), 1, f)
22	&& fwrite(c, 1, l, f)==l
23	&& putc('\n', f);
24	funlockfile(f);
25}
26
27int getopt(int argc, char * const argv[], const char *optstring)
28{
29	int i;
30	wchar_t c, d;
31	int k, l;
32	char *optchar;
33
34	if (!optind || __optreset) {
35		__optreset = 0;
36		__optpos = 0;
37		optind = 1;
38	}
39
40	if (optind >= argc || !argv[optind])
41		return -1;
42
43	if (argv[optind][0] != '-') {
44		if (optstring[0] == '-') {
45			optarg = argv[optind++];
46			return 1;
47		}
48		return -1;
49	}
50
51	if (!argv[optind][1])
52		return -1;
53
54	if (argv[optind][1] == '-' && !argv[optind][2])
55		return optind++, -1;
56
57	if (!optpos) optpos++;
58	if ((k = mbtowc(&c, argv[optind]+optpos, MB_LEN_MAX)) < 0) {
59		k = 1;
60		c = 0xfffd; /* replacement char */
61	}
62	optchar = argv[optind]+optpos;
63	optopt = c;
64	optpos += k;
65
66	if (!argv[optind][optpos]) {
67		optind++;
68		optpos = 0;
69	}
70
71	if (optstring[0] == '-' || optstring[0] == '+')
72		optstring++;
73
74	i = 0;
75	d = 0;
76	do {
77		l = mbtowc(&d, optstring+i, MB_LEN_MAX);
78		if (l>0) i+=l; else i++;
79	} while (l && d != c);
80
81	if (d != c) {
82		if (optstring[0] != ':' && opterr)
83			__getopt_msg(argv[0], ": unrecognized option: ", optchar, k);
84		return '?';
85	}
86	if (optstring[i] == ':') {
87		if (optstring[i+1] == ':') optarg = 0;
88		else if (optind >= argc) {
89			if (optstring[0] == ':') return ':';
90			if (opterr) __getopt_msg(argv[0],
91				": option requires an argument: ",
92				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