1570af302Sopenharmony_ci#define _BSD_SOURCE
2570af302Sopenharmony_ci#include <unistd.h>
3570af302Sopenharmony_ci#include <wchar.h>
4570af302Sopenharmony_ci#include <string.h>
5570af302Sopenharmony_ci#include <limits.h>
6570af302Sopenharmony_ci#include <stdlib.h>
7570af302Sopenharmony_ci#include "locale_impl.h"
8570af302Sopenharmony_ci#include "stdio_impl.h"
9570af302Sopenharmony_ci
10570af302Sopenharmony_cichar *optarg;
11570af302Sopenharmony_ciint optind=1, opterr=1, optopt, __optpos, __optreset=0;
12570af302Sopenharmony_ci
13570af302Sopenharmony_ci#define optpos __optpos
14570af302Sopenharmony_ciweak_alias(__optreset, optreset);
15570af302Sopenharmony_ci
16570af302Sopenharmony_civoid __getopt_msg(const char *a, const char *b, const char *c, size_t l)
17570af302Sopenharmony_ci{
18570af302Sopenharmony_ci	FILE *f = stderr;
19570af302Sopenharmony_ci	b = __lctrans_cur(b);
20570af302Sopenharmony_ci	FLOCK(f);
21570af302Sopenharmony_ci	fputs(a, f)>=0
22570af302Sopenharmony_ci	&& fwrite(b, strlen(b), 1, f)
23570af302Sopenharmony_ci	&& fwrite(c, 1, l, f)==l
24570af302Sopenharmony_ci	&& putc('\n', f);
25570af302Sopenharmony_ci	FUNLOCK(f);
26570af302Sopenharmony_ci}
27570af302Sopenharmony_ci
28570af302Sopenharmony_ciint getopt(int argc, char * const argv[], const char *optstring)
29570af302Sopenharmony_ci{
30570af302Sopenharmony_ci	int i;
31570af302Sopenharmony_ci	wchar_t c, d;
32570af302Sopenharmony_ci	int k, l;
33570af302Sopenharmony_ci	char *optchar;
34570af302Sopenharmony_ci
35570af302Sopenharmony_ci	if (!optind || __optreset) {
36570af302Sopenharmony_ci		__optreset = 0;
37570af302Sopenharmony_ci		__optpos = 0;
38570af302Sopenharmony_ci		optind = 1;
39570af302Sopenharmony_ci	}
40570af302Sopenharmony_ci
41570af302Sopenharmony_ci	if (optind >= argc || !argv[optind])
42570af302Sopenharmony_ci		return -1;
43570af302Sopenharmony_ci
44570af302Sopenharmony_ci	if (argv[optind][0] != '-') {
45570af302Sopenharmony_ci		if (optstring[0] == '-') {
46570af302Sopenharmony_ci			optarg = argv[optind++];
47570af302Sopenharmony_ci			return 1;
48570af302Sopenharmony_ci		}
49570af302Sopenharmony_ci		return -1;
50570af302Sopenharmony_ci	}
51570af302Sopenharmony_ci
52570af302Sopenharmony_ci	if (!argv[optind][1])
53570af302Sopenharmony_ci		return -1;
54570af302Sopenharmony_ci
55570af302Sopenharmony_ci	if (argv[optind][1] == '-' && !argv[optind][2])
56570af302Sopenharmony_ci		return optind++, -1;
57570af302Sopenharmony_ci
58570af302Sopenharmony_ci	if (!optpos) optpos++;
59570af302Sopenharmony_ci	if ((k = mbtowc(&c, argv[optind]+optpos, MB_LEN_MAX)) < 0) {
60570af302Sopenharmony_ci		k = 1;
61570af302Sopenharmony_ci		c = 0xfffd; /* replacement char */
62570af302Sopenharmony_ci	}
63570af302Sopenharmony_ci	optchar = argv[optind]+optpos;
64570af302Sopenharmony_ci	optpos += k;
65570af302Sopenharmony_ci
66570af302Sopenharmony_ci	if (!argv[optind][optpos]) {
67570af302Sopenharmony_ci		optind++;
68570af302Sopenharmony_ci		optpos = 0;
69570af302Sopenharmony_ci	}
70570af302Sopenharmony_ci
71570af302Sopenharmony_ci	if (optstring[0] == '-' || optstring[0] == '+')
72570af302Sopenharmony_ci		optstring++;
73570af302Sopenharmony_ci
74570af302Sopenharmony_ci	i = 0;
75570af302Sopenharmony_ci	d = 0;
76570af302Sopenharmony_ci	do {
77570af302Sopenharmony_ci		l = mbtowc(&d, optstring+i, MB_LEN_MAX);
78570af302Sopenharmony_ci		if (l>0) i+=l; else i++;
79570af302Sopenharmony_ci	} while (l && d != c);
80570af302Sopenharmony_ci
81570af302Sopenharmony_ci	if (d != c || c == ':') {
82570af302Sopenharmony_ci		optopt = c;
83570af302Sopenharmony_ci		if (optstring[0] != ':' && opterr)
84570af302Sopenharmony_ci			__getopt_msg(argv[0], ": unrecognized option: ", optchar, k);
85570af302Sopenharmony_ci		return '?';
86570af302Sopenharmony_ci	}
87570af302Sopenharmony_ci	if (optstring[i] == ':') {
88570af302Sopenharmony_ci		optarg = 0;
89570af302Sopenharmony_ci		if (optstring[i+1] != ':' || optpos) {
90570af302Sopenharmony_ci			optarg = argv[optind++];
91570af302Sopenharmony_ci			if (optpos) optarg += optpos;
92570af302Sopenharmony_ci			optpos = 0;
93570af302Sopenharmony_ci		}
94570af302Sopenharmony_ci		if (optind > argc) {
95570af302Sopenharmony_ci			optopt = c;
96570af302Sopenharmony_ci			if (optstring[0] == ':') return ':';
97570af302Sopenharmony_ci			if (opterr) __getopt_msg(argv[0],
98570af302Sopenharmony_ci				": option requires an argument: ",
99570af302Sopenharmony_ci				optchar, k);
100570af302Sopenharmony_ci			return '?';
101570af302Sopenharmony_ci		}
102570af302Sopenharmony_ci	}
103570af302Sopenharmony_ci	return c;
104570af302Sopenharmony_ci}
105570af302Sopenharmony_ci
106570af302Sopenharmony_ciweak_alias(getopt, __posix_getopt);
107