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