xref: /386bsd/usr/src/usr.bin/tar/getopt.c (revision a2142627)
1 /* Getopt for GNU.
2    NOTE: getopt is now part of the C library, so if you don't know what
3    "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
4    before changing it!
5 
6    Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
7    	Free Software Foundation, Inc.
8 
9    This program is free software; you can redistribute it and/or modify it
10    under the terms of the GNU General Public License as published by the
11    Free Software Foundation; either version 2, or (at your option) any
12    later version.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
22 
23 /* NOTE!!!  AIX requires this to be the first thing in the file.
24    Do not put ANYTHING before it!  */
25 #if !defined (__GNUC__) && defined (_AIX)
26  #pragma alloca
27 #endif
28 
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32 
33 #ifdef __GNUC__
34 #define alloca __builtin_alloca
35 #else /* not __GNUC__ */
36 #if defined (HAVE_ALLOCA_H) || (defined(sparc) && (defined(sun) || (!defined(USG) && !defined(SVR4) && !defined(__svr4__))))
37 #include <alloca.h>
38 #else
39 #ifndef _AIX
40 char *alloca ();
41 #endif
42 #endif /* alloca.h */
43 #endif /* not __GNUC__ */
44 
45 #if !__STDC__ && !defined(const) && IN_GCC
46 #define const
47 #endif
48 
49 #include <stdio.h>
50 
51 /* This needs to come after some library #include
52    to get __GNU_LIBRARY__ defined.  */
53 #ifdef	__GNU_LIBRARY__
54 #undef	alloca
55 /* Don't include stdlib.h for non-GNU C libraries because some of them
56    contain conflicting prototypes for getopt.  */
57 #include <stdlib.h>
58 #else	/* Not GNU C library.  */
59 #define	__alloca	alloca
60 #endif	/* GNU C library.  */
61 
62 /* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a
63    long-named option.  Because this is not POSIX.2 compliant, it is
64    being phased out.  */
65 /* #define GETOPT_COMPAT */
66 
67 /* This version of `getopt' appears to the caller like standard Unix `getopt'
68    but it behaves differently for the user, since it allows the user
69    to intersperse the options with the other arguments.
70 
71    As `getopt' works, it permutes the elements of ARGV so that,
72    when it is done, all the options precede everything else.  Thus
73    all application programs are extended to handle flexible argument order.
74 
75    Setting the environment variable POSIXLY_CORRECT disables permutation.
76    Then the behavior is completely standard.
77 
78    GNU application programs can use a third alternative mode in which
79    they can distinguish the relative order of options and other arguments.  */
80 
81 #include "getopt.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 = 0;
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 EOF, 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 /* XXX 1003.2 says this must be 1 before any call.  */
104 int optind = 0;
105 
106 /* The next char to be scanned in the option-element
107    in which the last option character we returned was found.
108    This allows us to pick up the scan where we left off.
109 
110    If this is zero, or a null string, it means resume the scan
111    by advancing to the next ARGV-element.  */
112 
113 static char *nextchar;
114 
115 /* Callers store zero here to inhibit the error message
116    for unrecognized options.  */
117 
118 int opterr = 1;
119 
120 /* Set to an option character which was unrecognized.
121    This must be initialized on some systems to avoid linking in the
122    system's own getopt implementation.  */
123 
124 int optopt = '?';
125 
126 /* Describe how to deal with options that follow non-option ARGV-elements.
127 
128    If the caller did not specify anything,
129    the default is REQUIRE_ORDER if the environment variable
130    POSIXLY_CORRECT is defined, PERMUTE otherwise.
131 
132    REQUIRE_ORDER means don't recognize them as options;
133    stop option processing when the first non-option is seen.
134    This is what Unix does.
135    This mode of operation is selected by either setting the environment
136    variable POSIXLY_CORRECT, or using `+' as the first character
137    of the list of option characters.
138 
139    PERMUTE is the default.  We permute the contents of ARGV as we scan,
140    so that eventually all the non-options are at the end.  This allows options
141    to be given in any order, even with programs that were not written to
142    expect this.
143 
144    RETURN_IN_ORDER is an option available to programs that were written
145    to expect options and other ARGV-elements in any order and that care about
146    the ordering of the two.  We describe each non-option ARGV-element
147    as if it were the argument of an option with character code 1.
148    Using `-' as the first character of the list of option characters
149    selects this mode of operation.
150 
151    The special argument `--' forces an end of option-scanning regardless
152    of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
153    `--' can cause `getopt' to return EOF with `optind' != ARGC.  */
154 
155 static enum
156 {
157   REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
158 } ordering;
159 
160 #ifdef	__GNU_LIBRARY__
161 /* We want to avoid inclusion of string.h with non-GNU libraries
162    because there are many ways it can cause trouble.
163    On some systems, it contains special magic macros that don't work
164    in GCC.  */
165 #include <string.h>
166 #define	my_index	strchr
167 #define	my_bcopy(src, dst, n)	memcpy ((dst), (src), (n))
168 #else
169 
170 /* Avoid depending on library functions or files
171    whose names are inconsistent.  */
172 
173 char *getenv ();
174 
175 static char *
my_index(string,chr)176 my_index (string, chr)
177      char *string;
178      int chr;
179 {
180   while (*string)
181     {
182       if (*string == chr)
183 	return string;
184       string++;
185     }
186   return 0;
187 }
188 
189 static void
my_bcopy(from,to,size)190 my_bcopy (from, to, size)
191      char *from, *to;
192      int size;
193 {
194   int i;
195   for (i = 0; i < size; i++)
196     to[i] = from[i];
197 }
198 #endif				/* GNU C library.  */
199 
200 /* Handle permutation of arguments.  */
201 
202 /* Describe the part of ARGV that contains non-options that have
203    been skipped.  `first_nonopt' is the index in ARGV of the first of them;
204    `last_nonopt' is the index after the last of them.  */
205 
206 static int first_nonopt;
207 static int last_nonopt;
208 
209 /* Exchange two adjacent subsequences of ARGV.
210    One subsequence is elements [first_nonopt,last_nonopt)
211    which contains all the non-options that have been skipped so far.
212    The other is elements [last_nonopt,optind), which contains all
213    the options processed since those non-options were skipped.
214 
215    `first_nonopt' and `last_nonopt' are relocated so that they describe
216    the new indices of the non-options in ARGV after they are moved.  */
217 
218 static void
exchange(argv)219 exchange (argv)
220      char **argv;
221 {
222   int nonopts_size = (last_nonopt - first_nonopt) * sizeof (char *);
223   char **temp = (char **) __alloca (nonopts_size);
224 
225   /* Interchange the two blocks of data in ARGV.  */
226 
227   my_bcopy ((char *) &argv[first_nonopt], (char *) temp, nonopts_size);
228   my_bcopy ((char *) &argv[last_nonopt], (char *) &argv[first_nonopt],
229 	    (optind - last_nonopt) * sizeof (char *));
230   my_bcopy ((char *) temp,
231 	    (char *) &argv[first_nonopt + optind - last_nonopt],
232 	    nonopts_size);
233 
234   /* Update records for the slots the non-options now occupy.  */
235 
236   first_nonopt += (optind - last_nonopt);
237   last_nonopt = optind;
238 }
239 
240 /* Scan elements of ARGV (whose length is ARGC) for option characters
241    given in OPTSTRING.
242 
243    If an element of ARGV starts with '-', and is not exactly "-" or "--",
244    then it is an option element.  The characters of this element
245    (aside from the initial '-') are option characters.  If `getopt'
246    is called repeatedly, it returns successively each of the option characters
247    from each of the option elements.
248 
249    If `getopt' finds another option character, it returns that character,
250    updating `optind' and `nextchar' so that the next call to `getopt' can
251    resume the scan with the following option character or ARGV-element.
252 
253    If there are no more option characters, `getopt' returns `EOF'.
254    Then `optind' is the index in ARGV of the first ARGV-element
255    that is not an option.  (The ARGV-elements have been permuted
256    so that those that are not options now come last.)
257 
258    OPTSTRING is a string containing the legitimate option characters.
259    If an option character is seen that is not listed in OPTSTRING,
260    return '?' after printing an error message.  If you set `opterr' to
261    zero, the error message is suppressed but we still return '?'.
262 
263    If a char in OPTSTRING is followed by a colon, that means it wants an arg,
264    so the following text in the same ARGV-element, or the text of the following
265    ARGV-element, is returned in `optarg'.  Two colons mean an option that
266    wants an optional arg; if there is text in the current ARGV-element,
267    it is returned in `optarg', otherwise `optarg' is set to zero.
268 
269    If OPTSTRING starts with `-' or `+', it requests different methods of
270    handling the non-option ARGV-elements.
271    See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
272 
273    Long-named options begin with `--' instead of `-'.
274    Their names may be abbreviated as long as the abbreviation is unique
275    or is an exact match for some defined option.  If they have an
276    argument, it follows the option name in the same ARGV-element, separated
277    from the option name by a `=', or else the in next ARGV-element.
278    When `getopt' finds a long-named option, it returns 0 if that option's
279    `flag' field is nonzero, the value of the option's `val' field
280    if the `flag' field is zero.
281 
282    The elements of ARGV aren't really const, because we permute them.
283    But we pretend they're const in the prototype to be compatible
284    with other systems.
285 
286    LONGOPTS is a vector of `struct option' terminated by an
287    element containing a name which is zero.
288 
289    LONGIND returns the index in LONGOPT of the long-named option found.
290    It is only valid when a long-named option has been found by the most
291    recent call.
292 
293    If LONG_ONLY is nonzero, '-' as well as '--' can introduce
294    long-named options.  */
295 
296 int
_getopt_internal(argc,argv,optstring,longopts,longind,long_only)297 _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
298      int argc;
299      char *const *argv;
300      const char *optstring;
301      const struct option *longopts;
302      int *longind;
303      int long_only;
304 {
305   int option_index;
306 
307   optarg = 0;
308 
309   /* Initialize the internal data when the first call is made.
310      Start processing options with ARGV-element 1 (since ARGV-element 0
311      is the program name); the sequence of previously skipped
312      non-option ARGV-elements is empty.  */
313 
314   if (optind == 0)
315     {
316       first_nonopt = last_nonopt = optind = 1;
317 
318       nextchar = NULL;
319 
320       /* Determine how to handle the ordering of options and nonoptions.  */
321 
322       if (optstring[0] == '-')
323 	{
324 	  ordering = RETURN_IN_ORDER;
325 	  ++optstring;
326 	}
327       else if (optstring[0] == '+')
328 	{
329 	  ordering = REQUIRE_ORDER;
330 	  ++optstring;
331 	}
332       else if (getenv ("POSIXLY_CORRECT") != NULL)
333 	ordering = REQUIRE_ORDER;
334       else
335 	ordering = PERMUTE;
336     }
337 
338   if (nextchar == NULL || *nextchar == '\0')
339     {
340       if (ordering == PERMUTE)
341 	{
342 	  /* If we have just processed some options following some non-options,
343 	     exchange them so that the options come first.  */
344 
345 	  if (first_nonopt != last_nonopt && last_nonopt != optind)
346 	    exchange ((char **) argv);
347 	  else if (last_nonopt != optind)
348 	    first_nonopt = optind;
349 
350 	  /* Now skip any additional non-options
351 	     and extend the range of non-options previously skipped.  */
352 
353 	  while (optind < argc
354 		 && (argv[optind][0] != '-' || argv[optind][1] == '\0')
355 #ifdef GETOPT_COMPAT
356 		 && (longopts == NULL
357 		     || argv[optind][0] != '+' || argv[optind][1] == '\0')
358 #endif				/* GETOPT_COMPAT */
359 		 )
360 	    optind++;
361 	  last_nonopt = optind;
362 	}
363 
364       /* Special ARGV-element `--' means premature end of options.
365 	 Skip it like a null option,
366 	 then exchange with previous non-options as if it were an option,
367 	 then skip everything else like a non-option.  */
368 
369       if (optind != argc && !strcmp (argv[optind], "--"))
370 	{
371 	  optind++;
372 
373 	  if (first_nonopt != last_nonopt && last_nonopt != optind)
374 	    exchange ((char **) argv);
375 	  else if (first_nonopt == last_nonopt)
376 	    first_nonopt = optind;
377 	  last_nonopt = argc;
378 
379 	  optind = argc;
380 	}
381 
382       /* If we have done all the ARGV-elements, stop the scan
383 	 and back over any non-options that we skipped and permuted.  */
384 
385       if (optind == argc)
386 	{
387 	  /* Set the next-arg-index to point at the non-options
388 	     that we previously skipped, so the caller will digest them.  */
389 	  if (first_nonopt != last_nonopt)
390 	    optind = first_nonopt;
391 	  return EOF;
392 	}
393 
394       /* If we have come to a non-option and did not permute it,
395 	 either stop the scan or describe it to the caller and pass it by.  */
396 
397       if ((argv[optind][0] != '-' || argv[optind][1] == '\0')
398 #ifdef GETOPT_COMPAT
399 	  && (longopts == NULL
400 	      || argv[optind][0] != '+' || argv[optind][1] == '\0')
401 #endif				/* GETOPT_COMPAT */
402 	  )
403 	{
404 	  if (ordering == REQUIRE_ORDER)
405 	    return EOF;
406 	  optarg = argv[optind++];
407 	  return 1;
408 	}
409 
410       /* We have found another option-ARGV-element.
411 	 Start decoding its characters.  */
412 
413       nextchar = (argv[optind] + 1
414 		  + (longopts != NULL && argv[optind][1] == '-'));
415     }
416 
417   if (longopts != NULL
418       && ((argv[optind][0] == '-'
419 	   && (argv[optind][1] == '-' || long_only))
420 #ifdef GETOPT_COMPAT
421 	  || argv[optind][0] == '+'
422 #endif				/* GETOPT_COMPAT */
423 	  ))
424     {
425       const struct option *p;
426       char *s = nextchar;
427       int exact = 0;
428       int ambig = 0;
429       const struct option *pfound = NULL;
430       int indfound;
431 
432       while (*s && *s != '=')
433 	s++;
434 
435       /* Test all options for either exact match or abbreviated matches.  */
436       for (p = longopts, option_index = 0; p->name;
437 	   p++, option_index++)
438 	if (!strncmp (p->name, nextchar, s - nextchar))
439 	  {
440 	    if (s - nextchar == strlen (p->name))
441 	      {
442 		/* Exact match found.  */
443 		pfound = p;
444 		indfound = option_index;
445 		exact = 1;
446 		break;
447 	      }
448 	    else if (pfound == NULL)
449 	      {
450 		/* First nonexact match found.  */
451 		pfound = p;
452 		indfound = option_index;
453 	      }
454 	    else
455 	      /* Second nonexact match found.  */
456 	      ambig = 1;
457 	  }
458 
459       if (ambig && !exact)
460 	{
461 	  if (opterr)
462 	    fprintf (stderr, "%s: option `%s' is ambiguous\n",
463 		     argv[0], argv[optind]);
464 	  nextchar += strlen (nextchar);
465 	  optind++;
466 	  return '?';
467 	}
468 
469       if (pfound != NULL)
470 	{
471 	  option_index = indfound;
472 	  optind++;
473 	  if (*s)
474 	    {
475 	      /* Don't test has_arg with >, because some C compilers don't
476 		 allow it to be used on enums.  */
477 	      if (pfound->has_arg)
478 		optarg = s + 1;
479 	      else
480 		{
481 		  if (opterr)
482 		    {
483 		      if (argv[optind - 1][1] == '-')
484 			/* --option */
485 			fprintf (stderr,
486 				 "%s: option `--%s' doesn't allow an argument\n",
487 				 argv[0], pfound->name);
488 		      else
489 			/* +option or -option */
490 			fprintf (stderr,
491 			     "%s: option `%c%s' doesn't allow an argument\n",
492 			     argv[0], argv[optind - 1][0], pfound->name);
493 		    }
494 		  nextchar += strlen (nextchar);
495 		  return '?';
496 		}
497 	    }
498 	  else if (pfound->has_arg == 1)
499 	    {
500 	      if (optind < argc)
501 		optarg = argv[optind++];
502 	      else
503 		{
504 		  if (opterr)
505 		    fprintf (stderr, "%s: option `%s' requires an argument\n",
506 			     argv[0], argv[optind - 1]);
507 		  nextchar += strlen (nextchar);
508 		  return optstring[0] == ':' ? ':' : '?';
509 		}
510 	    }
511 	  nextchar += strlen (nextchar);
512 	  if (longind != NULL)
513 	    *longind = option_index;
514 	  if (pfound->flag)
515 	    {
516 	      *(pfound->flag) = pfound->val;
517 	      return 0;
518 	    }
519 	  return pfound->val;
520 	}
521       /* Can't find it as a long option.  If this is not getopt_long_only,
522 	 or the option starts with '--' or is not a valid short
523 	 option, then it's an error.
524 	 Otherwise interpret it as a short option.  */
525       if (!long_only || argv[optind][1] == '-'
526 #ifdef GETOPT_COMPAT
527 	  || argv[optind][0] == '+'
528 #endif				/* GETOPT_COMPAT */
529 	  || my_index (optstring, *nextchar) == NULL)
530 	{
531 	  if (opterr)
532 	    {
533 	      if (argv[optind][1] == '-')
534 		/* --option */
535 		fprintf (stderr, "%s: unrecognized option `--%s'\n",
536 			 argv[0], nextchar);
537 	      else
538 		/* +option or -option */
539 		fprintf (stderr, "%s: unrecognized option `%c%s'\n",
540 			 argv[0], argv[optind][0], nextchar);
541 	    }
542 	  nextchar = (char *) "";
543 	  optind++;
544 	  return '?';
545 	}
546     }
547 
548   /* Look at and handle the next option-character.  */
549 
550   {
551     char c = *nextchar++;
552     char *temp = my_index (optstring, c);
553 
554     /* Increment `optind' when we start to process its last character.  */
555     if (*nextchar == '\0')
556       ++optind;
557 
558     if (temp == NULL || c == ':')
559       {
560 	if (opterr)
561 	  {
562 #if 0
563 	    if (c < 040 || c >= 0177)
564 	      fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
565 		       argv[0], c);
566 	    else
567 	      fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c);
568 #else
569 	    /* 1003.2 specifies the format of this message.  */
570 	    fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
571 #endif
572 	  }
573 	optopt = c;
574 	return '?';
575       }
576     if (temp[1] == ':')
577       {
578 	if (temp[2] == ':')
579 	  {
580 	    /* This is an option that accepts an argument optionally.  */
581 	    if (*nextchar != '\0')
582 	      {
583 		optarg = nextchar;
584 		optind++;
585 	      }
586 	    else
587 	      optarg = 0;
588 	    nextchar = NULL;
589 	  }
590 	else
591 	  {
592 	    /* This is an option that requires an argument.  */
593 	    if (*nextchar != '\0')
594 	      {
595 		optarg = nextchar;
596 		/* If we end this ARGV-element by taking the rest as an arg,
597 		   we must advance to the next element now.  */
598 		optind++;
599 	      }
600 	    else if (optind == argc)
601 	      {
602 		if (opterr)
603 		  {
604 #if 0
605 		    fprintf (stderr, "%s: option `-%c' requires an argument\n",
606 			     argv[0], c);
607 #else
608 		    /* 1003.2 specifies the format of this message.  */
609 		    fprintf (stderr, "%s: option requires an argument -- %c\n",
610 			     argv[0], c);
611 #endif
612 		  }
613 		optopt = c;
614 		if (optstring[0] == ':')
615 		  c = ':';
616 		else
617 		  c = '?';
618 	      }
619 	    else
620 	      /* We already incremented `optind' once;
621 		 increment it again when taking next ARGV-elt as argument.  */
622 	      optarg = argv[optind++];
623 	    nextchar = NULL;
624 	  }
625       }
626     return c;
627   }
628 }
629 
630 int
getopt(argc,argv,optstring)631 getopt (argc, argv, optstring)
632      int argc;
633      char *const *argv;
634      const char *optstring;
635 {
636   return _getopt_internal (argc, argv, optstring,
637 			   (const struct option *) 0,
638 			   (int *) 0,
639 			   0);
640 }
641 
642 #ifdef TEST
643 
644 /* Compile with -DTEST to make an executable for use in testing
645    the above definition of `getopt'.  */
646 
647 int
main(argc,argv)648 main (argc, argv)
649      int argc;
650      char **argv;
651 {
652   int c;
653   int digit_optind = 0;
654 
655   while (1)
656     {
657       int this_option_optind = optind ? optind : 1;
658 
659       c = getopt (argc, argv, "abc:d:0123456789");
660       if (c == EOF)
661 	break;
662 
663       switch (c)
664 	{
665 	case '0':
666 	case '1':
667 	case '2':
668 	case '3':
669 	case '4':
670 	case '5':
671 	case '6':
672 	case '7':
673 	case '8':
674 	case '9':
675 	  if (digit_optind != 0 && digit_optind != this_option_optind)
676 	    printf ("digits occur in two different argv-elements.\n");
677 	  digit_optind = this_option_optind;
678 	  printf ("option %c\n", c);
679 	  break;
680 
681 	case 'a':
682 	  printf ("option a\n");
683 	  break;
684 
685 	case 'b':
686 	  printf ("option b\n");
687 	  break;
688 
689 	case 'c':
690 	  printf ("option c with value `%s'\n", optarg);
691 	  break;
692 
693 	case '?':
694 	  break;
695 
696 	default:
697 	  printf ("?? getopt returned character code 0%o ??\n", c);
698 	}
699     }
700 
701   if (optind < argc)
702     {
703       printf ("non-option ARGV-elements: ");
704       while (optind < argc)
705 	printf ("%s ", argv[optind++]);
706       printf ("\n");
707     }
708 
709   exit (0);
710 }
711 
712 #endif /* TEST */
713