1 /* Getopt for GNU. 2 Copyright (C) 1987-2018 Free Software Foundation, Inc. 3 This file is part of the GNU C Library and is also part of gnulib. 4 Patches to this file should be submitted to both projects. 5 6 The GNU C Library is free software; you can redistribute it and/or 7 modify it under the terms of the GNU General Public 8 License as published by the Free Software Foundation; either 9 version 3 of the License, or (at your option) any later version. 10 11 The GNU C Library is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public 17 License along with the GNU C Library; if not, see 18 <https://www.gnu.org/licenses/>. */ 19 20 #ifndef _LIBC 21 # include <config.h> 22 #endif 23 24 #include "getopt.h" 25 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <unistd.h> 30 31 #ifdef _LIBC 32 /* When used as part of glibc, error printing must be done differently 33 for standards compliance. getopt is not a cancellation point, so 34 it must not call functions that are, and it is specified by an 35 older standard than stdio locking, so it must not refer to 36 functions in the "user namespace" related to stdio locking. 37 Finally, it must use glibc's internal message translation so that 38 the messages are looked up in the proper text domain. */ 39 # include <libintl.h> 40 # define fprintf __fxprintf_nocancel 41 # define flockfile(fp) _IO_flockfile (fp) 42 # define funlockfile(fp) _IO_funlockfile (fp) 43 #else 44 # include "gettext.h" 45 # define _(msgid) gettext (msgid) 46 /* When used standalone, flockfile and funlockfile might not be 47 available. */ 48 # if (!defined _POSIX_THREAD_SAFE_FUNCTIONS \ 49 || (defined _WIN32 && ! defined __CYGWIN__)) 50 # define flockfile(fp) /* nop */ 51 # define funlockfile(fp) /* nop */ 52 # endif 53 /* When used standalone, do not attempt to use alloca. */ 54 # define __libc_use_alloca(size) 0 55 # undef alloca 56 # define alloca(size) (abort (), (void *)0) 57 #endif 58 59 /* This implementation of 'getopt' has three modes for handling 60 options interspersed with non-option arguments. It can stop 61 scanning for options at the first non-option argument encountered, 62 as POSIX specifies. It can continue scanning for options after the 63 first non-option argument, but permute 'argv' as it goes so that, 64 after 'getopt' is done, all the options precede all the non-option 65 arguments and 'optind' points to the first non-option argument. 66 Or, it can report non-option arguments as if they were arguments to 67 the option character '\x01'. 68 69 The default behavior of 'getopt_long' is to permute the argument list. 70 When this implementation is used standalone, the default behavior of 71 'getopt' is to stop at the first non-option argument, but when it is 72 used as part of GNU libc it also permutes the argument list. In both 73 cases, setting the environment variable POSIXLY_CORRECT to any value 74 disables permutation. 75 76 If the first character of the OPTSTRING argument to 'getopt' or 77 'getopt_long' is '+', both functions will stop at the first 78 non-option argument. If it is '-', both functions will report 79 non-option arguments as arguments to the option character '\x01'. */ 80 81 #include "getopt_int.h" 82 83 /* For communication from 'getopt' to the caller. 84 When 'getopt' finds an option that takes an argument, 85 the argument value is returned here. 86 Also, when 'ordering' is RETURN_IN_ORDER, 87 each non-option ARGV-element is returned here. */ 88 89 char *optarg; 90 91 /* Index in ARGV of the next element to be scanned. 92 This is used for communication to and from the caller 93 and for communication between successive calls to 'getopt'. 94 95 On entry to 'getopt', zero means this is the first call; initialize. 96 97 When 'getopt' returns -1, this is the index of the first of the 98 non-option elements that the caller should itself scan. 99 100 Otherwise, 'optind' communicates from one call to the next 101 how much of ARGV has been scanned so far. */ 102 103 /* 1003.2 says this must be 1 before any call. */ 104 int optind = 1; 105 106 /* Callers store zero here to inhibit the error message 107 for unrecognized options. */ 108 109 int opterr = 1; 110 111 /* Set to an option character which was unrecognized. 112 This must be initialized on some systems to avoid linking in the 113 system's own getopt implementation. */ 114 115 int optopt = '?'; 116 117 /* Keep a global copy of all internal members of getopt_data. */ 118 119 static struct _getopt_data getopt_data; 120 121 /* Exchange two adjacent subsequences of ARGV. 122 One subsequence is elements [first_nonopt,last_nonopt) 123 which contains all the non-options that have been skipped so far. 124 The other is elements [last_nonopt,optind), which contains all 125 the options processed since those non-options were skipped. 126 127 'first_nonopt' and 'last_nonopt' are relocated so that they describe 128 the new indices of the non-options in ARGV after they are moved. */ 129 130 static void 131 exchange (char **argv, struct _getopt_data *d) 132 { 133 int bottom = d->__first_nonopt; 134 int middle = d->__last_nonopt; 135 int top = d->optind; 136 char *tem; 137 138 /* Exchange the shorter segment with the far end of the longer segment. 139 That puts the shorter segment into the right place. 140 It leaves the longer segment in the right place overall, 141 but it consists of two parts that need to be swapped next. */ 142 143 while (top > middle && middle > bottom) 144 { 145 if (top - middle > middle - bottom) 146 { 147 /* Bottom segment is the short one. */ 148 int len = middle - bottom; 149 int i; 150 151 /* Swap it with the top part of the top segment. */ 152 for (i = 0; i < len; i++) 153 { 154 tem = argv[bottom + i]; 155 argv[bottom + i] = argv[top - (middle - bottom) + i]; 156 argv[top - (middle - bottom) + i] = tem; 157 } 158 /* Exclude the moved bottom segment from further swapping. */ 159 top -= len; 160 } 161 else 162 { 163 /* Top segment is the short one. */ 164 int len = top - middle; 165 int i; 166 167 /* Swap it with the bottom part of the bottom segment. */ 168 for (i = 0; i < len; i++) 169 { 170 tem = argv[bottom + i]; 171 argv[bottom + i] = argv[middle + i]; 172 argv[middle + i] = tem; 173 } 174 /* Exclude the moved top segment from further swapping. */ 175 bottom += len; 176 } 177 } 178 179 /* Update records for the slots the non-options now occupy. */ 180 181 d->__first_nonopt += (d->optind - d->__last_nonopt); 182 d->__last_nonopt = d->optind; 183 } 184 185 /* Process the argument starting with d->__nextchar as a long option. 186 d->optind should *not* have been advanced over this argument. 187 188 If the value returned is -1, it was not actually a long option, the 189 state is unchanged, and the argument should be processed as a set 190 of short options (this can only happen when long_only is true). 191 Otherwise, the option (and its argument, if any) have been consumed 192 and the return value is the value to return from _getopt_internal_r. */ 193 static int 194 process_long_option (int argc, char **argv, const char *optstring, 195 const struct option *longopts, int *longind, 196 int long_only, struct _getopt_data *d, 197 int print_errors, const char *prefix) 198 { 199 char *nameend; 200 size_t namelen; 201 const struct option *p; 202 const struct option *pfound = NULL; 203 int n_options; 204 int option_index; 205 206 for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++) 207 /* Do nothing. */ ; 208 namelen = nameend - d->__nextchar; 209 210 /* First look for an exact match, counting the options as a side 211 effect. */ 212 for (p = longopts, n_options = 0; p->name; p++, n_options++) 213 if (!strncmp (p->name, d->__nextchar, namelen) 214 && namelen == strlen (p->name)) 215 { 216 /* Exact match found. */ 217 pfound = p; 218 option_index = n_options; 219 break; 220 } 221 222 if (pfound == NULL) 223 { 224 /* Didn't find an exact match, so look for abbreviations. */ 225 unsigned char *ambig_set = NULL; 226 int ambig_malloced = 0; 227 int ambig_fallback = 0; 228 int indfound = -1; 229 230 for (p = longopts, option_index = 0; p->name; p++, option_index++) 231 if (!strncmp (p->name, d->__nextchar, namelen)) 232 { 233 if (pfound == NULL) 234 { 235 /* First nonexact match found. */ 236 pfound = p; 237 indfound = option_index; 238 } 239 else if (long_only 240 || pfound->has_arg != p->has_arg 241 || pfound->flag != p->flag 242 || pfound->val != p->val) 243 { 244 /* Second or later nonexact match found. */ 245 if (!ambig_fallback) 246 { 247 if (!print_errors) 248 /* Don't waste effort tracking the ambig set if 249 we're not going to print it anyway. */ 250 ambig_fallback = 1; 251 else if (!ambig_set) 252 { 253 if (__libc_use_alloca (n_options)) 254 ambig_set = alloca (n_options); 255 else if ((ambig_set = malloc (n_options)) == NULL) 256 /* Fall back to simpler error message. */ 257 ambig_fallback = 1; 258 else 259 ambig_malloced = 1; 260 261 if (ambig_set) 262 { 263 memset (ambig_set, 0, n_options); 264 ambig_set[indfound] = 1; 265 } 266 } 267 if (ambig_set) 268 ambig_set[option_index] = 1; 269 } 270 } 271 } 272 273 if (ambig_set || ambig_fallback) 274 { 275 if (print_errors) 276 { 277 if (ambig_fallback) 278 fprintf (stderr, _("%s: option '%s%s' is ambiguous\n"), 279 argv[0], prefix, d->__nextchar); 280 else 281 { 282 flockfile (stderr); 283 fprintf (stderr, 284 _("%s: option '%s%s' is ambiguous; possibilities:"), 285 argv[0], prefix, d->__nextchar); 286 287 for (option_index = 0; option_index < n_options; option_index++) 288 if (ambig_set[option_index]) 289 fprintf (stderr, " '%s%s'", 290 prefix, longopts[option_index].name); 291 292 /* This must use 'fprintf' even though it's only 293 printing a single character, so that it goes through 294 __fxprintf_nocancel when compiled as part of glibc. */ 295 fprintf (stderr, "\n"); 296 funlockfile (stderr); 297 } 298 } 299 if (ambig_malloced) 300 free (ambig_set); 301 d->__nextchar += strlen (d->__nextchar); 302 d->optind++; 303 d->optopt = 0; 304 return '?'; 305 } 306 307 option_index = indfound; 308 } 309 310 if (pfound == NULL) 311 { 312 /* Can't find it as a long option. If this is not getopt_long_only, 313 or the option starts with '--' or is not a valid short option, 314 then it's an error. */ 315 if (!long_only || argv[d->optind][1] == '-' 316 || strchr (optstring, *d->__nextchar) == NULL) 317 { 318 if (print_errors) 319 fprintf (stderr, _("%s: unrecognized option '%s%s'\n"), 320 argv[0], prefix, d->__nextchar); 321 322 d->__nextchar = NULL; 323 d->optind++; 324 d->optopt = 0; 325 return '?'; 326 } 327 328 /* Otherwise interpret it as a short option. */ 329 return -1; 330 } 331 332 /* We have found a matching long option. Consume it. */ 333 d->optind++; 334 d->__nextchar = NULL; 335 if (*nameend) 336 { 337 /* Don't test has_arg with >, because some C compilers don't 338 allow it to be used on enums. */ 339 if (pfound->has_arg) 340 d->optarg = nameend + 1; 341 else 342 { 343 if (print_errors) 344 fprintf (stderr, 345 _("%s: option '%s%s' doesn't allow an argument\n"), 346 argv[0], prefix, pfound->name); 347 348 d->optopt = pfound->val; 349 return '?'; 350 } 351 } 352 else if (pfound->has_arg == 1) 353 { 354 if (d->optind < argc) 355 d->optarg = argv[d->optind++]; 356 else 357 { 358 if (print_errors) 359 fprintf (stderr, 360 _("%s: option '%s%s' requires an argument\n"), 361 argv[0], prefix, pfound->name); 362 363 d->optopt = pfound->val; 364 return optstring[0] == ':' ? ':' : '?'; 365 } 366 } 367 368 if (longind != NULL) 369 *longind = option_index; 370 if (pfound->flag) 371 { 372 *(pfound->flag) = pfound->val; 373 return 0; 374 } 375 return pfound->val; 376 } 377 378 /* Initialize internal data upon the first call to getopt. */ 379 380 static const char * 381 _getopt_initialize (int argc _GL_UNUSED, 382 char **argv _GL_UNUSED, const char *optstring, 383 struct _getopt_data *d, int posixly_correct) 384 { 385 /* Start processing options with ARGV-element 1 (since ARGV-element 0 386 is the program name); the sequence of previously skipped 387 non-option ARGV-elements is empty. */ 388 if (d->optind == 0) 389 d->optind = 1; 390 391 d->__first_nonopt = d->__last_nonopt = d->optind; 392 d->__nextchar = NULL; 393 394 /* Determine how to handle the ordering of options and nonoptions. */ 395 if (optstring[0] == '-') 396 { 397 d->__ordering = RETURN_IN_ORDER; 398 ++optstring; 399 } 400 else if (optstring[0] == '+') 401 { 402 d->__ordering = REQUIRE_ORDER; 403 ++optstring; 404 } 405 else if (posixly_correct || !!getenv ("POSIXLY_CORRECT")) 406 d->__ordering = REQUIRE_ORDER; 407 else 408 d->__ordering = PERMUTE; 409 410 d->__initialized = 1; 411 return optstring; 412 } 413 414 /* Scan elements of ARGV (whose length is ARGC) for option characters 415 given in OPTSTRING. 416 417 If an element of ARGV starts with '-', and is not exactly "-" or "--", 418 then it is an option element. The characters of this element 419 (aside from the initial '-') are option characters. If 'getopt' 420 is called repeatedly, it returns successively each of the option characters 421 from each of the option elements. 422 423 If 'getopt' finds another option character, it returns that character, 424 updating 'optind' and 'nextchar' so that the next call to 'getopt' can 425 resume the scan with the following option character or ARGV-element. 426 427 If there are no more option characters, 'getopt' returns -1. 428 Then 'optind' is the index in ARGV of the first ARGV-element 429 that is not an option. (The ARGV-elements have been permuted 430 so that those that are not options now come last.) 431 432 OPTSTRING is a string containing the legitimate option characters. 433 If an option character is seen that is not listed in OPTSTRING, 434 return '?' after printing an error message. If you set 'opterr' to 435 zero, the error message is suppressed but we still return '?'. 436 437 If a char in OPTSTRING is followed by a colon, that means it wants an arg, 438 so the following text in the same ARGV-element, or the text of the following 439 ARGV-element, is returned in 'optarg'. Two colons mean an option that 440 wants an optional arg; if there is text in the current ARGV-element, 441 it is returned in 'optarg', otherwise 'optarg' is set to zero. 442 443 If OPTSTRING starts with '-' or '+', it requests different methods of 444 handling the non-option ARGV-elements. 445 See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. 446 447 Long-named options begin with '--' instead of '-'. 448 Their names may be abbreviated as long as the abbreviation is unique 449 or is an exact match for some defined option. If they have an 450 argument, it follows the option name in the same ARGV-element, separated 451 from the option name by a '=', or else the in next ARGV-element. 452 When 'getopt' finds a long-named option, it returns 0 if that option's 453 'flag' field is nonzero, the value of the option's 'val' field 454 if the 'flag' field is zero. 455 456 The elements of ARGV aren't really const, because we permute them. 457 But we pretend they're const in the prototype to be compatible 458 with other systems. 459 460 LONGOPTS is a vector of 'struct option' terminated by an 461 element containing a name which is zero. 462 463 LONGIND returns the index in LONGOPT of the long-named option found. 464 It is only valid when a long-named option has been found by the most 465 recent call. 466 467 If LONG_ONLY is nonzero, '-' as well as '--' can introduce 468 long-named options. */ 469 470 int 471 _getopt_internal_r (int argc, char **argv, const char *optstring, 472 const struct option *longopts, int *longind, 473 int long_only, struct _getopt_data *d, int posixly_correct) 474 { 475 int print_errors = d->opterr; 476 477 if (argc < 1) 478 return -1; 479 480 d->optarg = NULL; 481 482 if (d->optind == 0 || !d->__initialized) 483 optstring = _getopt_initialize (argc, argv, optstring, d, posixly_correct); 484 else if (optstring[0] == '-' || optstring[0] == '+') 485 optstring++; 486 487 if (optstring[0] == ':') 488 print_errors = 0; 489 490 /* Test whether ARGV[optind] points to a non-option argument. */ 491 #define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0') 492 493 if (d->__nextchar == NULL || *d->__nextchar == '\0') 494 { 495 /* Advance to the next ARGV-element. */ 496 497 /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been 498 moved back by the user (who may also have changed the arguments). */ 499 if (d->__last_nonopt > d->optind) 500 d->__last_nonopt = d->optind; 501 if (d->__first_nonopt > d->optind) 502 d->__first_nonopt = d->optind; 503 504 if (d->__ordering == PERMUTE) 505 { 506 /* If we have just processed some options following some non-options, 507 exchange them so that the options come first. */ 508 509 if (d->__first_nonopt != d->__last_nonopt 510 && d->__last_nonopt != d->optind) 511 exchange (argv, d); 512 else if (d->__last_nonopt != d->optind) 513 d->__first_nonopt = d->optind; 514 515 /* Skip any additional non-options 516 and extend the range of non-options previously skipped. */ 517 518 while (d->optind < argc && NONOPTION_P) 519 d->optind++; 520 d->__last_nonopt = d->optind; 521 } 522 523 /* The special ARGV-element '--' means premature end of options. 524 Skip it like a null option, 525 then exchange with previous non-options as if it were an option, 526 then skip everything else like a non-option. */ 527 528 if (d->optind != argc && !strcmp (argv[d->optind], "--")) 529 { 530 d->optind++; 531 532 if (d->__first_nonopt != d->__last_nonopt 533 && d->__last_nonopt != d->optind) 534 exchange (argv, d); 535 else if (d->__first_nonopt == d->__last_nonopt) 536 d->__first_nonopt = d->optind; 537 d->__last_nonopt = argc; 538 539 d->optind = argc; 540 } 541 542 /* If we have done all the ARGV-elements, stop the scan 543 and back over any non-options that we skipped and permuted. */ 544 545 if (d->optind == argc) 546 { 547 /* Set the next-arg-index to point at the non-options 548 that we previously skipped, so the caller will digest them. */ 549 if (d->__first_nonopt != d->__last_nonopt) 550 d->optind = d->__first_nonopt; 551 return -1; 552 } 553 554 /* If we have come to a non-option and did not permute it, 555 either stop the scan or describe it to the caller and pass it by. */ 556 557 if (NONOPTION_P) 558 { 559 if (d->__ordering == REQUIRE_ORDER) 560 return -1; 561 d->optarg = argv[d->optind++]; 562 return 1; 563 } 564 565 /* We have found another option-ARGV-element. 566 Check whether it might be a long option. */ 567 if (longopts) 568 { 569 if (argv[d->optind][1] == '-') 570 { 571 /* "--foo" is always a long option. The special option 572 "--" was handled above. */ 573 d->__nextchar = argv[d->optind] + 2; 574 return process_long_option (argc, argv, optstring, longopts, 575 longind, long_only, d, 576 print_errors, "--"); 577 } 578 579 /* If long_only and the ARGV-element has the form "-f", 580 where f is a valid short option, don't consider it an 581 abbreviated form of a long option that starts with f. 582 Otherwise there would be no way to give the -f short 583 option. 584 585 On the other hand, if there's a long option "fubar" and 586 the ARGV-element is "-fu", do consider that an 587 abbreviation of the long option, just like "--fu", and 588 not "-f" with arg "u". 589 590 This distinction seems to be the most useful approach. */ 591 if (long_only && (argv[d->optind][2] 592 || !strchr (optstring, argv[d->optind][1]))) 593 { 594 int code; 595 d->__nextchar = argv[d->optind] + 1; 596 code = process_long_option (argc, argv, optstring, longopts, 597 longind, long_only, d, 598 print_errors, "-"); 599 if (code != -1) 600 return code; 601 } 602 } 603 604 /* It is not a long option. Skip the initial punctuation. */ 605 d->__nextchar = argv[d->optind] + 1; 606 } 607 608 /* Look at and handle the next short option-character. */ 609 610 { 611 char c = *d->__nextchar++; 612 const char *temp = strchr (optstring, c); 613 614 /* Increment 'optind' when we start to process its last character. */ 615 if (*d->__nextchar == '\0') 616 ++d->optind; 617 618 if (temp == NULL || c == ':' || c == ';') 619 { 620 if (print_errors) 621 fprintf (stderr, _("%s: invalid option -- '%c'\n"), argv[0], c); 622 d->optopt = c; 623 return '?'; 624 } 625 626 /* Convenience. Treat POSIX -W foo same as long option --foo */ 627 if (temp[0] == 'W' && temp[1] == ';' && longopts != NULL) 628 { 629 /* This is an option that requires an argument. */ 630 if (*d->__nextchar != '\0') 631 d->optarg = d->__nextchar; 632 else if (d->optind == argc) 633 { 634 if (print_errors) 635 fprintf (stderr, 636 _("%s: option requires an argument -- '%c'\n"), 637 argv[0], c); 638 639 d->optopt = c; 640 if (optstring[0] == ':') 641 c = ':'; 642 else 643 c = '?'; 644 return c; 645 } 646 else 647 d->optarg = argv[d->optind]; 648 649 d->__nextchar = d->optarg; 650 d->optarg = NULL; 651 return process_long_option (argc, argv, optstring, longopts, longind, 652 0 /* long_only */, d, print_errors, "-W "); 653 } 654 if (temp[1] == ':') 655 { 656 if (temp[2] == ':') 657 { 658 /* This is an option that accepts an argument optionally. */ 659 if (*d->__nextchar != '\0') 660 { 661 d->optarg = d->__nextchar; 662 d->optind++; 663 } 664 else 665 d->optarg = NULL; 666 d->__nextchar = NULL; 667 } 668 else 669 { 670 /* This is an option that requires an argument. */ 671 if (*d->__nextchar != '\0') 672 { 673 d->optarg = d->__nextchar; 674 /* If we end this ARGV-element by taking the rest as an arg, 675 we must advance to the next element now. */ 676 d->optind++; 677 } 678 else if (d->optind == argc) 679 { 680 if (print_errors) 681 fprintf (stderr, 682 _("%s: option requires an argument -- '%c'\n"), 683 argv[0], c); 684 685 d->optopt = c; 686 if (optstring[0] == ':') 687 c = ':'; 688 else 689 c = '?'; 690 } 691 else 692 /* We already incremented 'optind' once; 693 increment it again when taking next ARGV-elt as argument. */ 694 d->optarg = argv[d->optind++]; 695 d->__nextchar = NULL; 696 } 697 } 698 return c; 699 } 700 } 701 702 int 703 _getopt_internal (int argc, char **argv, const char *optstring, 704 const struct option *longopts, int *longind, int long_only, 705 int posixly_correct) 706 { 707 int result; 708 709 getopt_data.optind = optind; 710 getopt_data.opterr = opterr; 711 712 result = _getopt_internal_r (argc, argv, optstring, longopts, 713 longind, long_only, &getopt_data, 714 posixly_correct); 715 716 optind = getopt_data.optind; 717 optarg = getopt_data.optarg; 718 optopt = getopt_data.optopt; 719 720 return result; 721 } 722 723 /* glibc gets a LSB-compliant getopt and a POSIX-complaint __posix_getopt. 724 Standalone applications just get a POSIX-compliant getopt. 725 POSIX and LSB both require these functions to take 'char *const *argv' 726 even though this is incorrect (because of the permutation). */ 727 #define GETOPT_ENTRY(NAME, POSIXLY_CORRECT) \ 728 int \ 729 NAME (int argc, char *const *argv, const char *optstring) \ 730 { \ 731 return _getopt_internal (argc, (char **)argv, optstring, \ 732 0, 0, 0, POSIXLY_CORRECT); \ 733 } 734 735 #ifdef _LIBC 736 GETOPT_ENTRY(getopt, 0) 737 GETOPT_ENTRY(__posix_getopt, 1) 738 #else 739 GETOPT_ENTRY(getopt, 1) 740 #endif 741 742 743 #ifdef TEST 744 745 /* Compile with -DTEST to make an executable for use in testing 746 the above definition of 'getopt'. */ 747 748 int 749 main (int argc, char **argv) 750 { 751 int c; 752 int digit_optind = 0; 753 754 while (1) 755 { 756 int this_option_optind = optind ? optind : 1; 757 758 c = getopt (argc, argv, "abc:d:0123456789"); 759 if (c == -1) 760 break; 761 762 switch (c) 763 { 764 case '0': 765 case '1': 766 case '2': 767 case '3': 768 case '4': 769 case '5': 770 case '6': 771 case '7': 772 case '8': 773 case '9': 774 if (digit_optind != 0 && digit_optind != this_option_optind) 775 printf ("digits occur in two different argv-elements.\n"); 776 digit_optind = this_option_optind; 777 printf ("option %c\n", c); 778 break; 779 780 case 'a': 781 printf ("option a\n"); 782 break; 783 784 case 'b': 785 printf ("option b\n"); 786 break; 787 788 case 'c': 789 printf ("option c with value '%s'\n", optarg); 790 break; 791 792 case '?': 793 break; 794 795 default: 796 printf ("?? getopt returned character code 0%o ??\n", c); 797 } 798 } 799 800 if (optind < argc) 801 { 802 printf ("non-option ARGV-elements: "); 803 while (optind < argc) 804 printf ("%s ", argv[optind++]); 805 printf ("\n"); 806 } 807 808 exit (0); 809 } 810 811 #endif /* TEST */ 812