1 /* This file is from getopt of glibc 2.2.2 2 * And it is modified for TiMidity++ support at 01/19, 2002 3 * by Masanao Izumo <mo@goice.co.jp>. 4 */ 5 6 #ifdef HAVE_CONFIG_H 7 #include "config.h" 8 #endif /* HAVE_CONFIG_H */ 9 10 #if !defined(HAVE_GETOPT_LONG) || !defined(HAVE_GETOPT) 11 12 #include <stdio.h> 13 #include <stdlib.h> 14 #ifdef HAVE_UNISTD_H 15 #include <unistd.h> 16 #endif /* HAVE_UNISTD_H */ 17 #include <string.h> 18 19 #include "tmdy_getopt.h" 20 21 #ifndef HAVE_GETOPT 22 char *optarg; 23 int optind = 1; 24 int opterr = 1; 25 int optopt = '?'; 26 #endif /* HAVE_GETOPT */ 27 28 static enum 29 { 30 REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER 31 } ordering; 32 33 static int __getopt_initialized; 34 static char *nextchar; 35 static char *posixly_correct; 36 static int first_nonopt; 37 static int last_nonopt; 38 39 40 # define SWAP_FLAGS(ch1, ch2) 41 42 43 /* Exchange two adjacent subsequences of ARGV. 44 One subsequence is elements [first_nonopt,last_nonopt) 45 which contains all the non-options that have been skipped so far. 46 The other is elements [last_nonopt,optind), which contains all 47 the options processed since those non-options were skipped. 48 49 `first_nonopt' and `last_nonopt' are relocated so that they describe 50 the new indices of the non-options in ARGV after they are moved. */ 51 static void 52 exchange (char **argv) 53 { 54 int bottom = first_nonopt; 55 int middle = last_nonopt; 56 int top = optind; 57 char *tem; 58 59 /* Exchange the shorter segment with the far end of the longer segment. 60 That puts the shorter segment into the right place. 61 It leaves the longer segment in the right place overall, 62 but it consists of two parts that need to be swapped next. */ 63 64 while (top > middle && middle > bottom) 65 { 66 if (top - middle > middle - bottom) 67 { 68 /* Bottom segment is the short one. */ 69 int len = middle - bottom; 70 register int i; 71 72 /* Swap it with the top part of the top segment. */ 73 for (i = 0; i < len; i++) 74 { 75 tem = argv[bottom + i]; 76 argv[bottom + i] = argv[top - (middle - bottom) + i]; 77 argv[top - (middle - bottom) + i] = tem; 78 SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); 79 } 80 /* Exclude the moved bottom segment from further swapping. */ 81 top -= len; 82 } 83 else 84 { 85 /* Top segment is the short one. */ 86 int len = top - middle; 87 register int i; 88 89 /* Swap it with the bottom part of the bottom segment. */ 90 for (i = 0; i < len; i++) 91 { 92 tem = argv[bottom + i]; 93 argv[bottom + i] = argv[middle + i]; 94 argv[middle + i] = tem; 95 SWAP_FLAGS (bottom + i, middle + i); 96 } 97 /* Exclude the moved top segment from further swapping. */ 98 bottom += len; 99 } 100 } 101 102 /* Update records for the slots the non-options now occupy. */ 103 104 first_nonopt += (optind - last_nonopt); 105 last_nonopt = optind; 106 } 107 108 109 /* Initialize the internal data when the first call is made. */ 110 static const char * 111 _getopt_initialize (int argc, char *const*argv, const char *optstring) 112 { 113 /* Start processing options with ARGV-element 1 (since ARGV-element 0 114 is the program name); the sequence of previously skipped 115 non-option ARGV-elements is empty. */ 116 117 first_nonopt = last_nonopt = optind; 118 119 nextchar = NULL; 120 121 posixly_correct = getenv ("POSIXLY_CORRECT"); 122 123 /* Determine how to handle the ordering of options and nonoptions. */ 124 125 if (optstring[0] == '-') 126 { 127 ordering = RETURN_IN_ORDER; 128 ++optstring; 129 } 130 else if (optstring[0] == '+') 131 { 132 ordering = REQUIRE_ORDER; 133 ++optstring; 134 } 135 else if (posixly_correct != NULL) 136 ordering = REQUIRE_ORDER; 137 else 138 ordering = PERMUTE; 139 140 return optstring; 141 } 142 143 /* Scan elements of ARGV (whose length is ARGC) for option characters 144 given in OPTSTRING. 145 146 If an element of ARGV starts with '-', and is not exactly "-" or "--", 147 then it is an option element. The characters of this element 148 (aside from the initial '-') are option characters. If `getopt' 149 is called repeatedly, it returns successively each of the option characters 150 from each of the option elements. 151 152 If `getopt' finds another option character, it returns that character, 153 updating `optind' and `nextchar' so that the next call to `getopt' can 154 resume the scan with the following option character or ARGV-element. 155 156 If there are no more option characters, `getopt' returns -1. 157 Then `optind' is the index in ARGV of the first ARGV-element 158 that is not an option. (The ARGV-elements have been permuted 159 so that those that are not options now come last.) 160 161 OPTSTRING is a string containing the legitimate option characters. 162 If an option character is seen that is not listed in OPTSTRING, 163 return '?' after printing an error message. If you set `opterr' to 164 zero, the error message is suppressed but we still return '?'. 165 166 If a char in OPTSTRING is followed by a colon, that means it wants an arg, 167 so the following text in the same ARGV-element, or the text of the following 168 ARGV-element, is returned in `optarg'. Two colons mean an option that 169 wants an optional arg; if there is text in the current ARGV-element, 170 it is returned in `optarg', otherwise `optarg' is set to zero. 171 172 If OPTSTRING starts with `-' or `+', it requests different methods of 173 handling the non-option ARGV-elements. 174 See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. 175 176 Long-named options begin with `--' instead of `-'. 177 Their names may be abbreviated as long as the abbreviation is unique 178 or is an exact match for some defined option. If they have an 179 argument, it follows the option name in the same ARGV-element, separated 180 from the option name by a `=', or else the in next ARGV-element. 181 When `getopt' finds a long-named option, it returns 0 if that option's 182 `flag' field is nonzero, the value of the option's `val' field 183 if the `flag' field is zero. 184 185 The elements of ARGV aren't really const, because we permute them. 186 But we pretend they're const in the prototype to be compatible 187 with other systems. 188 189 LONGOPTS is a vector of `struct option' terminated by an 190 element containing a name which is zero. 191 192 LONGIND returns the index in LONGOPT of the long-named option found. 193 It is only valid when a long-named option has been found by the most 194 recent call. 195 196 If LONG_ONLY is nonzero, '-' as well as '--' can introduce 197 long-named options. */ 198 199 static int 200 _getopt_internal (int argc, char *const*argv, const char *optstring, 201 const struct option *longopts, int *longind, int long_only) 202 { 203 int print_errors = opterr; 204 if (optstring[0] == ':') 205 print_errors = 0; 206 207 if (argc < 1) 208 return -1; 209 210 optarg = NULL; 211 212 if (optind == 0 || !__getopt_initialized) 213 { 214 if (optind == 0) 215 optind = 1; /* Don't scan ARGV[0], the program name. */ 216 optstring = _getopt_initialize (argc, argv, optstring); 217 __getopt_initialized = 1; 218 } 219 220 /* Test whether ARGV[optind] points to a non-option argument. 221 Either it does not have option syntax, or there is an environment flag 222 from the shell indicating it is not an option. The later information 223 is only used when the used in the GNU libc. */ 224 # define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') 225 226 if (nextchar == NULL || *nextchar == '\0') 227 { 228 /* Advance to the next ARGV-element. */ 229 230 /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been 231 moved back by the user (who may also have changed the arguments). */ 232 if (last_nonopt > optind) 233 last_nonopt = optind; 234 if (first_nonopt > optind) 235 first_nonopt = optind; 236 237 if (ordering == PERMUTE) 238 { 239 /* If we have just processed some options following some non-options, 240 exchange them so that the options come first. */ 241 242 if (first_nonopt != last_nonopt && last_nonopt != optind) 243 exchange ((char **) argv); 244 else if (last_nonopt != optind) 245 first_nonopt = optind; 246 247 /* Skip any additional non-options 248 and extend the range of non-options previously skipped. */ 249 250 while (optind < argc && NONOPTION_P) 251 optind++; 252 last_nonopt = optind; 253 } 254 255 /* The special ARGV-element `--' means premature end of options. 256 Skip it like a null option, 257 then exchange with previous non-options as if it were an option, 258 then skip everything else like a non-option. */ 259 260 if (optind != argc && !strcmp (argv[optind], "--")) 261 { 262 optind++; 263 264 if (first_nonopt != last_nonopt && last_nonopt != optind) 265 exchange ((char **) argv); 266 else if (first_nonopt == last_nonopt) 267 first_nonopt = optind; 268 last_nonopt = argc; 269 270 optind = argc; 271 } 272 273 /* If we have done all the ARGV-elements, stop the scan 274 and back over any non-options that we skipped and permuted. */ 275 276 if (optind == argc) 277 { 278 /* Set the next-arg-index to point at the non-options 279 that we previously skipped, so the caller will digest them. */ 280 if (first_nonopt != last_nonopt) 281 optind = first_nonopt; 282 return -1; 283 } 284 285 /* If we have come to a non-option and did not permute it, 286 either stop the scan or describe it to the caller and pass it by. */ 287 288 if (NONOPTION_P) 289 { 290 if (ordering == REQUIRE_ORDER) 291 return -1; 292 optarg = argv[optind++]; 293 return 1; 294 } 295 296 /* We have found another option-ARGV-element. 297 Skip the initial punctuation. */ 298 299 nextchar = (argv[optind] + 1 300 + (longopts != NULL && argv[optind][1] == '-')); 301 } 302 303 /* Decode the current option-ARGV-element. */ 304 305 /* Check whether the ARGV-element is a long option. 306 307 If long_only and the ARGV-element has the form "-f", where f is 308 a valid short option, don't consider it an abbreviated form of 309 a long option that starts with f. Otherwise there would be no 310 way to give the -f short option. 311 312 On the other hand, if there's a long option "fubar" and 313 the ARGV-element is "-fu", do consider that an abbreviation of 314 the long option, just like "--fu", and not "-f" with arg "u". 315 316 This distinction seems to be the most useful approach. */ 317 318 if (longopts != NULL 319 && (argv[optind][1] == '-' 320 || (long_only && (argv[optind][2] || !strchr (optstring, argv[optind][1]))))) 321 { 322 char *nameend; 323 const struct option *p; 324 const struct option *pfound = NULL; 325 int exact = 0; 326 int ambig = 0; 327 int indfound = -1; 328 int option_index; 329 330 for (nameend = nextchar; *nameend && *nameend != '='; nameend++) 331 /* Do nothing. */ ; 332 333 /* Test all long options for either exact match 334 or abbreviated matches. */ 335 for (p = longopts, option_index = 0; p->name; p++, option_index++) 336 if (!strncmp (p->name, nextchar, nameend - nextchar)) 337 { 338 if ((unsigned int) (nameend - nextchar) 339 == (unsigned int) strlen (p->name)) 340 { 341 /* Exact match found. */ 342 pfound = p; 343 indfound = option_index; 344 exact = 1; 345 break; 346 } 347 else if (pfound == NULL) 348 { 349 /* First nonexact match found. */ 350 pfound = p; 351 indfound = option_index; 352 } 353 else if (long_only 354 || pfound->has_arg != p->has_arg 355 || pfound->flag != p->flag 356 || pfound->val != p->val) 357 /* Second or later nonexact match found. */ 358 ambig = 1; 359 } 360 361 if (ambig && !exact) 362 { 363 if (print_errors) 364 fprintf (stderr, "%s: option `%s' is ambiguous\n", 365 argv[0], argv[optind]); 366 nextchar += strlen (nextchar); 367 optind++; 368 optopt = 0; 369 return '?'; 370 } 371 372 if (pfound != NULL) 373 { 374 option_index = indfound; 375 optind++; 376 if (*nameend) 377 { 378 /* Don't test has_arg with >, because some C compilers don't 379 allow it to be used on enums. */ 380 if (pfound->has_arg) 381 optarg = nameend + 1; 382 else 383 { 384 if (print_errors) 385 { 386 if (argv[optind - 1][1] == '-') 387 /* --option */ 388 fprintf (stderr, 389 "%s: option `--%s' doesn't allow an argument\n", 390 argv[0], pfound->name); 391 else 392 /* +option or -option */ 393 fprintf (stderr, 394 "%s: option `%c%s' doesn't allow an argument\n", 395 argv[0], argv[optind - 1][0], pfound->name); 396 } 397 398 nextchar += strlen (nextchar); 399 400 optopt = pfound->val; 401 return '?'; 402 } 403 } 404 else if (pfound->has_arg == 1) 405 { 406 if (optind < argc) 407 optarg = argv[optind++]; 408 else 409 { 410 if (print_errors) 411 fprintf (stderr, 412 "%s: option `%s' requires an argument\n", 413 argv[0], argv[optind - 1]); 414 nextchar += strlen (nextchar); 415 optopt = pfound->val; 416 return optstring[0] == ':' ? ':' : '?'; 417 } 418 } 419 nextchar += strlen (nextchar); 420 if (longind != NULL) 421 *longind = option_index; 422 if (pfound->flag) 423 { 424 *(pfound->flag) = pfound->val; 425 return 0; 426 } 427 return pfound->val; 428 } 429 430 /* Can't find it as a long option. If this is not getopt_long_only, 431 or the option starts with '--' or is not a valid short 432 option, then it's an error. 433 Otherwise interpret it as a short option. */ 434 if (!long_only || argv[optind][1] == '-' 435 || strchr (optstring, *nextchar) == NULL) 436 { 437 if (print_errors) 438 { 439 if (argv[optind][1] == '-') 440 /* --option */ 441 fprintf (stderr, "%s: unrecognized option `--%s'\n", 442 argv[0], nextchar); 443 else 444 /* +option or -option */ 445 fprintf (stderr, "%s: unrecognized option `%c%s'\n", 446 argv[0], argv[optind][0], nextchar); 447 } 448 nextchar = (char *) ""; 449 optind++; 450 optopt = 0; 451 return '?'; 452 } 453 } 454 455 /* Look at and handle the next short option-character. */ 456 457 { 458 char c = *nextchar++; 459 char *temp = strchr (optstring, c); 460 461 /* Increment `optind' when we start to process its last character. */ 462 if (*nextchar == '\0') 463 ++optind; 464 465 if (temp == NULL || c == ':') 466 { 467 if (print_errors) 468 { 469 if (posixly_correct) 470 /* 1003.2 specifies the format of this message. */ 471 fprintf (stderr, "%s: illegal option -- %c\n", 472 argv[0], c); 473 else 474 fprintf (stderr, "%s: invalid option -- %c\n", 475 argv[0], c); 476 } 477 optopt = c; 478 return '?'; 479 } 480 /* Convenience. Treat POSIX -W foo same as long option --foo */ 481 if (temp[0] == 'W' && temp[1] == ';') 482 { 483 char *nameend; 484 const struct option *p; 485 const struct option *pfound = NULL; 486 int exact = 0; 487 int ambig = 0; 488 int indfound = 0; 489 int option_index; 490 491 /* This is an option that requires an argument. */ 492 if (*nextchar != '\0') 493 { 494 optarg = nextchar; 495 /* If we end this ARGV-element by taking the rest as an arg, 496 we must advance to the next element now. */ 497 optind++; 498 } 499 else if (optind == argc) 500 { 501 if (print_errors) 502 { 503 /* 1003.2 specifies the format of this message. */ 504 fprintf (stderr, "%s: option requires an argument -- %c\n", 505 argv[0], c); 506 } 507 optopt = c; 508 if (optstring[0] == ':') 509 c = ':'; 510 else 511 c = '?'; 512 return c; 513 } 514 else 515 /* We already incremented `optind' once; 516 increment it again when taking next ARGV-elt as argument. */ 517 optarg = argv[optind++]; 518 519 /* optarg is now the argument, see if it's in the 520 table of longopts. */ 521 522 for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) 523 /* Do nothing. */ ; 524 525 /* Test all long options for either exact match 526 or abbreviated matches. */ 527 for (p = longopts, option_index = 0; p->name; p++, option_index++) 528 if (!strncmp (p->name, nextchar, nameend - nextchar)) 529 { 530 if ((unsigned int) (nameend - nextchar) == strlen (p->name)) 531 { 532 /* Exact match found. */ 533 pfound = p; 534 indfound = option_index; 535 exact = 1; 536 break; 537 } 538 else if (pfound == NULL) 539 { 540 /* First nonexact match found. */ 541 pfound = p; 542 indfound = option_index; 543 } 544 else 545 /* Second or later nonexact match found. */ 546 ambig = 1; 547 } 548 if (ambig && !exact) 549 { 550 if (print_errors) 551 fprintf (stderr, "%s: option `-W %s' is ambiguous\n", 552 argv[0], argv[optind]); 553 nextchar += strlen (nextchar); 554 optind++; 555 return '?'; 556 } 557 if (pfound != NULL) 558 { 559 option_index = indfound; 560 if (*nameend) 561 { 562 /* Don't test has_arg with >, because some C compilers don't 563 allow it to be used on enums. */ 564 if (pfound->has_arg) 565 optarg = nameend + 1; 566 else 567 { 568 if (print_errors) 569 fprintf (stderr, "\ 570 %s: option `-W %s' doesn't allow an argument\n", 571 argv[0], pfound->name); 572 573 nextchar += strlen (nextchar); 574 return '?'; 575 } 576 } 577 else if (pfound->has_arg == 1) 578 { 579 if (optind < argc) 580 optarg = argv[optind++]; 581 else 582 { 583 if (print_errors) 584 fprintf (stderr, 585 "%s: option `%s' requires an argument\n", 586 argv[0], argv[optind - 1]); 587 nextchar += strlen (nextchar); 588 return optstring[0] == ':' ? ':' : '?'; 589 } 590 } 591 nextchar += strlen (nextchar); 592 if (longind != NULL) 593 *longind = option_index; 594 if (pfound->flag) 595 { 596 *(pfound->flag) = pfound->val; 597 return 0; 598 } 599 return pfound->val; 600 } 601 nextchar = NULL; 602 return 'W'; /* Let the application handle it. */ 603 } 604 if (temp[1] == ':') 605 { 606 if (temp[2] == ':') 607 { 608 /* This is an option that accepts an argument optionally. */ 609 if (*nextchar != '\0') 610 { 611 optarg = nextchar; 612 optind++; 613 } 614 else 615 optarg = NULL; 616 nextchar = NULL; 617 } 618 else 619 { 620 /* This is an option that requires an argument. */ 621 if (*nextchar != '\0') 622 { 623 optarg = nextchar; 624 /* If we end this ARGV-element by taking the rest as an arg, 625 we must advance to the next element now. */ 626 optind++; 627 } 628 else if (optind == argc) 629 { 630 if (print_errors) 631 { 632 /* 1003.2 specifies the format of this message. */ 633 fprintf (stderr, 634 "%s: option requires an argument -- %c\n", 635 argv[0], c); 636 } 637 optopt = c; 638 if (optstring[0] == ':') 639 c = ':'; 640 else 641 c = '?'; 642 } 643 else 644 /* We already incremented `optind' once; 645 increment it again when taking next ARGV-elt as argument. */ 646 optarg = argv[optind++]; 647 nextchar = NULL; 648 } 649 } 650 return c; 651 } 652 } 653 654 #ifndef HAVE_GETOPT_LONG 655 int 656 getopt_long (int argc, char *const *argv, const char *options, 657 const struct option *long_options, int *opt_index) 658 { 659 return _getopt_internal (argc, argv, options, long_options, opt_index, 0); 660 } 661 662 /* Like getopt_long, but '-' as well as '--' can indicate a long option. 663 If an option that starts with '-' (not '--') doesn't match a long option, 664 but does match a short option, it is parsed as a short option 665 instead. */ 666 667 int 668 getopt_long_only (int argc, char *const *argv, const char *options, 669 const struct option *long_options, int *opt_index) 670 { 671 return _getopt_internal (argc, argv, options, long_options, opt_index, 1); 672 } 673 #endif 674 675 #ifndef HAVE_GETOPT 676 int 677 getopt (int argc, char *const *argv, const char *optstring) 678 { 679 return _getopt_internal (argc, argv, optstring, 680 (const struct option *) 0, 681 (int *) 0, 682 0); 683 } 684 #endif 685 686 #endif 687