48e2f01c |
1 | /* $OpenBSD: getopt_long.c,v 1.21 2006/09/22 17:22:05 millert Exp $ */ |
2 | /* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ |
3 | |
4 | /* |
5 | * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com> |
6 | * |
7 | * Permission to use, copy, modify, and distribute this software for any |
8 | * purpose with or without fee is hereby granted, provided that the above |
9 | * copyright notice and this permission notice appear in all copies. |
10 | * |
11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
18 | * |
19 | * Sponsored in part by the Defense Advanced Research Projects |
20 | * Agency (DARPA) and Air Force Research Laboratory, Air Force |
21 | * Materiel Command, USAF, under agreement number F39502-99-1-0512. |
22 | */ |
23 | /*- |
24 | * Copyright (c) 2000 The NetBSD Foundation, Inc. |
25 | * All rights reserved. |
26 | * |
27 | * This code is derived from software contributed to The NetBSD Foundation |
28 | * by Dieter Baron and Thomas Klausner. |
29 | * |
30 | * Redistribution and use in source and binary forms, with or without |
31 | * modification, are permitted provided that the following conditions |
32 | * are met: |
33 | * 1. Redistributions of source code must retain the above copyright |
34 | * notice, this list of conditions and the following disclaimer. |
35 | * 2. Redistributions in binary form must reproduce the above copyright |
36 | * notice, this list of conditions and the following disclaimer in the |
37 | * documentation and/or other materials provided with the distribution. |
38 | * 3. All advertising materials mentioning features or use of this software |
39 | * must display the following acknowledgement: |
40 | * This product includes software developed by the NetBSD |
41 | * Foundation, Inc. and its contributors. |
42 | * 4. Neither the name of The NetBSD Foundation nor the names of its |
43 | * contributors may be used to endorse or promote products derived |
44 | * from this software without specific prior written permission. |
45 | * |
46 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
47 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
48 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
49 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
50 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
51 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
52 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
53 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
54 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
55 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
56 | * POSSIBILITY OF SUCH DAMAGE. |
57 | */ |
58 | |
59 | #if 0 |
60 | #if defined(LIBC_SCCS) && !defined(lint) |
61 | static char *rcsid = "$OpenBSD: getopt_long.c,v 1.16 2004/02/04 18:17:25 millert Exp $"; |
62 | #endif /* LIBC_SCCS and not lint */ |
63 | #endif |
64 | |
65 | #include <stdio.h> |
66 | #include <stdlib.h> |
67 | #include <string.h> |
68 | #include <stdarg.h> |
69 | #include <errno.h> |
70 | #include "getopt.h" |
71 | |
72 | #define GNU_COMPATIBLE /* Be more compatible, configure's use us! */ |
73 | |
74 | #if 0 /* we prefer to keep our getopt(3) */ |
75 | #define REPLACE_GETOPT /* use this getopt as the system getopt(3) */ |
76 | #endif |
77 | |
78 | int opterr = 1; /* if error message should be printed */ |
79 | int optind = 1; /* index into parent argv vector */ |
80 | int optopt = '?'; /* character checked for validity */ |
81 | int optreset; /* reset getopt */ |
82 | char *optarg; /* argument associated with option */ |
83 | |
84 | #define PRINT_ERROR ((opterr) && (*options != ':')) |
85 | |
86 | #define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ |
87 | #define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ |
88 | #define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ |
89 | |
90 | /* return values */ |
91 | #define BADCH (int)'?' |
92 | #define BADARG ((*options == ':') ? (int)':' : (int)'?') |
93 | #define INORDER (int)1 |
94 | |
95 | #define EMSG "" |
96 | |
97 | #ifdef GNU_COMPATIBLE |
98 | #define NO_PREFIX (-1) |
99 | #define D_PREFIX 0 |
100 | #define DD_PREFIX 1 |
101 | #define W_PREFIX 2 |
102 | #endif |
103 | |
104 | static int getopt_internal(int, char * const *, const char *, |
105 | const struct option *, int *, int); |
106 | static int parse_long_options(char * const *, const char *, |
107 | const struct option *, int *, int, int); |
108 | static int gcd(int, int); |
109 | static void permute_args(int, int, int, char * const *); |
110 | |
111 | static char *place = EMSG; /* option letter processing */ |
112 | |
113 | /* XXX: set optreset to 1 rather than these two */ |
114 | static int nonopt_start = -1; /* first non option argument (for permute) */ |
115 | static int nonopt_end = -1; /* first option after non options (for permute) */ |
116 | |
117 | /* Error messages */ |
118 | static const char recargchar[] = "option requires an argument -- %c"; |
119 | static const char illoptchar[] = "illegal option -- %c"; /* From P1003.2 */ |
120 | #ifdef GNU_COMPATIBLE |
121 | static int dash_prefix = NO_PREFIX; |
122 | static const char gnuoptchar[] = "invalid option -- %c"; |
123 | |
124 | static const char recargstring[] = "option `%s%s' requires an argument"; |
125 | static const char ambig[] = "option `%s%.*s' is ambiguous"; |
126 | static const char noarg[] = "option `%s%.*s' doesn't allow an argument"; |
127 | static const char illoptstring[] = "unrecognized option `%s%s'"; |
128 | #else |
129 | static const char recargstring[] = "option requires an argument -- %s"; |
130 | static const char ambig[] = "ambiguous option -- %.*s"; |
131 | static const char noarg[] = "option doesn't take an argument -- %.*s"; |
132 | static const char illoptstring[] = "unknown option -- %s"; |
133 | #endif |
134 | |
135 | static void |
136 | warnx(const char *fmt, ...) |
137 | { |
138 | va_list args; |
139 | va_start(args, fmt); |
140 | vfprintf(stderr, fmt, args); |
141 | putc('\n', stderr); |
142 | va_end(args); |
143 | } |
144 | |
145 | /* |
146 | * Compute the greatest common divisor of a and b. |
147 | */ |
148 | static int |
149 | gcd(int a, int b) |
150 | { |
151 | int c; |
152 | |
153 | c = a % b; |
154 | while (c != 0) { |
155 | a = b; |
156 | b = c; |
157 | c = a % b; |
158 | } |
159 | |
160 | return (b); |
161 | } |
162 | |
163 | /* |
164 | * Exchange the block from nonopt_start to nonopt_end with the block |
165 | * from nonopt_end to opt_end (keeping the same order of arguments |
166 | * in each block). |
167 | */ |
168 | static void |
169 | permute_args(int panonopt_start, int panonopt_end, int opt_end, |
170 | char * const *nargv) |
171 | { |
172 | int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; |
173 | char *swap; |
174 | |
175 | /* |
176 | * compute lengths of blocks and number and size of cycles |
177 | */ |
178 | nnonopts = panonopt_end - panonopt_start; |
179 | nopts = opt_end - panonopt_end; |
180 | ncycle = gcd(nnonopts, nopts); |
181 | cyclelen = (opt_end - panonopt_start) / ncycle; |
182 | |
183 | for (i = 0; i < ncycle; i++) { |
184 | cstart = panonopt_end+i; |
185 | pos = cstart; |
186 | for (j = 0; j < cyclelen; j++) { |
187 | if (pos >= panonopt_end) |
188 | pos -= nnonopts; |
189 | else |
190 | pos += nopts; |
191 | swap = nargv[pos]; |
192 | /* LINTED const cast */ |
193 | ((char **) nargv)[pos] = nargv[cstart]; |
194 | /* LINTED const cast */ |
195 | ((char **)nargv)[cstart] = swap; |
196 | } |
197 | } |
198 | } |
199 | |
200 | /* |
201 | * parse_long_options -- |
202 | * Parse long options in argc/argv argument vector. |
203 | * Returns -1 if short_too is set and the option does not match long_options. |
204 | */ |
205 | static int |
206 | parse_long_options(char * const *nargv, const char *options, |
207 | const struct option *long_options, int *idx, int short_too, int flags) |
208 | { |
209 | char *current_argv, *has_equal; |
210 | #ifdef GNU_COMPATIBLE |
211 | char *current_dash; |
212 | #endif |
213 | size_t current_argv_len; |
214 | int i, match, exact_match, second_partial_match; |
215 | |
216 | current_argv = place; |
217 | #ifdef GNU_COMPATIBLE |
218 | switch (dash_prefix) { |
219 | case D_PREFIX: |
220 | current_dash = "-"; |
221 | break; |
222 | case DD_PREFIX: |
223 | current_dash = "--"; |
224 | break; |
225 | case W_PREFIX: |
226 | current_dash = "-W "; |
227 | break; |
228 | default: |
229 | current_dash = ""; |
230 | break; |
231 | } |
232 | #endif |
233 | match = -1; |
234 | exact_match = 0; |
235 | second_partial_match = 0; |
236 | |
237 | optind++; |
238 | |
239 | if ((has_equal = strchr(current_argv, '=')) != NULL) { |
240 | /* argument found (--option=arg) */ |
241 | current_argv_len = has_equal - current_argv; |
242 | has_equal++; |
243 | } else |
244 | current_argv_len = strlen(current_argv); |
245 | |
246 | for (i = 0; long_options[i].name; i++) { |
247 | /* find matching long option */ |
248 | if (strncmp(current_argv, long_options[i].name, |
249 | current_argv_len)) |
250 | continue; |
251 | |
252 | if (strlen(long_options[i].name) == current_argv_len) { |
253 | /* exact match */ |
254 | match = i; |
255 | exact_match = 1; |
256 | break; |
257 | } |
258 | /* |
259 | * If this is a known short option, don't allow |
260 | * a partial match of a single character. |
261 | */ |
262 | if (short_too && current_argv_len == 1) |
263 | continue; |
264 | |
265 | if (match == -1) /* first partial match */ |
266 | match = i; |
267 | else if ((flags & FLAG_LONGONLY) || |
268 | long_options[i].has_arg != |
269 | long_options[match].has_arg || |
270 | long_options[i].flag != long_options[match].flag || |
271 | long_options[i].val != long_options[match].val) |
272 | second_partial_match = 1; |
273 | } |
274 | if (!exact_match && second_partial_match) { |
275 | /* ambiguous abbreviation */ |
276 | if (PRINT_ERROR) |
277 | warnx(ambig, |
278 | #ifdef GNU_COMPATIBLE |
279 | current_dash, |
280 | #endif |
281 | (int)current_argv_len, |
282 | current_argv); |
283 | optopt = 0; |
284 | return (BADCH); |
285 | } |
286 | if (match != -1) { /* option found */ |
287 | if (long_options[match].has_arg == no_argument |
288 | && has_equal) { |
289 | if (PRINT_ERROR) |
290 | warnx(noarg, |
291 | #ifdef GNU_COMPATIBLE |
292 | current_dash, |
293 | #endif |
294 | (int)current_argv_len, |
295 | current_argv); |
296 | /* |
297 | * XXX: GNU sets optopt to val regardless of flag |
298 | */ |
299 | if (long_options[match].flag == NULL) |
300 | optopt = long_options[match].val; |
301 | else |
302 | optopt = 0; |
303 | #ifdef GNU_COMPATIBLE |
304 | return (BADCH); |
305 | #else |
306 | return (BADARG); |
307 | #endif |
308 | } |
309 | if (long_options[match].has_arg == required_argument || |
310 | long_options[match].has_arg == optional_argument) { |
311 | if (has_equal) |
312 | optarg = has_equal; |
313 | else if (long_options[match].has_arg == |
314 | required_argument) { |
315 | /* |
316 | * optional argument doesn't use next nargv |
317 | */ |
318 | optarg = nargv[optind++]; |
319 | } |
320 | } |
321 | if ((long_options[match].has_arg == required_argument) |
322 | && (optarg == NULL)) { |
323 | /* |
324 | * Missing argument; leading ':' indicates no error |
325 | * should be generated. |
326 | */ |
327 | if (PRINT_ERROR) |
328 | warnx(recargstring, |
329 | #ifdef GNU_COMPATIBLE |
330 | current_dash, |
331 | #endif |
332 | current_argv); |
333 | /* |
334 | * XXX: GNU sets optopt to val regardless of flag |
335 | */ |
336 | if (long_options[match].flag == NULL) |
337 | optopt = long_options[match].val; |
338 | else |
339 | optopt = 0; |
340 | --optind; |
341 | return (BADARG); |
342 | } |
343 | } else { /* unknown option */ |
344 | if (short_too) { |
345 | --optind; |
346 | return (-1); |
347 | } |
348 | if (PRINT_ERROR) |
349 | warnx(illoptstring, |
350 | #ifdef GNU_COMPATIBLE |
351 | current_dash, |
352 | #endif |
353 | current_argv); |
354 | optopt = 0; |
355 | return (BADCH); |
356 | } |
357 | if (idx) |
358 | *idx = match; |
359 | if (long_options[match].flag) { |
360 | *long_options[match].flag = long_options[match].val; |
361 | return (0); |
362 | } else |
363 | return (long_options[match].val); |
364 | } |
365 | |
366 | /* |
367 | * getopt_internal -- |
368 | * Parse argc/argv argument vector. Called by user level routines. |
369 | */ |
370 | static int |
371 | getopt_internal(int nargc, char * const *nargv, const char *options, |
372 | const struct option *long_options, int *idx, int flags) |
373 | { |
374 | char *oli; /* option letter list index */ |
375 | int optchar, short_too; |
376 | int posixly_correct; /* no static, can be changed on the fly */ |
377 | |
378 | if (options == NULL) |
379 | return (-1); |
380 | |
381 | /* |
382 | * Disable GNU extensions if POSIXLY_CORRECT is set or options |
383 | * string begins with a '+'. |
384 | */ |
385 | posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); |
386 | #ifdef GNU_COMPATIBLE |
387 | if (*options == '-') |
388 | flags |= FLAG_ALLARGS; |
389 | else if (posixly_correct || *options == '+') |
390 | flags &= ~FLAG_PERMUTE; |
391 | #else |
392 | if (posixly_correct || *options == '+') |
393 | flags &= ~FLAG_PERMUTE; |
394 | else if (*options == '-') |
395 | flags |= FLAG_ALLARGS; |
396 | #endif |
397 | if (*options == '+' || *options == '-') |
398 | options++; |
399 | |
400 | /* |
401 | * XXX Some GNU programs (like cvs) set optind to 0 instead of |
402 | * XXX using optreset. Work around this braindamage. |
403 | */ |
404 | if (optind == 0) |
405 | optind = optreset = 1; |
406 | |
407 | optarg = NULL; |
408 | if (optreset) |
409 | nonopt_start = nonopt_end = -1; |
410 | start: |
411 | if (optreset || !*place) { /* update scanning pointer */ |
412 | optreset = 0; |
413 | if (optind >= nargc) { /* end of argument vector */ |
414 | place = EMSG; |
415 | if (nonopt_end != -1) { |
416 | /* do permutation, if we have to */ |
417 | permute_args(nonopt_start, nonopt_end, |
418 | optind, nargv); |
419 | optind -= nonopt_end - nonopt_start; |
420 | } |
421 | else if (nonopt_start != -1) { |
422 | /* |
423 | * If we skipped non-options, set optind |
424 | * to the first of them. |
425 | */ |
426 | optind = nonopt_start; |
427 | } |
428 | nonopt_start = nonopt_end = -1; |
429 | return (-1); |
430 | } |
431 | if (*(place = nargv[optind]) != '-' || |
432 | #ifdef GNU_COMPATIBLE |
433 | place[1] == '\0') { |
434 | #else |
435 | (place[1] == '\0' && strchr(options, '-') == NULL)) { |
436 | #endif |
437 | place = EMSG; /* found non-option */ |
438 | if (flags & FLAG_ALLARGS) { |
439 | /* |
440 | * GNU extension: |
441 | * return non-option as argument to option 1 |
442 | */ |
443 | optarg = nargv[optind++]; |
444 | return (INORDER); |
445 | } |
446 | if (!(flags & FLAG_PERMUTE)) { |
447 | /* |
448 | * If no permutation wanted, stop parsing |
449 | * at first non-option. |
450 | */ |
451 | return (-1); |
452 | } |
453 | /* do permutation */ |
454 | if (nonopt_start == -1) |
455 | nonopt_start = optind; |
456 | else if (nonopt_end != -1) { |
457 | permute_args(nonopt_start, nonopt_end, |
458 | optind, nargv); |
459 | nonopt_start = optind - |
460 | (nonopt_end - nonopt_start); |
461 | nonopt_end = -1; |
462 | } |
463 | optind++; |
464 | /* process next argument */ |
465 | goto start; |
466 | } |
467 | if (nonopt_start != -1 && nonopt_end == -1) |
468 | nonopt_end = optind; |
469 | |
470 | /* |
471 | * If we have "-" do nothing, if "--" we are done. |
472 | */ |
473 | if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { |
474 | optind++; |
475 | place = EMSG; |
476 | /* |
477 | * We found an option (--), so if we skipped |
478 | * non-options, we have to permute. |
479 | */ |
480 | if (nonopt_end != -1) { |
481 | permute_args(nonopt_start, nonopt_end, |
482 | optind, nargv); |
483 | optind -= nonopt_end - nonopt_start; |
484 | } |
485 | nonopt_start = nonopt_end = -1; |
486 | return (-1); |
487 | } |
488 | } |
489 | |
490 | /* |
491 | * Check long options if: |
492 | * 1) we were passed some |
493 | * 2) the arg is not just "-" |
494 | * 3) either the arg starts with -- we are getopt_long_only() |
495 | */ |
496 | if (long_options != NULL && place != nargv[optind] && |
497 | (*place == '-' || (flags & FLAG_LONGONLY))) { |
498 | short_too = 0; |
499 | #ifdef GNU_COMPATIBLE |
500 | dash_prefix = D_PREFIX; |
501 | #endif |
502 | if (*place == '-') { |
503 | place++; /* --foo long option */ |
504 | #ifdef GNU_COMPATIBLE |
505 | dash_prefix = DD_PREFIX; |
506 | #endif |
507 | } else if (*place != ':' && strchr(options, *place) != NULL) |
508 | short_too = 1; /* could be short option too */ |
509 | |
510 | optchar = parse_long_options(nargv, options, long_options, |
511 | idx, short_too, flags); |
512 | if (optchar != -1) { |
513 | place = EMSG; |
514 | return (optchar); |
515 | } |
516 | } |
517 | |
518 | if ((optchar = (int)*place++) == (int)':' || |
519 | (optchar == (int)'-' && *place != '\0') || |
520 | (oli = strchr(options, optchar)) == NULL) { |
521 | /* |
522 | * If the user specified "-" and '-' isn't listed in |
523 | * options, return -1 (non-option) as per POSIX. |
524 | * Otherwise, it is an unknown option character (or ':'). |
525 | */ |
526 | if (optchar == (int)'-' && *place == '\0') |
527 | return (-1); |
528 | if (!*place) |
529 | ++optind; |
530 | #ifdef GNU_COMPATIBLE |
531 | if (PRINT_ERROR) |
532 | warnx(posixly_correct ? illoptchar : gnuoptchar, |
533 | optchar); |
534 | #else |
535 | if (PRINT_ERROR) |
536 | warnx(illoptchar, optchar); |
537 | #endif |
538 | optopt = optchar; |
539 | return (BADCH); |
540 | } |
541 | if (long_options != NULL && optchar == 'W' && oli[1] == ';') { |
542 | /* -W long-option */ |
543 | if (*place) /* no space */ |
544 | /* NOTHING */; |
545 | else if (++optind >= nargc) { /* no arg */ |
546 | place = EMSG; |
547 | if (PRINT_ERROR) |
548 | warnx(recargchar, optchar); |
549 | optopt = optchar; |
550 | return (BADARG); |
551 | } else /* white space */ |
552 | place = nargv[optind]; |
553 | #ifdef GNU_COMPATIBLE |
554 | dash_prefix = W_PREFIX; |
555 | #endif |
556 | optchar = parse_long_options(nargv, options, long_options, |
557 | idx, 0, flags); |
558 | place = EMSG; |
559 | return (optchar); |
560 | } |
561 | if (*++oli != ':') { /* doesn't take argument */ |
562 | if (!*place) |
563 | ++optind; |
564 | } else { /* takes (optional) argument */ |
565 | optarg = NULL; |
566 | if (*place) /* no white space */ |
567 | optarg = place; |
568 | else if (oli[1] != ':') { /* arg not optional */ |
569 | if (++optind >= nargc) { /* no arg */ |
570 | place = EMSG; |
571 | if (PRINT_ERROR) |
572 | warnx(recargchar, optchar); |
573 | optopt = optchar; |
574 | return (BADARG); |
575 | } else |
576 | optarg = nargv[optind]; |
577 | } |
578 | place = EMSG; |
579 | ++optind; |
580 | } |
581 | /* dump back option letter */ |
582 | return (optchar); |
583 | } |
584 | |
585 | /* |
586 | * getopt -- |
587 | * Parse argc/argv argument vector. |
588 | * |
589 | * [eventually this will replace the BSD getopt] |
590 | */ |
591 | int |
592 | getopt(int nargc, char * const *nargv, const char *options) |
593 | { |
594 | |
595 | /* |
596 | * We don't pass FLAG_PERMUTE to getopt_internal() since |
597 | * the BSD getopt(3) (unlike GNU) has never done this. |
598 | * |
599 | * Furthermore, since many privileged programs call getopt() |
600 | * before dropping privileges it makes sense to keep things |
601 | * as simple (and bug-free) as possible. |
602 | */ |
603 | return (getopt_internal(nargc, nargv, options, NULL, NULL, FLAG_PERMUTE)); |
604 | } |
605 | |
606 | /* |
607 | * getopt_long -- |
608 | * Parse argc/argv argument vector. |
609 | */ |
610 | int |
611 | getopt_long(int nargc, char * const *nargv, const char *options, |
612 | const struct option *long_options, int *idx) |
613 | { |
614 | |
615 | return (getopt_internal(nargc, nargv, options, long_options, idx, |
616 | FLAG_PERMUTE)); |
617 | } |
618 | |
619 | /* |
620 | * getopt_long_only -- |
621 | * Parse argc/argv argument vector. |
622 | */ |
623 | int |
624 | getopt_long_only(int nargc, char * const *nargv, const char *options, |
625 | const struct option *long_options, int *idx) |
626 | { |
627 | |
628 | return (getopt_internal(nargc, nargv, options, long_options, idx, |
629 | FLAG_PERMUTE|FLAG_LONGONLY)); |
630 | } |