1#[repr(C)]
7#[derive(Copy, Clone)]
8pub struct LongOption {
9 pub name: *const c_char,
10 pub has_arg: c_int,
11 pub flag: *mut c_int,
12 pub val: c_int,
13}
14
15#[no_mangle]
16pub static mut __optpos: c_int = 0;
17#[no_mangle]
18pub static mut __optreset: c_int = 0;
19
20unsafe fn getopt_reset_if_needed() {
21 if optind == 0 || __optreset != 0 || optreset != 0 {
22 __optreset = 0;
23 optreset = 0;
24 __optpos = 0;
25 optind = 1;
26 }
27}
28
29unsafe fn opt_char_len(s: *const c_char) -> usize {
30 let b = *s as u8;
33 if b < 0x80 { 1 }
34 else if b >= 0xf0 { 4 }
35 else if b >= 0xe0 { 3 }
36 else if b >= 0xc0 { 2 }
37 else { 1 }
38}
39
40#[no_mangle]
41pub unsafe extern "C" fn getopt(
42 argc: c_int,
43 argv: *const *const c_char,
44 optstring_in: *const c_char,
45) -> c_int {
46 getopt_reset_if_needed();
47 if argc <= 0 || argv.is_null() || optstring_in.is_null() { return -1; }
48 if optind >= argc { return -1; }
49 let av = argv.add(optind as usize);
50 if (*av).is_null() { return -1; }
51 let arg = *av;
52 if *arg != b'-' as c_char {
53 if *optstring_in == b'-' as c_char {
54 optarg = arg as *mut c_char;
55 optind += 1;
56 return 1;
57 }
58 return -1;
59 }
60 if *arg.add(1) == 0 { return -1; }
61 if *arg.add(1) == b'-' as c_char && *arg.add(2) == 0 {
62 optind += 1;
63 return -1;
64 }
65 if __optpos == 0 { __optpos = 1; }
66 let clen = opt_char_len(arg.add(__optpos as usize));
67 let c = *arg.add(__optpos as usize) as u8;
68 let optchar = arg.add(__optpos as usize);
69 __optpos += clen as c_int;
70 if *arg.add(__optpos as usize) == 0 {
71 optind += 1;
72 __optpos = 0;
73 }
74
75 let mut spec = optstring_in;
76 if *spec == b'-' as c_char || *spec == b'+' as c_char { spec = spec.add(1); }
77
78 let mut i = 0usize;
79 let mut found = false;
80 while *spec.add(i) != 0 {
81 if *spec.add(i) as u8 == c { found = true; break; }
82 i += 1;
83 }
84 if !found || c == b':' {
85 optopt = c as c_int;
86 if *spec != b':' as c_char && opterr != 0 {
87 let mut msg = [0 as c_char; 256];
88 let prog = if !(*argv).is_null() { *argv } else { b"\0".as_ptr() as *const c_char };
89 crate::fprintf(
90 crate::stderr,
91 b"%s: unrecognized option: %.*s\n\0".as_ptr() as *const c_char,
92 prog,
93 clen as c_int,
94 optchar,
95 );
96 let _ = &mut msg;
97 }
98 return b'?' as c_int;
99 }
100 if *spec.add(i + 1) == b':' as c_char {
101 optarg = core::ptr::null_mut();
102 if *spec.add(i + 2) != b':' as c_char || __optpos != 0 {
103 if optind >= argc {
104 optopt = c as c_int;
105 if *spec == b':' as c_char { return b':' as c_int; }
106 if opterr != 0 {
107 let prog = if !(*argv).is_null() { *argv } else { b"\0".as_ptr() as *const c_char };
108 crate::fprintf(
109 crate::stderr,
110 b"%s: option requires an argument: %.*s\n\0".as_ptr() as *const c_char,
111 prog,
112 clen as c_int,
113 optchar,
114 );
115 }
116 return b'?' as c_int;
117 }
118 optarg = *argv.add(optind as usize) as *mut c_char;
119 optind += 1;
120 if __optpos != 0 { optarg = optarg.add(__optpos as usize); }
121 __optpos = 0;
122 }
123 }
124 c as c_int
125}
126
127unsafe fn getopt_permute(argv: *mut *mut c_char, dest: isize, src: isize) {
128 let tmp = *argv.offset(src);
129 let mut i = src;
130 while i > dest {
131 *argv.offset(i) = *argv.offset(i - 1);
132 i -= 1;
133 }
134 *argv.offset(dest) = tmp;
135}
136
137unsafe fn getopt_long_core(
138 argc: c_int,
139 argv: *const *const c_char,
140 optstring: *const c_char,
141 longopts: *const LongOption,
142 idx: *mut c_int,
143 longonly: bool,
144) -> c_int {
145 optarg = core::ptr::null_mut();
146 let cur = *argv.add(optind as usize);
147 let is_long = !longopts.is_null()
148 && *cur == b'-' as c_char
149 && ((longonly && *cur.add(1) != 0 && *cur.add(1) != b'-' as c_char)
150 || (*cur.add(1) == b'-' as c_char && *cur.add(2) != 0));
151 if is_long {
152 let colon = *optstring.add(if *optstring == b'+' as c_char || *optstring == b'-' as c_char { 1 } else { 0 }) == b':' as c_char;
153 let start = cur.add(1);
154 let mut cnt = 0;
155 let mut match_idx = 0usize;
156 let mut arg: *const c_char = core::ptr::null();
157 let mut i = 0usize;
158 loop {
159 let opt = (*longopts.add(i)).name;
160 if opt.is_null() { break; }
161 let mut o = start;
162 if *o == b'-' as c_char { o = o.add(1); }
163 let mut n = opt;
164 while *o != 0 && *o != b'=' as c_char && *o == *n {
165 o = o.add(1);
166 n = n.add(1);
167 }
168 if *o != 0 && *o != b'=' as c_char {
169 i += 1;
170 continue;
171 }
172 arg = o;
173 match_idx = i;
174 if *n == 0 { cnt = 1; break; }
175 cnt += 1;
176 i += 1;
177 }
178 let _ = arg;
179 if cnt == 1 {
180 let opt = arg;
181 optind += 1;
182 let entry = *longopts.add(match_idx);
183 if *opt == b'=' as c_char {
184 if entry.has_arg == 0 {
185 optopt = entry.val;
186 if colon || opterr == 0 { return b'?' as c_int; }
187 crate::fprintf(
188 crate::stderr,
189 b"%s: option does not take an argument: %s\n\0".as_ptr() as *const c_char,
190 *argv,
191 entry.name,
192 );
193 return b'?' as c_int;
194 }
195 optarg = opt.add(1) as *mut c_char;
196 } else if entry.has_arg == 1 {
197 if optind >= argc {
198 optopt = entry.val;
199 if colon { return b':' as c_int; }
200 if opterr == 0 { return b'?' as c_int; }
201 crate::fprintf(
202 crate::stderr,
203 b"%s: option requires an argument: %s\n\0".as_ptr() as *const c_char,
204 *argv,
205 entry.name,
206 );
207 return b'?' as c_int;
208 }
209 optarg = *argv.add(optind as usize) as *mut c_char;
210 optind += 1;
211 }
212 if !idx.is_null() { *idx = match_idx as c_int; }
213 if !entry.flag.is_null() {
214 *entry.flag = entry.val;
215 return 0;
216 }
217 return entry.val;
218 }
219 if *cur.add(1) == b'-' as c_char {
220 optopt = 0;
221 if !colon && opterr != 0 {
222 crate::fprintf(
223 crate::stderr,
224 if cnt != 0 {
225 b"%s: option is ambiguous: %s\n\0".as_ptr() as *const c_char
226 } else {
227 b"%s: unrecognized option: %s\n\0".as_ptr() as *const c_char
228 },
229 *argv,
230 cur.add(2),
231 );
232 }
233 optind += 1;
234 return b'?' as c_int;
235 }
236 }
237 getopt(argc, argv, optstring)
238}
239
240#[no_mangle]
241pub unsafe extern "C" fn getopt_long(
242 argc: c_int,
243 argv: *const *const c_char,
244 optstring: *const c_char,
245 longopts: *const LongOption,
246 idx: *mut c_int,
247) -> c_int {
248 getopt_reset_if_needed();
249 if argc <= 0 || argv.is_null() { return -1; }
250 if optind >= argc || (*argv.add(optind as usize)).is_null() { return -1; }
251 let skipped = optind;
252 if *optstring != b'+' as c_char && *optstring != b'-' as c_char {
253 let mut i = optind;
254 loop {
255 if i >= argc || (*argv.add(i as usize)).is_null() { return -1; }
256 let a = *argv.add(i as usize);
257 if *a == b'-' as c_char && *a.add(1) != 0 { break; }
258 i += 1;
259 }
260 optind = i;
261 }
262 let resumed = optind;
263 let ret = getopt_long_core(argc, argv, optstring, longopts, idx, false);
264 if resumed > skipped {
265 let cnt = optind - resumed;
266 let mut i = 0;
267 while i < cnt {
268 getopt_permute(argv as *mut *mut c_char, skipped as isize, (optind - 1) as isize);
269 i += 1;
270 }
271 optind = skipped + cnt;
272 }
273 ret
274}
275
276#[no_mangle]
277pub unsafe extern "C" fn getopt_long_only(
278 argc: c_int,
279 argv: *const *const c_char,
280 optstring: *const c_char,
281 longopts: *const LongOption,
282 idx: *mut c_int,
283) -> c_int {
284 getopt_reset_if_needed();
285 if argc <= 0 || argv.is_null() { return -1; }
286 if optind >= argc || (*argv.add(optind as usize)).is_null() { return -1; }
287 let skipped = optind;
288 if *optstring != b'+' as c_char && *optstring != b'-' as c_char {
289 let mut i = optind;
290 loop {
291 if i >= argc || (*argv.add(i as usize)).is_null() { return -1; }
292 let a = *argv.add(i as usize);
293 if *a == b'-' as c_char && *a.add(1) != 0 { break; }
294 i += 1;
295 }
296 optind = i;
297 }
298 let resumed = optind;
299 let ret = getopt_long_core(argc, argv, optstring, longopts, idx, true);
300 if resumed > skipped {
301 let cnt = optind - resumed;
302 let mut i = 0;
303 while i < cnt {
304 getopt_permute(argv as *mut *mut c_char, skipped as isize, (optind - 1) as isize);
305 i += 1;
306 }
307 optind = skipped + cnt;
308 }
309 ret
310}