1 /* This version of `getopt' appears to the caller like standard Unix getopt()
2 but it behaves differently for the user, since it allows the user
3 to intersperse the options with the other arguments.
5 As getopt() works, it permutes the elements of `argv' so that,
6 when it is done, all the options precede everything else. Thus
7 all application programs are extended to handle flexible argument order.
9 Setting the environment variable _POSIX_OPTION_ORDER disables permutation.
10 Then the behavior is completely standard.
12 GNU application programs can use a third alternative mode in which
13 they can distinguish the relative order of options and other arguments.
22 /* Note that on some systems, the header files above declare variables
23 for use with their native getopt facilities, and those variables have
24 the same names as we'd like to use. So we use things like optargx
25 instead of optarg to avoid the collision.
28 /* For communication from `getopt' to the caller.
29 When `getopt' finds an option that takes an argument,
30 the argument value is returned here.
32 static char *optargx = 0;
34 /* Index in ARGV of the next element to be scanned.
35 This is used for communication to and from the caller
36 and for communication between successive calls to getoptx().
38 On entry to getoptx(), zero means this is the first call; initialize.
40 When getoptx() returns EOF, this is the index of the first of the
41 non-option elements that the caller should itself scan.
43 Otherwise, `optindx' communicates from one call to the next
44 how much of ARGV has been scanned so far.
47 static int optindx = 0;
49 /* The next char to be scanned in the option-element
50 in which the last option character we returned was found.
51 This allows us to pick up the scan where we left off.
53 If this is zero, or a null string, it means resume the scan
54 by advancing to the next ARGV-element. */
56 static char *nextchar;
58 /* Callers store zero here to inhibit the error message
59 for unrecognized options.
64 /* Index in _GETOPT_LONG_OPTIONS of the long-named option actually found.
65 Only valid when a long-named option was found. */
67 static int option_index;
69 struct optionx * _getopt_long_options;
71 /* Handle permutation of arguments. */
73 /* Describe the part of ARGV that contains non-options that have
74 been skipped. `first_nonopt' is the index in ARGV of the first of them;
75 `last_nonopt' is the index after the last of them. */
77 static int first_nonopt;
78 static int last_nonopt;
80 /* Exchange two adjacent subsequences of ARGV.
81 One subsequence is elements [first_nonopt,last_nonopt)
82 which contains all the non-options that have been skipped so far.
83 The other is elements [last_nonopt,optindx), which contains all
84 the options processed since those non-options were skipped.
86 `first_nonopt' and `last_nonopt' are relocated so that they describe
87 the new indices of the non-options in ARGV after they are moved. */
90 exchange(char ** const argv) {
91 unsigned int const nonopts_size =
92 (last_nonopt - first_nonopt) * sizeof (char *);
93 char **temp = (char **) malloc (nonopts_size);
98 /* Interchange the two blocks of data in argv. */
100 bcopy (&argv[first_nonopt], temp, nonopts_size);
101 bcopy (&argv[last_nonopt], &argv[first_nonopt],
102 (optindx - last_nonopt) * sizeof (char *));
103 bcopy (temp, &argv[first_nonopt + optindx - last_nonopt],
106 /* Update records for the slots the non-options now occupy. */
108 first_nonopt += (optindx - last_nonopt);
109 last_nonopt = optindx;
114 /* Scan elements of ARGV (whose length is ARGC) for option characters
117 If an element of ARGV starts with '-', and is not exactly "-" or "--",
118 then it is an option element. The characters of this element
119 (aside from the initial '-') are option characters. If getoptx()
120 is called repeatedly, it returns successively each of the option characters
121 from each of the option elements.
123 If getoptx() finds another option character, it returns that character,
124 updating `optindx' and `nextchar' so that the next call to getoptx() can
125 resume the scan with the following option character or ARGV-element.
127 If there are no more option characters, getoptx() returns `EOF'.
128 Then `optindx' is the index in ARGV of the first ARGV-element
129 that is not an option. (The ARGV-elements have been permuted
130 so that those that are not options now come last.)
132 OPTSTRING is a string containing the legitimate option characters.
133 If an option character is seen that is not listed in OPTSTRING,
134 return '?' after printing an error message. If you set `opterrx' to
135 zero, the error message is suppressed but we still return '?'.
137 If a char in OPTSTRING is followed by a colon, that means it wants an arg,
138 so the following text in the same ARGV-element, or the text of the following
139 ARGV-element, is returned in `optargx'. Two colons mean an option that
140 wants an optional arg; if there is text in the current ARGV-element,
141 it is returned in `optargx', otherwise `optargx' is set to zero.
143 If OPTSTRING starts with `-', it requests a different method of handling the
144 non-option ARGV-elements. See the comments about RETURN_IN_ORDER, above.
146 Long-named options begin with `+' instead of `-'.
147 Their names may be abbreviated as long as the abbreviation is unique
148 or is an exact match for some defined option. If they have an
149 argument, it follows the option name in the same ARGV-element, separated
150 from the option name by a `=', or else the in next ARGV-element.
151 getoptx() returns 0 when it finds a long-named option. */
154 getoptx(int const argc,
156 const char * const optstring) {
160 /* Initialize the internal data when the first call is made.
161 Start processing options with ARGV-element 1 (since ARGV-element 0
162 is the program name); the sequence of previously skipped
163 non-option ARGV-elements is empty. */
167 first_nonopt = last_nonopt = optindx = 1;
173 if (nextchar == 0 || *nextchar == 0)
175 /* If we have just processed some options following some non-options,
176 exchange them so that the options come first. */
178 if (first_nonopt != last_nonopt && last_nonopt != optindx)
180 else if (last_nonopt != optindx)
181 first_nonopt = optindx;
183 /* Now skip any additional non-options
184 and extend the range of non-options previously skipped. */
186 while (optindx < argc
187 && (argv[optindx][0] != '-'|| argv[optindx][1] == 0)
188 && (argv[optindx][0] != '+'|| argv[optindx][1] == 0))
190 last_nonopt = optindx;
192 /* Special ARGV-element `--' means premature end of options.
193 Skip it like a null option,
194 then exchange with previous non-options as if it were an option,
195 then skip everything else like a non-option. */
197 if (optindx != argc && !strcmp (argv[optindx], "--"))
201 if (first_nonopt != last_nonopt && last_nonopt != optindx)
203 else if (first_nonopt == last_nonopt)
204 first_nonopt = optindx;
210 /* If we have done all the ARGV-elements, stop the scan
211 and back over any non-options that we skipped and permuted. */
215 /* Set the next-arg-index to point at the non-options
216 that we previously skipped, so the caller will digest them. */
217 if (first_nonopt != last_nonopt)
218 optindx = first_nonopt;
222 /* If we have come to a non-option and did not permute it,
223 either stop the scan or describe it to the caller and pass
227 if ((argv[optindx][0] != '-' || argv[optindx][1] == 0)
228 && (argv[optindx][0] != '+' || argv[optindx][1] == 0))
230 optargx = argv[optindx++];
234 /* We have found another option-ARGV-element.
235 Start decoding its characters. */
237 nextchar = argv[optindx] + 1;
240 if ((argv[optindx][0] == '+' || (argv[optindx][0] == '-'))
247 struct optionx * pfound;
250 while (*s && *s != '=') s++;
252 indfound = 0; /* quite compiler warning */
254 /* Test all options for either exact match or abbreviated matches. */
255 for (p = _getopt_long_options, option_index = 0, pfound = NULL;
258 if (!strncmp (p->name, nextchar, s - nextchar))
260 if ((unsigned int)(s - nextchar) == strlen (p->name))
262 /* Exact match found. */
264 indfound = option_index;
270 /* First nonexact match found. */
272 indfound = option_index;
275 /* Second nonexact match found. */
281 fprintf (stderr, "%s: option `%s' is ambiguous\n",
282 argv[0], argv[optindx]);
283 nextchar += strlen (nextchar);
289 option_index = indfound;
293 if (pfound->has_arg > 0)
298 "%s: option `%c%s' doesn't allow an argument\n",
299 argv[0], argv[optindx - 1][0], pfound->name);
300 nextchar += strlen (nextchar);
304 else if (pfound->has_arg)
307 optargx = argv[optindx++];
308 else if (pfound->has_arg != 2)
310 fprintf (stderr, "%s: option `%s' requires an argument\n",
311 argv[0], argv[optindx - 1]);
312 nextchar += strlen (nextchar);
316 nextchar += strlen (nextchar);
318 *(pfound->flag) = pfound->val;
321 if (argv[optindx][0] == '+' || index (optstring, *nextchar) == 0)
324 fprintf (stderr, "%s: unrecognized option `%c%s'\n",
325 argv[0], argv[optindx][0], nextchar);
326 nextchar += strlen (nextchar);
331 /* Look at and handle the next option-character. */
334 char c = *nextchar++;
335 char *temp = index (optstring, c);
337 /* Increment `optindx' when we start to process its last character. */
341 if (temp == 0 || c == ':')
345 if (c < 040 || c >= 0177)
346 fprintf (stderr, "%s: unrecognized option, "
347 "character code 0%o\n",
350 fprintf (stderr, "%s: unrecognized option `-%c'\n",
359 /* This is an option that accepts an argument optionally. */
371 /* This is an option that requires an argument. */
375 /* If we end this ARGV-element by taking the rest
376 as an arg, we must advance to the next element
381 else if (optindx == argc)
385 "%s: option `-%c' requires an argument\n",
390 /* We already incremented `optindx' once;
391 increment it again when taking next ARGV-elt as
394 optargx = argv[optindx++];
405 getopt_long_onlyx(int const argc,
407 const char * const options,
408 struct optionx * const long_options,
409 unsigned int * const opt_index,
411 int * const end_of_options,
412 const char ** const optarg_arg,
413 const char ** const unrecognized_option) {
418 _getopt_long_options = long_options;
419 rc = getoptx(argc, argv, options);
421 *opt_index = option_index;
424 *unrecognized_option = argv[optindx];
426 *unrecognized_option = NULL;
433 *optarg_arg = optargx;
438 getopt_argstart(void) {
439 /*----------------------------------------------------------------------------
440 This is a replacement for what traditional getopt does with global
443 You call this after getopt_long_onlyx() has returned "end of
445 -----------------------------------------------------------------------------*/
451 Copyright (C) 1987, 1989 Free Software Foundation, Inc.
453 This program is free software; you can redistribute it and/or modify
454 it under the terms of the GNU General Public License as published by
455 the Free Software Foundation; either version 1, or (at your option)
458 This program is distributed in the hope that it will be useful,
459 but WITHOUT ANY WARRANTY; without even the implied warranty of
460 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
461 GNU General Public License for more details.
463 You should have received a copy of the GNU General Public License
464 along with this program; if not, write to the Free Software
465 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.