| /* Getopt for GNU. |
| Copyright (C) 1987 Free Software Foundation, Inc. |
| |
| NO WARRANTY |
| |
| BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY |
| NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT |
| WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, |
| RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS" |
| WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, |
| BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
| FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY |
| AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE |
| DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR |
| CORRECTION. |
| |
| IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M. |
| STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY |
| WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE |
| LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR |
| OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE |
| USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR |
| DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR |
| A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS |
| PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH |
| DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. |
| |
| GENERAL PUBLIC LICENSE TO COPY |
| |
| 1. You may copy and distribute verbatim copies of this source file |
| as you receive it, in any medium, provided that you conspicuously and |
| appropriately publish on each copy a valid copyright notice "Copyright |
| (C) 1987 Free Software Foundation, Inc."; and include following the |
| copyright notice a verbatim copy of the above disclaimer of warranty |
| and of this License. You may charge a distribution fee for the |
| physical act of transferring a copy. |
| |
| 2. You may modify your copy or copies of this source file or |
| any portion of it, and copy and distribute such modifications under |
| the terms of Paragraph 1 above, provided that you also do the following: |
| |
| a) cause the modified files to carry prominent notices stating |
| that you changed the files and the date of any change; and |
| |
| b) cause the whole of any work that you distribute or publish, |
| that in whole or in part contains or is a derivative of this |
| program or any part thereof, to be licensed at no charge to all |
| third parties on terms identical to those contained in this |
| License Agreement (except that you may choose to grant more |
| extensive warranty protection to third parties, at your option). |
| |
| c) You may charge a distribution fee for the physical act of |
| transferring a copy, and you may at your option offer warranty |
| protection in exchange for a fee. |
| |
| 3. You may copy and distribute this program or any portion of it in |
| compiled, executable or object code form under the terms of Paragraphs |
| 1 and 2 above provided that you do the following: |
| |
| a) cause each such copy to be accompanied by the |
| corresponding machine-readable source code, which must |
| be distributed under the terms of Paragraphs 1 and 2 above; or, |
| |
| b) cause each such copy to be accompanied by a |
| written offer, with no time limit, to give any third party |
| free (except for a nominal shipping charge) a machine readable |
| copy of the corresponding source code, to be distributed |
| under the terms of Paragraphs 1 and 2 above; or, |
| |
| c) in the case of a recipient of this program in compiled, executable |
| or object code form (without the corresponding source code) you |
| shall cause copies you distribute to be accompanied by a copy |
| of the written offer of source code which you received along |
| with the copy you received. |
| |
| 4. You may not copy, sublicense, distribute or transfer this program |
| except as expressly provided under this License Agreement. Any attempt |
| otherwise to copy, sublicense, distribute or transfer this program is void and |
| your rights to use the program under this License agreement shall be |
| automatically terminated. However, parties who have received computer |
| software programs from you with this License Agreement will not have |
| their licenses terminated so long as such parties remain in full compliance. |
| |
| 5. If you wish to incorporate parts of this program into other free |
| programs whose distribution conditions are different, write to the Free |
| Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet |
| worked out a simple rule that can be stated here, but we will often permit |
| this. We will be guided by the two goals of preserving the free status of |
| all derivatives of our free software and of promoting the sharing and reuse of |
| software. |
| |
| |
| In other words, you are welcome to use, share and improve this program. |
| You are forbidden to forbid anyone else to use, share and improve |
| what you give them. Help stamp out software-hoarding! */ |
| |
| /* This version of `getopt' appears to the caller like standard Unix `getopt' |
| but it behaves differently for the user, since it allows the user |
| to intersperse the options with the other arguments. |
| |
| As `getopt' works, it permutes the elements of `argv' so that, |
| when it is done, all the options precede everything else. Thus |
| all application programs are extended to handle flexible argument order. |
| |
| Setting the environment variable _POSIX_OPTION_ORDER disables permutation. |
| Then the behavior is completely standard. |
| |
| GNU application programs can use a third alternative mode in which |
| they can distinguish the relative order of options and other arguments. */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #ifdef sparc |
| #include <alloca.h> |
| #endif |
| |
| #define alloca1(x) malloc(x) |
| #ifndef bcopy |
| #define bcopy(src, dst, num) memcpy((dst), (src), (num)) |
| #endif |
| |
| /* For communication from `getopt' to the caller. |
| When `getopt' finds an option that takes an argument, |
| the argument value is returned here. |
| Also, when `ordering' is RETURN_IN_ORDER, |
| each non-option ARGV-element is returned here. */ |
| |
| char *optarg = 0; |
| |
| /* Index in ARGV of the next element to be scanned. |
| This is used for communication to and from the caller |
| and for communication between successive calls to `getopt'. |
| |
| On entry to `getopt', zero means this is the first call; initialize. |
| |
| When `getopt' returns EOF, this is the index of the first of the |
| non-option elements that the caller should itself scan. |
| |
| Otherwise, `optind' communicates from one call to the next |
| how much of ARGV has been scanned so far. */ |
| |
| int optind = 0; |
| |
| /* The next char to be scanned in the option-element |
| in which the last option character we returned was found. |
| This allows us to pick up the scan where we left off. |
| |
| If this is zero, or a null string, it means resume the scan |
| by advancing to the next ARGV-element. */ |
| |
| static char *nextchar; |
| |
| /* Callers store zero here to inhibit the error message |
| for unrecognized options. */ |
| |
| int opterr = 1; |
| |
| /* Describe how to deal with options that follow non-option ARGV-elements. |
| |
| UNSPECIFIED means the caller did not specify anything; |
| the default is then REQUIRE_ORDER if the environment variable |
| _OPTIONS_FIRST is defined, PERMUTE otherwise. |
| |
| REQUIRE_ORDER means don't recognize them as options. |
| Stop option processing when the first non-option is seen. |
| This is what Unix does. |
| |
| PERMUTE is the default. We permute the contents of `argv' as we scan, |
| so that eventually all the options are at the end. This allows options |
| to be given in any order, even with programs that were not written to |
| expect this. |
| |
| RETURN_IN_ORDER is an option available to programs that were written |
| to expect options and other ARGV-elements in any order and that care about |
| the ordering of the two. We describe each non-option ARGV-element |
| as if it were the argument of an option with character code zero. |
| Using `-' as the first character of the list of option characters |
| requests this mode of operation. |
| |
| The special argument `--' forces an end of option-scanning regardless |
| of the value of `ordering'. In the case of RETURN_IN_ORDER, only |
| `--' can cause `getopt' to return EOF with `optind' != ARGC. */ |
| |
| static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering; |
| |
| /* Handle permutation of arguments. */ |
| |
| /* Describe the part of ARGV that contains non-options that have |
| been skipped. `first_nonopt' is the index in ARGV of the first of them; |
| `last_nonopt' is the index after the last of them. */ |
| |
| static int first_nonopt; |
| static int last_nonopt; |
| |
| /* Exchange two adjacent subsequences of ARGV. |
| One subsequence is elements [first_nonopt,last_nonopt) |
| which contains all the non-options that have been skipped so far. |
| The other is elements [last_nonopt,optind), which contains all |
| the options processed since those non-options were skipped. |
| |
| `first_nonopt' and `last_nonopt' are relocated so that they describe |
| the new indices of the non-options in ARGV after they are moved. */ |
| |
| static void exchange(char **argv) |
| { |
| int nonopts_size |
| = (last_nonopt - first_nonopt) * sizeof (char *); |
| char **temp = (char **) alloca1 (nonopts_size); |
| |
| /* Interchange the two blocks of data in argv. */ |
| |
| bcopy (&argv[first_nonopt], temp, nonopts_size); |
| bcopy (&argv[last_nonopt], &argv[first_nonopt], |
| (optind - last_nonopt) * sizeof (char *)); |
| bcopy (temp, &argv[first_nonopt + optind - last_nonopt], |
| nonopts_size); |
| |
| /* Update records for the slots the non-options now occupy. */ |
| |
| first_nonopt += (optind - last_nonopt); |
| last_nonopt = optind; |
| } |
| |
| /* Scan elements of ARGV (whose length is ARGC) for option characters |
| given in OPTSTRING. |
| |
| If an element of ARGV starts with '-', and is not exactly "-" or "--", |
| then it is an option element. The characters of this element |
| (aside from the initial '-') are option characters. If `getopt' |
| is called repeatedly, it returns successively each of theoption characters |
| from each of the option elements. |
| |
| If `getopt' finds another option character, it returns that character, |
| updating `optind' and `nextchar' so that the next call to `getopt' can |
| resume the scan with the following option character or ARGV-element. |
| |
| If there are no more option characters, `getopt' returns `EOF'. |
| Then `optind' is the index in ARGV of the first ARGV-element |
| that is not an option. (The ARGV-elements have been permuted |
| so that those that are not options now come last.) |
| |
| OPTSTRING is a string containing the legitimate option characters. |
| A colon in OPTSTRING means that the previous character is an option |
| that wants an argument. The argument is taken from the rest of the |
| current ARGV-element, or from the following ARGV-element, |
| and returned in `optarg'. |
| |
| If an option character is seen that is not listed in OPTSTRING, |
| return '?' after printing an error message. If you set `opterr' to |
| zero, the error message is suppressed but we still return '?'. |
| |
| If a char in OPTSTRING is followed by a colon, that means it wants an arg, |
| so the following text in the same ARGV-element, or the text of the following |
| ARGV-element, is returned in `optarg. Two colons mean an option that |
| wants an optional arg; if there is text in the current ARGV-element, |
| it is returned in `optarg'. |
| |
| If OPTSTRING starts with `-', it requests a different method of handling the |
| non-option ARGV-elements. See the comments about RETURN_IN_ORDER, above. |
| */ |
| |
| #ifndef __sun__ |
| int getopt(int argc,char **argv,char *optstring) |
| { |
| /* Initialize the internal data when the first call is made. |
| Start processing options with ARGV-element 1 (since ARGV-element 0 |
| is the program name); the sequence of previously skipped |
| non-option ARGV-elements is empty. */ |
| |
| if (optind == 0) |
| { |
| first_nonopt = last_nonopt = optind = 1; |
| |
| nextchar = 0; |
| |
| /* Determine how to handle the ordering of options and nonoptions. */ |
| |
| if (optstring[0] == '-') |
| ordering = RETURN_IN_ORDER; |
| else if (getenv ("_POSIX_OPTION_ORDER") != 0) |
| ordering = REQUIRE_ORDER; |
| else |
| ordering = PERMUTE; |
| } |
| |
| if (nextchar == 0 || *nextchar == 0) |
| { |
| if (ordering == PERMUTE) |
| { |
| /* If we have just processed some options following some non-options, |
| exchange them so that the options come first. */ |
| |
| if (first_nonopt != last_nonopt && last_nonopt != optind) |
| exchange (argv); |
| else if (last_nonopt != optind) |
| first_nonopt = optind; |
| |
| /* Now skip any additional non-options |
| and extend the range of non-options previously skipped. */ |
| |
| while (optind < argc |
| && (argv[optind][0] != '-' |
| || argv[optind][1] == 0)) |
| optind++; |
| last_nonopt = optind; |
| } |
| |
| /* Special ARGV-element `--' means premature end of options. |
| Skip it like a null option, |
| then exchange with previous non-options as if it were an option, |
| then skip everything else like a non-option. */ |
| |
| if (optind != argc && !strcmp (argv[optind], "--")) |
| { |
| optind++; |
| |
| if (first_nonopt != last_nonopt && last_nonopt != optind) |
| exchange (argv); |
| else if (first_nonopt == last_nonopt) |
| first_nonopt = optind; |
| last_nonopt = argc; |
| |
| optind = argc; |
| } |
| |
| /* If we have done all the ARGV-elements, stop the scan |
| and back over any non-options that we skipped and permuted. */ |
| |
| if (optind == argc) |
| { |
| /* Set the next-arg-index to point at the non-options |
| that we previously skipped, so the caller will digest them. */ |
| if (first_nonopt != last_nonopt) |
| optind = first_nonopt; |
| return EOF; |
| } |
| |
| /* If we have come to a non-option and did not permute it, |
| either stop the scan or describe it to the caller and pass it by. */ |
| |
| if (argv[optind][0] != '-' || argv[optind][1] == 0) |
| { |
| if (ordering == REQUIRE_ORDER) |
| return EOF; |
| optarg = argv[optind++]; |
| return 0; |
| } |
| |
| /* We have found another option-ARGV-element. |
| Start decoding its characters. */ |
| |
| nextchar = argv[optind] + 1; |
| } |
| |
| /* Look at and handle the next option-character. */ |
| |
| { |
| char c = *nextchar++; |
| |
| /* This is only supported with 'cc' |
| char *temp = (char *) index (optstring, c); |
| */ |
| |
| char *temp = strchr(optstring, (int) c); |
| |
| /* Increment `optind' when we start to process its last character. */ |
| if (*nextchar == 0) |
| optind++; |
| |
| if (temp == 0 || c == ':') |
| { |
| if (opterr != 0) |
| { |
| if (c < 040 || c >= 0177) |
| fprintf (stderr, "%s: unrecognized option, character code 0%o\n", |
| argv[0], c); |
| else |
| fprintf (stderr, "%s: unrecognized option `-%c'\n", |
| argv[0], c); |
| } |
| return '?'; |
| } |
| if (temp[1] == ':') |
| { |
| if (temp[2] == ':') |
| { |
| /* This is an option that accepts an argument optionally. */ |
| if (*nextchar != 0) |
| { |
| optarg = nextchar; |
| optind++; |
| } |
| else |
| optarg = 0; |
| nextchar = 0; |
| } |
| else |
| { |
| /* This is an option that requires an argument. */ |
| if (*nextchar != 0) |
| { |
| optarg = nextchar; |
| /* If we end this ARGV-element by taking the rest as an arg, |
| we must advance to the next element now. */ |
| optind++; |
| } |
| else if (optind == argc) |
| { |
| if (opterr != 0) |
| fprintf (stderr, "%s: no argument for `-%c' option\n", |
| argv[0], c); |
| optarg = 0; |
| } |
| else |
| /* We already incremented `optind' once; |
| increment it again when taking next ARGV-elt as argument. */ |
| optarg = argv[optind++]; |
| nextchar = 0; |
| } |
| } |
| return c; |
| } |
| } |
| #endif /* __sun__ */ |
| |
| #ifdef TEST |
| |
| /* Compile with -DTEST to make an executable for use in testing |
| the above definition of `getopt'. */ |
| |
| int main(int argc,char **argv) |
| { |
| char c; |
| int digit_optind = 0; |
| |
| while (1) |
| { |
| int this_option_optind = optind; |
| if ((c = getopt (argc, argv, "abc:d:0123456789")) == EOF) |
| break; |
| |
| switch (c) |
| { |
| case '0': |
| case '1': |
| case '2': |
| case '3': |
| case '4': |
| case '5': |
| case '6': |
| case '7': |
| case '8': |
| case '9': |
| if (digit_optind != 0 && digit_optind != this_option_optind) |
| printf ("digits occur in two different argv-elements.\n"); |
| digit_optind = this_option_optind; |
| printf ("option %c\n", c); |
| break; |
| |
| case 'a': |
| printf ("option a\n"); |
| break; |
| |
| case 'b': |
| printf ("option b\n"); |
| break; |
| |
| case 'c': |
| printf ("option c with value `%s'\n", optarg); |
| break; |
| |
| case '?': |
| break; |
| |
| default: |
| printf ("?? getopt returned character code 0%o ??\n", c); |
| } |
| } |
| |
| if (optind < argc) |
| { |
| printf ("non-option ARGV-elements: "); |
| while (optind < argc) |
| printf ("%s ", argv[optind++]); |
| printf ("\n"); |
| } |
| |
| return 0; |
| } |
| |
| #endif /* TEST */ |