1/* getopt for BASH.
2
3   Copyright (C) 1993, 1994
4   	Free Software Foundation, Inc.
5
6   This program is free software; you can redistribute it and/or modify it
7   under the terms of the GNU General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   This program 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
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with this program; if not, write to the Free Software
18   Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.  */
19
20#include <config.h>
21
22#if defined (HAVE_UNISTD_H)
23#  ifdef _MINIX
24#    include <sys/types.h>
25#  endif
26#  include <unistd.h>
27#endif
28
29#include <stdio.h>
30#include "memalloc.h"
31#include "../bashintl.h"
32#include "../shell.h"
33#include "getopt.h"
34
35/* For communication from `sh_getopt' to the caller.
36   When `sh_getopt' finds an option that takes an argument,
37   the argument value is returned here. */
38char *sh_optarg = 0;
39
40/* Index in ARGV of the next element to be scanned.
41   This is used for communication to and from the caller
42   and for communication between successive calls to `sh_getopt'.
43
44   On entry to `sh_getopt', zero means this is the first call; initialize.
45
46   When `sh_getopt' returns EOF, this is the index of the first of the
47   non-option elements that the caller should itself scan.
48
49   Otherwise, `sh_optind' communicates from one call to the next
50   how much of ARGV has been scanned so far.  */
51
52/* XXX 1003.2 says this must be 1 before any call.  */
53int sh_optind = 0;
54
55/* Index of the current argument. */
56static int sh_curopt;
57
58/* The next char to be scanned in the option-element
59   in which the last option character we returned was found.
60   This allows us to pick up the scan where we left off.
61
62   If this is zero, or a null string, it means resume the scan
63   by advancing to the next ARGV-element.  */
64
65static char *nextchar;
66static int sh_charindex;
67
68/* Callers store zero here to inhibit the error message
69   for unrecognized options.  */
70
71int sh_opterr = 1;
72
73/* Set to an option character which was unrecognized.
74   This must be initialized on some systems to avoid linking in the
75   system's own getopt implementation.  */
76
77int sh_optopt = '?';
78
79/* Set to 1 when we see an invalid option; public so getopts can reset it. */
80int sh_badopt = 0;
81
82/* Scan elements of ARGV (whose length is ARGC) for option characters
83   given in OPTSTRING.
84
85   If an element of ARGV starts with '-', and is not exactly "-" or "--",
86   then it is an option element.  The characters of this element
87   (aside from the initial '-') are option characters.  If `sh_getopt'
88   is called repeatedly, it returns successively each of the option characters
89   from each of the option elements.
90
91   If `sh_getopt' finds another option character, it returns that character,
92   updating `sh_optind' and `nextchar' so that the next call to `sh_getopt' can
93   resume the scan with the following option character or ARGV-element.
94
95   If there are no more option characters, `sh_getopt' returns `EOF'.
96   Then `sh_optind' is the index in ARGV of the first ARGV-element
97   that is not an option.
98
99   OPTSTRING is a string containing the legitimate option characters.
100   If an option character is seen that is not listed in OPTSTRING,
101   return '?' after printing an error message.  If you set `sh_opterr' to
102   zero, the error message is suppressed but we still return '?'.
103
104   If a char in OPTSTRING is followed by a colon, that means it wants an arg,
105   so the following text in the same ARGV-element, or the text of the following
106   ARGV-element, is returned in `sh_optarg'. */
107
108/* 1003.2 specifies the format of this message.  */
109#define BADOPT(x)  fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], x)
110#define NEEDARG(x) fprintf (stderr, _("%s: option requires an argument -- %c\n"), argv[0], x)
111
112int
113sh_getopt (argc, argv, optstring)
114     int argc;
115     char *const *argv;
116     const char *optstring;
117{
118  char c, *temp;
119
120  sh_optarg = 0;
121
122  if (sh_optind >= argc || sh_optind < 0)	/* XXX was sh_optind > argc */
123    {
124      sh_optind = argc;
125      return (EOF);
126    }
127
128  /* Initialize the internal data when the first call is made.
129     Start processing options with ARGV-element 1 (since ARGV-element 0
130     is the program name); the sequence of previously skipped
131     non-option ARGV-elements is empty.  */
132
133  if (sh_optind == 0)
134    {
135      sh_optind = 1;
136      nextchar = (char *)NULL;
137    }
138
139  if (nextchar == 0 || *nextchar == '\0')
140    {
141      /* If we have done all the ARGV-elements, stop the scan. */
142      if (sh_optind >= argc)
143	return EOF;
144
145      temp = argv[sh_optind];
146
147      /* Special ARGV-element `--' means premature end of options.
148	 Skip it like a null option, and return EOF. */
149      if (temp[0] == '-' && temp[1] == '-' && temp[2] == '\0')
150	{
151	  sh_optind++;
152	  return EOF;
153	}
154
155      /* If we have come to a non-option, either stop the scan or describe
156	 it to the caller and pass it by.  This makes the pseudo-option
157	 `-' mean the end of options, but does not skip over it. */
158      if (temp[0] != '-' || temp[1] == '\0')
159	return EOF;
160
161      /* We have found another option-ARGV-element.
162	 Start decoding its characters.  */
163      nextchar = argv[sh_curopt = sh_optind] + 1;
164      sh_charindex = 1;
165    }
166
167  /* Look at and handle the next option-character.  */
168
169  c = *nextchar++; sh_charindex++;
170  temp = strchr (optstring, c);
171
172  sh_optopt = c;
173
174  /* Increment `sh_optind' when we start to process its last character.  */
175  if (nextchar == 0 || *nextchar == '\0')
176    {
177      sh_optind++;
178      nextchar = (char *)NULL;
179    }
180
181  if (sh_badopt = (temp == NULL || c == ':'))
182    {
183      if (sh_opterr)
184	BADOPT (c);
185
186      return '?';
187    }
188
189  if (temp[1] == ':')
190    {
191      if (nextchar && *nextchar)
192	{
193	  /* This is an option that requires an argument.  */
194	  sh_optarg = nextchar;
195	  /* If we end this ARGV-element by taking the rest as an arg,
196	     we must advance to the next element now.  */
197	  sh_optind++;
198	}
199      else if (sh_optind == argc)
200	{
201	  if (sh_opterr)
202	    NEEDARG (c);
203
204	  sh_optopt = c;
205	  sh_optarg = "";	/* Needed by getopts. */
206	  c = (optstring[0] == ':') ? ':' : '?';
207	}
208      else
209	/* We already incremented `sh_optind' once;
210	   increment it again when taking next ARGV-elt as argument.  */
211	sh_optarg = argv[sh_optind++];
212      nextchar = (char *)NULL;
213    }
214  return c;
215}
216
217void
218sh_getopt_restore_state (argv)
219     char **argv;
220{
221  if (nextchar)
222    nextchar = argv[sh_curopt] + sh_charindex;
223}
224
225#if 0
226void
227sh_getopt_debug_restore_state (argv)
228     char **argv;
229{
230  if (nextchar && nextchar != argv[sh_curopt] + sh_charindex)
231    {
232      itrace("sh_getopt_debug_restore_state: resetting nextchar");
233      nextchar = argv[sh_curopt] + sh_charindex;
234    }
235}
236#endif
237
238#ifdef TEST
239
240/* Compile with -DTEST to make an executable for use in testing
241   the above definition of `sh_getopt'.  */
242
243int
244main (argc, argv)
245     int argc;
246     char **argv;
247{
248  int c;
249  int digit_sh_optind = 0;
250
251  while (1)
252    {
253      int this_option_sh_optind = sh_optind ? sh_optind : 1;
254
255      c = sh_getopt (argc, argv, "abc:d:0123456789");
256      if (c == EOF)
257	break;
258
259      switch (c)
260	{
261	case '0':
262	case '1':
263	case '2':
264	case '3':
265	case '4':
266	case '5':
267	case '6':
268	case '7':
269	case '8':
270	case '9':
271	  if (digit_sh_optind != 0 && digit_sh_optind != this_option_sh_optind)
272	    printf ("digits occur in two different argv-elements.\n");
273	  digit_sh_optind = this_option_sh_optind;
274	  printf ("option %c\n", c);
275	  break;
276
277	case 'a':
278	  printf ("option a\n");
279	  break;
280
281	case 'b':
282	  printf ("option b\n");
283	  break;
284
285	case 'c':
286	  printf ("option c with value `%s'\n", sh_optarg);
287	  break;
288
289	case '?':
290	  break;
291
292	default:
293	  printf ("?? sh_getopt returned character code 0%o ??\n", c);
294	}
295    }
296
297  if (sh_optind < argc)
298    {
299      printf ("non-option ARGV-elements: ");
300      while (sh_optind < argc)
301	printf ("%s ", argv[sh_optind++]);
302      printf ("\n");
303    }
304
305  exit (0);
306}
307
308#endif /* TEST */
309