diff options
author | millert <> | 2002-12-05 21:45:01 +0000 |
---|---|---|
committer | millert <> | 2002-12-05 21:45:01 +0000 |
commit | 134d36e1be4bd10ccec3bfba3d10a9b959891c36 (patch) | |
tree | 0c60ca3de6c8688b8a581062622f9820a1974199 /src/lib | |
parent | 33cc42bb698271fab5f0273c3b9acc3a530efb59 (diff) | |
download | openbsd-134d36e1be4bd10ccec3bfba3d10a9b959891c36.tar.gz openbsd-134d36e1be4bd10ccec3bfba3d10a9b959891c36.tar.bz2 openbsd-134d36e1be4bd10ccec3bfba3d10a9b959891c36.zip |
Reorganize this so that getopt_only_only() works correctly.
In order for getopt_only_only() to work we need to check for long
options before short ones. I have merged getopt_internal and
getopt_long_internal into a single function with the actual long
args parsing broken out into a separate function.
This also simplifies the flow of control.
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/libc/stdlib/getopt_long.c | 429 |
1 files changed, 208 insertions, 221 deletions
diff --git a/src/lib/libc/stdlib/getopt_long.c b/src/lib/libc/stdlib/getopt_long.c index 4fc1874367..130c1d8bfa 100644 --- a/src/lib/libc/stdlib/getopt_long.c +++ b/src/lib/libc/stdlib/getopt_long.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: getopt_long.c,v 1.2 2002/12/03 20:28:12 millert Exp $ */ | 1 | /* $OpenBSD: getopt_long.c,v 1.3 2002/12/05 21:45:01 millert Exp $ */ |
2 | /* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ | 2 | /* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ |
3 | 3 | ||
4 | /*- | 4 | /*- |
@@ -38,7 +38,7 @@ | |||
38 | */ | 38 | */ |
39 | 39 | ||
40 | #if defined(LIBC_SCCS) && !defined(lint) | 40 | #if defined(LIBC_SCCS) && !defined(lint) |
41 | static char *rcsid = "$OpenBSD: getopt_long.c,v 1.2 2002/12/03 20:28:12 millert Exp $"; | 41 | static char *rcsid = "$OpenBSD: getopt_long.c,v 1.3 2002/12/05 21:45:01 millert Exp $"; |
42 | #endif /* LIBC_SCCS and not lint */ | 42 | #endif /* LIBC_SCCS and not lint */ |
43 | 43 | ||
44 | #include <err.h> | 44 | #include <err.h> |
@@ -57,9 +57,9 @@ char *optarg; /* argument associated with option */ | |||
57 | 57 | ||
58 | #define PRINT_ERROR ((opterr) && (*options != ':')) | 58 | #define PRINT_ERROR ((opterr) && (*options != ':')) |
59 | 59 | ||
60 | #define FLAG_PERMUTE 0x01 | 60 | #define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ |
61 | #define FLAG_ALLARGS 0x02 | 61 | #define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ |
62 | #define FLAG_LONGONLY 0x04 | 62 | #define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ |
63 | 63 | ||
64 | /* return values */ | 64 | /* return values */ |
65 | #define BADCH (int)'?' | 65 | #define BADCH (int)'?' |
@@ -68,9 +68,10 @@ char *optarg; /* argument associated with option */ | |||
68 | 68 | ||
69 | #define EMSG "" | 69 | #define EMSG "" |
70 | 70 | ||
71 | static int getopt_internal(int, char * const *, const char *, int); | 71 | static int getopt_internal(int, char * const *, const char *, |
72 | static int getopt_long_internal(int, char * const *, const char *, | 72 | const struct option *, int *, int); |
73 | const struct option *, int *, int); | 73 | static int parse_long_options(int, char * const *, const char *, |
74 | const struct option *, int *, int); | ||
74 | static int gcd(int, int); | 75 | static int gcd(int, int); |
75 | static void permute_args(int, int, int, char * const *); | 76 | static void permute_args(int, int, int, char * const *); |
76 | 77 | ||
@@ -92,9 +93,7 @@ static const char illoptstring[] = "unknown option -- %s"; | |||
92 | * Compute the greatest common divisor of a and b. | 93 | * Compute the greatest common divisor of a and b. |
93 | */ | 94 | */ |
94 | static int | 95 | static int |
95 | gcd(a, b) | 96 | gcd(int a, int b) |
96 | int a; | ||
97 | int b; | ||
98 | { | 97 | { |
99 | int c; | 98 | int c; |
100 | 99 | ||
@@ -105,7 +104,7 @@ gcd(a, b) | |||
105 | c = a % b; | 104 | c = a % b; |
106 | } | 105 | } |
107 | 106 | ||
108 | return b; | 107 | return (b); |
109 | } | 108 | } |
110 | 109 | ||
111 | /* | 110 | /* |
@@ -114,11 +113,8 @@ gcd(a, b) | |||
114 | * in each block). | 113 | * in each block). |
115 | */ | 114 | */ |
116 | static void | 115 | static void |
117 | permute_args(panonopt_start, panonopt_end, opt_end, nargv) | 116 | permute_args(int panonopt_start, int panonopt_end, int opt_end, |
118 | int panonopt_start; | 117 | char * const *nargv) |
119 | int panonopt_end; | ||
120 | int opt_end; | ||
121 | char * const *nargv; | ||
122 | { | 118 | { |
123 | int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; | 119 | int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; |
124 | char *swap; | 120 | char *swap; |
@@ -149,23 +145,154 @@ permute_args(panonopt_start, panonopt_end, opt_end, nargv) | |||
149 | } | 145 | } |
150 | 146 | ||
151 | /* | 147 | /* |
148 | * parse_long_options -- | ||
149 | * Parse long options in argc/argv argument vector. | ||
150 | * Returns -2 if long_only is set and the current option could be a short | ||
151 | * (single character) option instead. | ||
152 | */ | ||
153 | static int | ||
154 | parse_long_options(int nargc, char * const *nargv, const char *options, | ||
155 | const struct option *long_options, int *idx, int long_only) | ||
156 | { | ||
157 | char *current_argv, *has_equal; | ||
158 | size_t current_argv_len; | ||
159 | int i, match; | ||
160 | |||
161 | current_argv = place; | ||
162 | match = -1; | ||
163 | |||
164 | optind++; | ||
165 | |||
166 | if ((has_equal = strchr(current_argv, '=')) != NULL) { | ||
167 | /* argument found (--option=arg) */ | ||
168 | current_argv_len = has_equal - current_argv; | ||
169 | has_equal++; | ||
170 | } else | ||
171 | current_argv_len = strlen(current_argv); | ||
172 | |||
173 | for (i = 0; long_options[i].name; i++) { | ||
174 | /* find matching long option */ | ||
175 | if (strncmp(current_argv, long_options[i].name, | ||
176 | current_argv_len)) | ||
177 | continue; | ||
178 | |||
179 | if (strlen(long_options[i].name) == current_argv_len) { | ||
180 | /* exact match */ | ||
181 | match = i; | ||
182 | break; | ||
183 | } | ||
184 | /* | ||
185 | * Don't try a partial match of a short option when in | ||
186 | * long_only mode. Otherwise there is a potential conflict | ||
187 | * between partial matches and short options. | ||
188 | */ | ||
189 | if (long_only && current_argv_len == 1) | ||
190 | continue; | ||
191 | |||
192 | if (match == -1) /* partial match */ | ||
193 | match = i; | ||
194 | else { | ||
195 | /* ambiguous abbreviation */ | ||
196 | if (PRINT_ERROR) | ||
197 | warnx(ambig, (int)current_argv_len, | ||
198 | current_argv); | ||
199 | optopt = 0; | ||
200 | return (BADCH); | ||
201 | } | ||
202 | } | ||
203 | if (match != -1) { /* option found */ | ||
204 | if (long_options[match].has_arg == no_argument | ||
205 | && has_equal) { | ||
206 | if (PRINT_ERROR) | ||
207 | warnx(noarg, (int)current_argv_len, | ||
208 | current_argv); | ||
209 | /* | ||
210 | * XXX: GNU sets optopt to val regardless of flag | ||
211 | */ | ||
212 | if (long_options[match].flag == NULL) | ||
213 | optopt = long_options[match].val; | ||
214 | else | ||
215 | optopt = 0; | ||
216 | return (BADARG); | ||
217 | } | ||
218 | if (long_options[match].has_arg == required_argument || | ||
219 | long_options[match].has_arg == optional_argument) { | ||
220 | if (has_equal) | ||
221 | optarg = has_equal; | ||
222 | else if (long_options[match].has_arg == | ||
223 | required_argument) { | ||
224 | /* | ||
225 | * optional argument doesn't use next nargv | ||
226 | */ | ||
227 | optarg = nargv[optind++]; | ||
228 | } | ||
229 | } | ||
230 | if ((long_options[match].has_arg == required_argument) | ||
231 | && (optarg == NULL)) { | ||
232 | /* | ||
233 | * Missing argument; leading ':' indicates no error | ||
234 | * should be generated. | ||
235 | */ | ||
236 | if (PRINT_ERROR) | ||
237 | warnx(recargstring, | ||
238 | current_argv); | ||
239 | /* | ||
240 | * XXX: GNU sets optopt to val regardless of flag | ||
241 | */ | ||
242 | if (long_options[match].flag == NULL) | ||
243 | optopt = long_options[match].val; | ||
244 | else | ||
245 | optopt = 0; | ||
246 | --optind; | ||
247 | return (BADARG); | ||
248 | } | ||
249 | } else { /* unknown option */ | ||
250 | if (long_only) { | ||
251 | --optind; | ||
252 | return (-2); | ||
253 | } | ||
254 | if (PRINT_ERROR) | ||
255 | warnx(illoptstring, current_argv); | ||
256 | optopt = 0; | ||
257 | return (BADCH); | ||
258 | } | ||
259 | if (idx) | ||
260 | *idx = match; | ||
261 | if (long_options[match].flag) { | ||
262 | *long_options[match].flag = long_options[match].val; | ||
263 | return (0); | ||
264 | } else | ||
265 | return (long_options[match].val); | ||
266 | } | ||
267 | |||
268 | /* | ||
152 | * getopt_internal -- | 269 | * getopt_internal -- |
153 | * Parse argc/argv argument vector. Called by user level routines. | 270 | * Parse argc/argv argument vector. Called by user level routines. |
154 | * Returns -2 if -- is found (can be long option or end of options marker). | ||
155 | */ | 271 | */ |
156 | static int | 272 | static int |
157 | getopt_internal(nargc, nargv, options, flags) | 273 | getopt_internal(int nargc, char * const *nargv, const char *options, |
158 | int nargc; | 274 | const struct option *long_options, int *idx, int flags) |
159 | char * const *nargv; | ||
160 | const char *options; | ||
161 | int flags; | ||
162 | { | 275 | { |
163 | char *oli; /* option letter list index */ | 276 | char *oli; /* option letter list index */ |
164 | int optchar; | 277 | int optchar; |
278 | static int posixly_correct = -1; | ||
165 | 279 | ||
166 | optarg = NULL; | 280 | optarg = NULL; |
167 | 281 | ||
168 | /* | 282 | /* |
283 | * Disable GNU extensions if POSIXLY_CORRECT is set or options | ||
284 | * string begins with a '+'. | ||
285 | */ | ||
286 | if (posixly_correct == -1) | ||
287 | posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); | ||
288 | if (posixly_correct || *options == '+') | ||
289 | flags &= ~FLAG_PERMUTE; | ||
290 | else if (*options == '-') | ||
291 | flags |= FLAG_ALLARGS; | ||
292 | if (*options == '+' || *options == '-') | ||
293 | options++; | ||
294 | |||
295 | /* | ||
169 | * XXX Some programs (like rsyncd) expect to be able to | 296 | * XXX Some programs (like rsyncd) expect to be able to |
170 | * XXX re-initialize optind to 0 and have getopt_long(3) | 297 | * XXX re-initialize optind to 0 and have getopt_long(3) |
171 | * XXX properly function again. Work around this braindamage. | 298 | * XXX properly function again. Work around this braindamage. |
@@ -194,7 +321,7 @@ start: | |||
194 | optind = nonopt_start; | 321 | optind = nonopt_start; |
195 | } | 322 | } |
196 | nonopt_start = nonopt_end = -1; | 323 | nonopt_start = nonopt_end = -1; |
197 | return -1; | 324 | return (-1); |
198 | } | 325 | } |
199 | if ((*(place = nargv[optind]) != '-') | 326 | if ((*(place = nargv[optind]) != '-') |
200 | || (place[1] == '\0')) { /* found non-option */ | 327 | || (place[1] == '\0')) { /* found non-option */ |
@@ -205,14 +332,14 @@ start: | |||
205 | * return non-option as argument to option 1 | 332 | * return non-option as argument to option 1 |
206 | */ | 333 | */ |
207 | optarg = nargv[optind++]; | 334 | optarg = nargv[optind++]; |
208 | return INORDER; | 335 | return (INORDER); |
209 | } | 336 | } |
210 | if (!(flags & FLAG_PERMUTE)) { | 337 | if (!(flags & FLAG_PERMUTE)) { |
211 | /* | 338 | /* |
212 | * If no permutation wanted, stop parsing | 339 | * If no permutation wanted, stop parsing |
213 | * at first non-option. | 340 | * at first non-option. |
214 | */ | 341 | */ |
215 | return -1; | 342 | return (-1); |
216 | } | 343 | } |
217 | /* do permutation */ | 344 | /* do permutation */ |
218 | if (nonopt_start == -1) | 345 | if (nonopt_start == -1) |
@@ -230,42 +357,64 @@ start: | |||
230 | } | 357 | } |
231 | if (nonopt_start != -1 && nonopt_end == -1) | 358 | if (nonopt_start != -1 && nonopt_end == -1) |
232 | nonopt_end = optind; | 359 | nonopt_end = optind; |
233 | if (place[1] && *++place == '-') { /* found "--" */ | 360 | if (strcmp(place, "--") == 0) { |
234 | place++; | 361 | optind++; |
235 | return -2; | 362 | place = EMSG; |
363 | /* | ||
364 | * We found an option (--), so if we skipped | ||
365 | * non-options, we have to permute. | ||
366 | */ | ||
367 | if (nonopt_end != -1) { | ||
368 | permute_args(nonopt_start, nonopt_end, | ||
369 | optind, nargv); | ||
370 | optind -= nonopt_end - nonopt_start; | ||
371 | } | ||
372 | nonopt_start = nonopt_end = -1; | ||
373 | return (-1); | ||
374 | } | ||
375 | place++; | ||
376 | |||
377 | /* Check long options if we have any */ | ||
378 | if (long_options != NULL) { | ||
379 | int long_only = 0; | ||
380 | |||
381 | if (*place == '-' || | ||
382 | (long_only = (flags & FLAG_LONGONLY))) { | ||
383 | if (!long_only) | ||
384 | place++; | ||
385 | optchar = parse_long_options(nargc, nargv, | ||
386 | options, long_options, idx, long_only); | ||
387 | if (optchar != -2) { | ||
388 | place = EMSG; | ||
389 | return (optchar); | ||
390 | } | ||
391 | } | ||
236 | } | 392 | } |
237 | } | 393 | } |
238 | if ((optchar = (int)*place++) == (int)':' || | 394 | if ((optchar = (int)*place++) == (int)':' || |
239 | (oli = strchr(options, optchar)) == NULL) { | 395 | (oli = strchr(options, optchar)) == NULL) { |
240 | /* could it be a long option with a single '-'? */ | ||
241 | if (flags & FLAG_LONGONLY) | ||
242 | return -2; | ||
243 | /* option letter unknown or ':' */ | 396 | /* option letter unknown or ':' */ |
244 | if (!*place) | 397 | if (!*place) |
245 | ++optind; | 398 | ++optind; |
246 | if (PRINT_ERROR) | 399 | if (PRINT_ERROR) |
247 | warnx(illoptchar, optchar); | 400 | warnx(illoptchar, optchar); |
248 | optopt = optchar; | 401 | optopt = optchar; |
249 | return BADCH; | 402 | return (BADCH); |
250 | } | 403 | } |
251 | if (optchar == 'W' && oli[1] == ';') { /* -W long-option */ | 404 | if (long_options != NULL && optchar == 'W' && oli[1] == ';') { |
252 | /* XXX: what if no long options provided (called by getopt)? */ | 405 | /* -W long-option */ |
253 | if (*place) | ||
254 | return -2; | ||
255 | |||
256 | if (++optind >= nargc) { /* no arg */ | 406 | if (++optind >= nargc) { /* no arg */ |
257 | place = EMSG; | 407 | place = EMSG; |
258 | if (PRINT_ERROR) | 408 | if (PRINT_ERROR) |
259 | warnx(recargchar, optchar); | 409 | warnx(recargchar, optchar); |
260 | optopt = optchar; | 410 | optopt = optchar; |
261 | return BADARG; | 411 | return (BADARG); |
262 | } else /* white space */ | 412 | } else /* white space */ |
263 | place = nargv[optind]; | 413 | place = nargv[optind]; |
264 | /* | 414 | optchar = parse_long_options(nargc, nargv, options, |
265 | * Handle -W arg the same as --arg (which causes getopt to | 415 | long_options, idx, 0); |
266 | * stop parsing). | 416 | place = EMSG; |
267 | */ | 417 | return (optchar); |
268 | return -2; | ||
269 | } | 418 | } |
270 | if (*++oli != ':') { /* doesn't take argument */ | 419 | if (*++oli != ':') { /* doesn't take argument */ |
271 | if (!*place) | 420 | if (!*place) |
@@ -281,7 +430,7 @@ start: | |||
281 | if (PRINT_ERROR) | 430 | if (PRINT_ERROR) |
282 | warnx(recargchar, optchar); | 431 | warnx(recargchar, optchar); |
283 | optopt = optchar; | 432 | optopt = optchar; |
284 | return BADARG; | 433 | return (BADARG); |
285 | } else | 434 | } else |
286 | optarg = nargv[optind]; | 435 | optarg = nargv[optind]; |
287 | } | 436 | } |
@@ -289,7 +438,7 @@ start: | |||
289 | ++optind; | 438 | ++optind; |
290 | } | 439 | } |
291 | /* dump back option letter */ | 440 | /* dump back option letter */ |
292 | return optchar; | 441 | return (optchar); |
293 | } | 442 | } |
294 | 443 | ||
295 | #ifdef REPLACE_GETOPT | 444 | #ifdef REPLACE_GETOPT |
@@ -300,183 +449,20 @@ start: | |||
300 | * [eventually this will replace the BSD getopt] | 449 | * [eventually this will replace the BSD getopt] |
301 | */ | 450 | */ |
302 | int | 451 | int |
303 | getopt(nargc, nargv, options) | 452 | getopt(int nargc, char * const *nargv, const char *options) |
304 | int nargc; | ||
305 | char * const *nargv; | ||
306 | const char *options; | ||
307 | { | 453 | { |
308 | int retval; | ||
309 | |||
310 | if ((retval = getopt_internal(nargc, nargv, options, 0)) == -2) { | ||
311 | ++optind; | ||
312 | /* | ||
313 | * We found an option (--), so if we skipped non-options, | ||
314 | * we have to permute. | ||
315 | */ | ||
316 | if (nonopt_end != -1) { | ||
317 | permute_args(nonopt_start, nonopt_end, optind, | ||
318 | nargv); | ||
319 | optind -= nonopt_end - nonopt_start; | ||
320 | } | ||
321 | nonopt_start = nonopt_end = -1; | ||
322 | retval = -1; | ||
323 | } | ||
324 | return retval; | ||
325 | } | ||
326 | #endif /* REPLACE_GETOPT */ | ||
327 | |||
328 | /* | ||
329 | * getopt_long_internal -- | ||
330 | * Parse argc/argv argument vector. | ||
331 | */ | ||
332 | static int | ||
333 | getopt_long_internal(nargc, nargv, options, long_options, idx, flags) | ||
334 | int nargc; | ||
335 | char * const *nargv; | ||
336 | const char *options; | ||
337 | const struct option *long_options; | ||
338 | int *idx; | ||
339 | int flags; | ||
340 | { | ||
341 | int retval; | ||
342 | 454 | ||
343 | /* | 455 | /* |
344 | * Disable GNU extensions if POSIXLY_CORRECT is set or options | 456 | * We dont' pass FLAG_PERMUTE to getopt_internal() since |
345 | * string begins with a '+'. | 457 | * the BSD getopt(3) (unlike GNU) has never done this. |
458 | * | ||
459 | * Furthermore, since many privileged programs call getopt() | ||
460 | * before dropping privileges it makes sense to keep things | ||
461 | * as simple (and bug-free) as possible. | ||
346 | */ | 462 | */ |
347 | if (getenv("POSIXLY_CORRECT")) { | 463 | return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); |
348 | if (*options == '+' || *options == '-') | ||
349 | options++; | ||
350 | } else { | ||
351 | if (*options == '+') { | ||
352 | options++; | ||
353 | } else { | ||
354 | flags |= FLAG_PERMUTE; | ||
355 | if (*options == '-') { | ||
356 | flags |= FLAG_ALLARGS; | ||
357 | options++; | ||
358 | } | ||
359 | } | ||
360 | } | ||
361 | |||
362 | if ((retval = getopt_internal(nargc, nargv, options, flags)) == -2) { | ||
363 | char *current_argv, *has_equal; | ||
364 | size_t current_argv_len; | ||
365 | int i, match; | ||
366 | |||
367 | current_argv = place; | ||
368 | match = -1; | ||
369 | |||
370 | optind++; | ||
371 | place = EMSG; | ||
372 | |||
373 | if (*current_argv == '\0') { /* found "--" */ | ||
374 | /* | ||
375 | * We found an option (--), so if we skipped | ||
376 | * non-options, we have to permute. | ||
377 | */ | ||
378 | if (nonopt_end != -1) { | ||
379 | permute_args(nonopt_start, nonopt_end, | ||
380 | optind, nargv); | ||
381 | optind -= nonopt_end - nonopt_start; | ||
382 | } | ||
383 | nonopt_start = nonopt_end = -1; | ||
384 | return -1; | ||
385 | } | ||
386 | if ((has_equal = strchr(current_argv, '=')) != NULL) { | ||
387 | /* argument found (--option=arg) */ | ||
388 | current_argv_len = has_equal - current_argv; | ||
389 | has_equal++; | ||
390 | } else | ||
391 | current_argv_len = strlen(current_argv); | ||
392 | |||
393 | for (i = 0; long_options[i].name; i++) { | ||
394 | /* find matching long option */ | ||
395 | if (strncmp(current_argv, long_options[i].name, | ||
396 | current_argv_len)) | ||
397 | continue; | ||
398 | |||
399 | if (strlen(long_options[i].name) == | ||
400 | (unsigned)current_argv_len) { | ||
401 | /* exact match */ | ||
402 | match = i; | ||
403 | break; | ||
404 | } | ||
405 | if (match == -1) /* partial match */ | ||
406 | match = i; | ||
407 | else { | ||
408 | /* ambiguous abbreviation */ | ||
409 | if (PRINT_ERROR) | ||
410 | warnx(ambig, (int)current_argv_len, | ||
411 | current_argv); | ||
412 | optopt = 0; | ||
413 | return BADCH; | ||
414 | } | ||
415 | } | ||
416 | if (match != -1) { /* option found */ | ||
417 | if (long_options[match].has_arg == no_argument | ||
418 | && has_equal) { | ||
419 | if (PRINT_ERROR) | ||
420 | warnx(noarg, (int)current_argv_len, | ||
421 | current_argv); | ||
422 | /* | ||
423 | * XXX: GNU sets optopt to val regardless of | ||
424 | * flag | ||
425 | */ | ||
426 | if (long_options[match].flag == NULL) | ||
427 | optopt = long_options[match].val; | ||
428 | else | ||
429 | optopt = 0; | ||
430 | return BADARG; | ||
431 | } | ||
432 | if (long_options[match].has_arg == required_argument || | ||
433 | long_options[match].has_arg == optional_argument) { | ||
434 | if (has_equal) | ||
435 | optarg = has_equal; | ||
436 | else if (long_options[match].has_arg == | ||
437 | required_argument) { | ||
438 | /* | ||
439 | * optional argument doesn't use | ||
440 | * next nargv | ||
441 | */ | ||
442 | optarg = nargv[optind++]; | ||
443 | } | ||
444 | } | ||
445 | if ((long_options[match].has_arg == required_argument) | ||
446 | && (optarg == NULL)) { | ||
447 | /* | ||
448 | * Missing argument; leading ':' | ||
449 | * indicates no error should be generated | ||
450 | */ | ||
451 | if (PRINT_ERROR) | ||
452 | warnx(recargstring, current_argv); | ||
453 | /* | ||
454 | * XXX: GNU sets optopt to val regardless | ||
455 | * of flag | ||
456 | */ | ||
457 | if (long_options[match].flag == NULL) | ||
458 | optopt = long_options[match].val; | ||
459 | else | ||
460 | optopt = 0; | ||
461 | --optind; | ||
462 | return BADARG; | ||
463 | } | ||
464 | } else { /* unknown option */ | ||
465 | if (PRINT_ERROR) | ||
466 | warnx(illoptstring, current_argv); | ||
467 | optopt = 0; | ||
468 | return BADCH; | ||
469 | } | ||
470 | if (long_options[match].flag) { | ||
471 | *long_options[match].flag = long_options[match].val; | ||
472 | retval = 0; | ||
473 | } else | ||
474 | retval = long_options[match].val; | ||
475 | if (idx) | ||
476 | *idx = match; | ||
477 | } | ||
478 | return retval; | ||
479 | } | 464 | } |
465 | #endif /* REPLACE_GETOPT */ | ||
480 | 466 | ||
481 | /* | 467 | /* |
482 | * getopt_long -- | 468 | * getopt_long -- |
@@ -491,7 +477,8 @@ getopt_long(nargc, nargv, options, long_options, idx) | |||
491 | int *idx; | 477 | int *idx; |
492 | { | 478 | { |
493 | 479 | ||
494 | return getopt_long_internal(nargc, nargv, options, long_options, idx, 0); | 480 | return (getopt_internal(nargc, nargv, options, long_options, idx, |
481 | FLAG_PERMUTE)); | ||
495 | } | 482 | } |
496 | 483 | ||
497 | /* | 484 | /* |
@@ -507,6 +494,6 @@ getopt_long_only(nargc, nargv, options, long_options, idx) | |||
507 | int *idx; | 494 | int *idx; |
508 | { | 495 | { |
509 | 496 | ||
510 | return getopt_long_internal(nargc, nargv, options, long_options, idx, | 497 | return (getopt_internal(nargc, nargv, options, long_options, idx, |
511 | FLAG_LONGONLY); | 498 | FLAG_PERMUTE|FLAG_LONGONLY)); |
512 | } | 499 | } |