- Timestamp:
- Nov 8, 2004, 1:42:55 AM (21 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/emx/src/lib/bsd/stdlib/getopt_long.c
-
Property cvs2svn:cvs-rev
changed from
1.2to1.3
r1622 r1623 1 1 2 /* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ 2 /* $FreeBSD: src/lib/libc/stdlib/getopt_long.c,v 1.2 2002/10/16 22:18:42 alfred Exp $ */ 3 3 4 /* 5 * Copyright (c) 2002 Todd C. Miller <[email protected]> 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 */ 4 23 /*- 5 24 * Copyright (c) 2000 The NetBSD Foundation, Inc. … … 38 57 */ 39 58 59 60 61 62 63 64 65 66 67 40 68 #include <sys/cdefs.h> 41 #if defined(LIBC_SCCS) && !defined(lint) 42 __RCSID("$NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $"); 43 #endif /* LIBC_SCCS and not lint */ 44 45 #include "namespace.h" 46 47 #include <assert.h> 69 __FBSDID("$FreeBSD: src/lib/libc/stdlib/getopt_long.c,v 1.12 2004/07/06 13:58:45 ache Exp $"); 70 48 71 #include <err.h> 49 72 #include <errno.h> … … 56 79 #endif 57 80 58 /* not part of the original file */ 59 #ifndef _DIAGASSERT 60 #define _DIAGASSERT(X) 61 #endif 62 63 #if HAVE_CONFIG_H && !HAVE_GETOPT_LONG && !HAVE_DECL_OPTIND 64 #define REPLACE_GETOPT 81 #define GNU_COMPATIBLE /* Be more compatible, configure's use us! */ 82 83 #ifndef GNU_COMPATIBLE 84 #define REPLACE_GETOPT /* use this getopt as the system getopt(3) */ 65 85 #endif 66 86 67 87 #ifdef REPLACE_GETOPT 68 #ifdef __weak_alias69 __weak_alias(getopt,_getopt)70 #endif71 88 int opterr = 1; /* if error message should be printed */ 72 89 int optind = 1; /* index into parent argv vector */ … … 74 91 int optreset; /* reset getopt */ 75 92 char *optarg; /* argument associated with option */ 76 #elif HAVE_CONFIG_H && !HAVE_DECL_OPTRESET 77 static int optreset; 78 #endif 79 80 #ifdef __weak_alias 81 __weak_alias(getopt_long,_getopt_long) 82 #endif 83 84 #if !HAVE_GETOPT_LONG 85 #define IGNORE_FIRST (*options == '-' || *options == '+') 86 #define PRINT_ERROR ((opterr) && ((*options != ':') \ 87 || (IGNORE_FIRST && options[1] != ':'))) 88 #define IS_POSIXLY_CORRECT (getenv("POSIXLY_CORRECT") != NULL) 89 #define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST) 90 /* XXX: GNU ignores PC if *options == '-' */ 91 #define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-') 93 #endif 94 95 #define PRINT_ERROR ((opterr) && (*options != ':')) 96 97 #define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ 98 #define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ 99 #define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ 92 100 93 101 /* return values */ 94 #define BADCH (int)'?' 95 #define BADARG ((IGNORE_FIRST && options[1] == ':') \ 96 || (*options == ':') ? (int)':' : (int)'?') 97 #define INORDER (int)1 98 99 #define EMSG "" 100 101 static int getopt_internal(int, char * const *, const char *); 102 #define BADCH (int)'?' 103 #define BADARG ((*options == ':') ? (int)':' : (int)'?') 104 #define INORDER (int)1 105 106 #define EMSG "" 107 108 #ifdef GNU_COMPATIBLE 109 #define NO_PREFIX (-1) 110 #define D_PREFIX 0 111 #define DD_PREFIX 1 112 #define W_PREFIX 2 113 #endif 114 115 static int getopt_internal(int, char * const *, const char *, 116 const struct option *, int *, int); 117 static int parse_long_options(char * const *, const char *, 118 const struct option *, int *, int, int); 102 119 static int gcd(int, int); 103 120 static void permute_args(int, int, int, char * const *); … … 111 128 /* Error messages */ 112 129 static const char recargchar[] = "option requires an argument -- %c"; 130 131 132 133 134 135 136 137 138 139 113 140 static const char recargstring[] = "option requires an argument -- %s"; 114 141 static const char ambig[] = "ambiguous option -- %.*s"; 115 142 static const char noarg[] = "option doesn't take an argument -- %.*s"; 116 static const char illoptchar[] = "unknown option -- %c";117 143 static const char illoptstring[] = "unknown option -- %s"; 118 144 #endif 119 145 120 146 /* … … 122 148 */ 123 149 static int 124 gcd(a, b) 125 int a; 126 int b; 150 gcd(int a, int b) 127 151 { 128 152 int c; … … 134 158 c = a % b; 135 159 } 136 137 return b; 160 return (b); 138 161 } 139 162 … … 144 167 */ 145 168 static void 146 permute_args(panonopt_start, panonopt_end, opt_end, nargv) 147 int panonopt_start; 148 int panonopt_end; 149 int opt_end; 150 char * const *nargv; 169 permute_args(int panonopt_start, int panonopt_end, int opt_end, 170 char * const *nargv) 151 171 { 152 172 int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; 153 173 char *swap; 154 155 _DIAGASSERT(nargv != NULL);156 174 157 175 /* … … 181 199 182 200 /* 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 183 367 * getopt_internal -- 184 368 * Parse argc/argv argument vector. Called by user level routines. 185 * Returns -2 if -- is found (can be long option or end of options marker).186 369 */ 187 370 static int 188 getopt_internal(nargc, nargv, options) 189 int nargc; 190 char * const *nargv; 191 const char *options; 371 getopt_internal(int nargc, char * const *nargv, const char *options, 372 const struct option *long_options, int *idx, int flags) 192 373 { 193 374 char *oli; /* option letter list index */ 194 int optchar; 195 196 _DIAGASSERT(nargv != NULL); 197 _DIAGASSERT(options != NULL); 198 199 optarg = NULL; 375 int optchar, short_too; 376 int posixly_correct; 377 378 if (options == NULL) 379 return (-1); 200 380 201 381 /* 202 * XXX Some programs (like rsyncd) expect to be able to 203 * XXX re-initialize optind to 0 and have getopt_long(3) 204 * XXX properly function again. Work around this braindamage. 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. 205 403 */ 206 404 if (optind == 0) 207 optind = 1; 208 405 optind = optreset = 1; 406 407 optarg = NULL; 209 408 if (optreset) 210 409 nonopt_start = nonopt_end = -1; … … 228 427 } 229 428 nonopt_start = nonopt_end = -1; 230 return -1; 231 } 232 if ((*(place = nargv[optind]) != '-') 233 || (place[1] == '\0')) { /* found non-option */ 234 place = EMSG; 235 if (IN_ORDER) { 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) { 236 439 /* 237 440 * GNU extension: … … 239 442 */ 240 443 optarg = nargv[optind++]; 241 return INORDER;444 return ; 242 445 } 243 if (! PERMUTE) {446 if (!) { 244 447 /* 245 * if no permutation wanted, stop parsing246 * at first non-option 448 * f no permutation wanted, stop parsing 449 * at first non-option 247 450 */ 248 return -1;451 return ; 249 452 } 250 453 /* do permutation */ … … 264 467 if (nonopt_start != -1 && nonopt_end == -1) 265 468 nonopt_end = optind; 266 if (place[1] && *++place == '-') { /* found "--" */ 267 place++; 268 return -2; 269 } 270 } 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 271 518 if ((optchar = (int)*place++) == (int)':' || 272 (oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) { 273 /* option letter unknown or ':' */ 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); 274 528 if (!*place) 275 529 ++optind; 530 531 532 533 534 276 535 if (PRINT_ERROR) 277 536 warnx(illoptchar, optchar); 537 278 538 optopt = optchar; 279 return BADCH; 280 } 281 if (optchar == 'W' && oli[1] == ';') { /* -W long-option */ 282 /* XXX: what if no long options provided (called by getopt)? */ 283 if (*place) 284 return -2; 285 286 if (++optind >= nargc) { /* no arg */ 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 */ 287 546 place = EMSG; 288 547 if (PRINT_ERROR) 289 548 warnx(recargchar, optchar); 290 549 optopt = optchar; 291 return BADARG;550 return ; 292 551 } else /* white space */ 293 552 place = nargv[optind]; 294 /* 295 * Handle -W arg the same as --arg (which causes getopt to 296 * stop parsing). 297 */ 298 return -2; 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); 299 560 } 300 561 if (*++oli != ':') { /* doesn't take argument */ … … 312 573 warnx(recargchar, optchar); 313 574 optopt = optchar; 314 return BADARG;575 return ; 315 576 } else 316 577 optarg = nargv[optind]; 578 579 580 581 582 583 584 585 317 586 } 318 587 place = EMSG; … … 320 589 } 321 590 /* dump back option letter */ 322 return optchar;591 return ; 323 592 } 324 593 … … 328 597 * Parse argc/argv argument vector. 329 598 * 330 * [eventually this will replace the realgetopt]599 * [eventually this will replace the getopt] 331 600 */ 332 601 int 333 _STD(getopt)(nargc, nargv, options) 334 int nargc; 335 char * const *nargv; 336 const char *options; 602 _STD(getopt)(int nargc, char * const *nargv, const char *options) 337 603 { 338 int retval; 339 340 _DIAGASSERT(nargv != NULL); 341 _DIAGASSERT(options != NULL); 342 343 if ((retval = getopt_internal(nargc, nargv, options)) == -2) { 344 ++optind; 345 /* 346 * We found an option (--), so if we skipped non-options, 347 * we have to permute. 348 */ 349 if (nonopt_end != -1) { 350 permute_args(nonopt_start, nonopt_end, optind, 351 nargv); 352 optind -= nonopt_end - nonopt_start; 353 } 354 nonopt_start = nonopt_end = -1; 355 retval = -1; 356 } 357 return retval; 604 605 /* 606 * We don't pass FLAG_PERMUTE to getopt_internal() since 607 * the BSD getopt(3) (unlike GNU) has never done this. 608 * 609 * Furthermore, since many privileged programs call getopt() 610 * before dropping privileges it makes sense to keep things 611 * as simple (and bug-free) as possible. 612 */ 613 return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); 358 614 } 359 #endif 615 #endif 360 616 361 617 /* … … 364 620 */ 365 621 int 366 getopt_long(nargc, nargv, options, long_options, idx)622 (nargc, nargv, options, long_options, idx) 367 623 int nargc; 368 624 char * const *nargv; … … 371 627 int *idx; 372 628 { 373 int retval; 374 375 _DIAGASSERT(nargv != NULL); 376 _DIAGASSERT(options != NULL); 377 _DIAGASSERT(long_options != NULL); 378 /* idx may be NULL */ 379 380 if ((retval = getopt_internal(nargc, nargv, options)) == -2) { 381 char *current_argv, *has_equal; 382 size_t current_argv_len; 383 int i, match; 384 385 current_argv = place; 386 match = -1; 387 388 optind++; 389 place = EMSG; 390 391 if (*current_argv == '\0') { /* found "--" */ 392 /* 393 * We found an option (--), so if we skipped 394 * non-options, we have to permute. 395 */ 396 if (nonopt_end != -1) { 397 permute_args(nonopt_start, nonopt_end, 398 optind, nargv); 399 optind -= nonopt_end - nonopt_start; 400 } 401 nonopt_start = nonopt_end = -1; 402 return -1; 403 } 404 if ((has_equal = strchr(current_argv, '=')) != NULL) { 405 /* argument found (--option=arg) */ 406 current_argv_len = has_equal - current_argv; 407 has_equal++; 408 } else 409 current_argv_len = strlen(current_argv); 410 411 for (i = 0; long_options[i].name; i++) { 412 /* find matching long option */ 413 if (strncmp(current_argv, long_options[i].name, 414 current_argv_len)) 415 continue; 416 417 if (strlen(long_options[i].name) == 418 (unsigned)current_argv_len) { 419 /* exact match */ 420 match = i; 421 break; 422 } 423 if (match == -1) /* partial match */ 424 match = i; 425 else { 426 /* ambiguous abbreviation */ 427 if (PRINT_ERROR) 428 warnx(ambig, (int)current_argv_len, 429 current_argv); 430 optopt = 0; 431 return BADCH; 432 } 433 } 434 if (match != -1) { /* option found */ 435 if (long_options[match].has_arg == no_argument 436 && has_equal) { 437 if (PRINT_ERROR) 438 warnx(noarg, (int)current_argv_len, 439 current_argv); 440 /* 441 * XXX: GNU sets optopt to val regardless of 442 * flag 443 */ 444 if (long_options[match].flag == NULL) 445 optopt = long_options[match].val; 446 else 447 optopt = 0; 448 return BADARG; 449 } 450 if (long_options[match].has_arg == required_argument || 451 long_options[match].has_arg == optional_argument) { 452 if (has_equal) 453 optarg = has_equal; 454 else if (long_options[match].has_arg == 455 required_argument) { 456 /* 457 * optional argument doesn't use 458 * next nargv 459 */ 460 optarg = nargv[optind++]; 461 } 462 } 463 if ((long_options[match].has_arg == required_argument) 464 && (optarg == NULL)) { 465 /* 466 * Missing argument; leading ':' 467 * indicates no error should be generated 468 */ 469 if (PRINT_ERROR) 470 warnx(recargstring, current_argv); 471 /* 472 * XXX: GNU sets optopt to val regardless 473 * of flag 474 */ 475 if (long_options[match].flag == NULL) 476 optopt = long_options[match].val; 477 else 478 optopt = 0; 479 --optind; 480 return BADARG; 481 } 482 } else { /* unknown option */ 483 if (PRINT_ERROR) 484 warnx(illoptstring, current_argv); 485 optopt = 0; 486 return BADCH; 487 } 488 if (long_options[match].flag) { 489 *long_options[match].flag = long_options[match].val; 490 retval = 0; 491 } else 492 retval = long_options[match].val; 493 if (idx) 494 *idx = match; 495 } 496 return retval; 629 630 return (getopt_internal(nargc, nargv, options, long_options, idx, 631 FLAG_PERMUTE)); 497 632 } 498 #endif /* !GETOPT_LONG */ 633 634 /* 635 * getopt_long_only -- 636 * Parse argc/argv argument vector. 637 */ 638 int 639 _STD(getopt_long_only)(nargc, nargv, options, long_options, idx) 640 int nargc; 641 char * const *nargv; 642 const char *options; 643 const struct option *long_options; 644 int *idx; 645 { 646 647 return (getopt_internal(nargc, nargv, options, long_options, idx, 648 FLAG_PERMUTE|FLAG_LONGONLY)); 649 } -
Property cvs2svn:cvs-rev
changed from
Note:
See TracChangeset
for help on using the changeset viewer.
