xref: /openbsd-src/gnu/usr.bin/cvs/lib/getopt.c (revision 461cc63e7458ce60db55037c1a7656349538b52f)
11e72d8d2Sderaadt /* Getopt for GNU.
21e72d8d2Sderaadt    NOTE: getopt is now part of the C library, so if you don't know what
31e72d8d2Sderaadt    "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
41e72d8d2Sderaadt    before changing it!
51e72d8d2Sderaadt 
61e72d8d2Sderaadt    Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94
71e72d8d2Sderaadt    	Free Software Foundation, Inc.
81e72d8d2Sderaadt 
91e72d8d2Sderaadt    This program is free software; you can redistribute it and/or modify it
101e72d8d2Sderaadt    under the terms of the GNU General Public License as published by the
111e72d8d2Sderaadt    Free Software Foundation; either version 2, or (at your option) any
121e72d8d2Sderaadt    later version.
131e72d8d2Sderaadt 
141e72d8d2Sderaadt    This program is distributed in the hope that it will be useful,
151e72d8d2Sderaadt    but WITHOUT ANY WARRANTY; without even the implied warranty of
161e72d8d2Sderaadt    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17*461cc63eStholo    GNU General Public License for more details.  */
181e72d8d2Sderaadt 
191e72d8d2Sderaadt /* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
201e72d8d2Sderaadt    Ditto for AIX 3.2 and <stdlib.h>.  */
211e72d8d2Sderaadt #ifndef _NO_PROTO
221e72d8d2Sderaadt #define _NO_PROTO
231e72d8d2Sderaadt #endif
241e72d8d2Sderaadt 
251e72d8d2Sderaadt #ifdef HAVE_CONFIG_H
261e72d8d2Sderaadt #if defined (emacs) || defined (CONFIG_BROKETS)
271e72d8d2Sderaadt /* We use <config.h> instead of "config.h" so that a compilation
281e72d8d2Sderaadt    using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
291e72d8d2Sderaadt    (which it would do because it found this file in $srcdir).  */
301e72d8d2Sderaadt #include <config.h>
311e72d8d2Sderaadt #else
321e72d8d2Sderaadt #include "config.h"
331e72d8d2Sderaadt #endif
341e72d8d2Sderaadt #endif
351e72d8d2Sderaadt 
361e72d8d2Sderaadt #ifndef __STDC__
371e72d8d2Sderaadt /* This is a separate conditional since some stdc systems
381e72d8d2Sderaadt    reject `defined (const)'.  */
391e72d8d2Sderaadt #ifndef const
401e72d8d2Sderaadt #define const
411e72d8d2Sderaadt #endif
421e72d8d2Sderaadt #endif
431e72d8d2Sderaadt 
441e72d8d2Sderaadt #include <stdio.h>
451e72d8d2Sderaadt 
461e72d8d2Sderaadt #ifdef HAVE_STRING_H
471e72d8d2Sderaadt #include <string.h>
481e72d8d2Sderaadt #endif
491e72d8d2Sderaadt 
501e72d8d2Sderaadt /* Comment out all this code if we are using the GNU C Library, and are not
511e72d8d2Sderaadt    actually compiling the library itself.  This code is part of the GNU C
521e72d8d2Sderaadt    Library, but also included in many other GNU distributions.  Compiling
531e72d8d2Sderaadt    and linking in this code is a waste when using the GNU C library
541e72d8d2Sderaadt    (especially if it is a shared library).  Rather than having every GNU
551e72d8d2Sderaadt    program understand `configure --with-gnu-libc' and omit the object files,
561e72d8d2Sderaadt    it is simpler to just do this in the source for each such file.  */
571e72d8d2Sderaadt 
581e72d8d2Sderaadt #if defined (_LIBC) || !defined (__GNU_LIBRARY__)
591e72d8d2Sderaadt 
601e72d8d2Sderaadt 
611e72d8d2Sderaadt /* This needs to come after some library #include
621e72d8d2Sderaadt    to get __GNU_LIBRARY__ defined.  */
631e72d8d2Sderaadt #ifdef	__GNU_LIBRARY__
641e72d8d2Sderaadt /* Don't include stdlib.h for non-GNU C libraries because some of them
651e72d8d2Sderaadt    contain conflicting prototypes for getopt.  */
661e72d8d2Sderaadt #include <stdlib.h>
671e72d8d2Sderaadt #endif	/* GNU C library.  */
681e72d8d2Sderaadt 
691e72d8d2Sderaadt /* This version of `getopt' appears to the caller like standard Unix `getopt'
701e72d8d2Sderaadt    but it behaves differently for the user, since it allows the user
711e72d8d2Sderaadt    to intersperse the options with the other arguments.
721e72d8d2Sderaadt 
731e72d8d2Sderaadt    As `getopt' works, it permutes the elements of ARGV so that,
741e72d8d2Sderaadt    when it is done, all the options precede everything else.  Thus
751e72d8d2Sderaadt    all application programs are extended to handle flexible argument order.
761e72d8d2Sderaadt 
771e72d8d2Sderaadt    Setting the environment variable POSIXLY_CORRECT disables permutation.
781e72d8d2Sderaadt    Then the behavior is completely standard.
791e72d8d2Sderaadt 
801e72d8d2Sderaadt    GNU application programs can use a third alternative mode in which
811e72d8d2Sderaadt    they can distinguish the relative order of options and other arguments.  */
821e72d8d2Sderaadt 
831e72d8d2Sderaadt #include "getopt.h"
841e72d8d2Sderaadt 
851e72d8d2Sderaadt /* For communication from `getopt' to the caller.
861e72d8d2Sderaadt    When `getopt' finds an option that takes an argument,
871e72d8d2Sderaadt    the argument value is returned here.
881e72d8d2Sderaadt    Also, when `ordering' is RETURN_IN_ORDER,
891e72d8d2Sderaadt    each non-option ARGV-element is returned here.  */
901e72d8d2Sderaadt 
911e72d8d2Sderaadt char *optarg = NULL;
921e72d8d2Sderaadt 
931e72d8d2Sderaadt /* Index in ARGV of the next element to be scanned.
941e72d8d2Sderaadt    This is used for communication to and from the caller
951e72d8d2Sderaadt    and for communication between successive calls to `getopt'.
961e72d8d2Sderaadt 
971e72d8d2Sderaadt    On entry to `getopt', zero means this is the first call; initialize.
981e72d8d2Sderaadt 
991e72d8d2Sderaadt    When `getopt' returns EOF, this is the index of the first of the
1001e72d8d2Sderaadt    non-option elements that the caller should itself scan.
1011e72d8d2Sderaadt 
1021e72d8d2Sderaadt    Otherwise, `optind' communicates from one call to the next
1031e72d8d2Sderaadt    how much of ARGV has been scanned so far.  */
1041e72d8d2Sderaadt 
1051e72d8d2Sderaadt /* XXX 1003.2 says this must be 1 before any call.  */
1061e72d8d2Sderaadt int optind = 0;
1071e72d8d2Sderaadt 
1081e72d8d2Sderaadt /* The next char to be scanned in the option-element
1091e72d8d2Sderaadt    in which the last option character we returned was found.
1101e72d8d2Sderaadt    This allows us to pick up the scan where we left off.
1111e72d8d2Sderaadt 
1121e72d8d2Sderaadt    If this is zero, or a null string, it means resume the scan
1131e72d8d2Sderaadt    by advancing to the next ARGV-element.  */
1141e72d8d2Sderaadt 
1151e72d8d2Sderaadt static char *nextchar;
1161e72d8d2Sderaadt 
1171e72d8d2Sderaadt /* Callers store zero here to inhibit the error message
1181e72d8d2Sderaadt    for unrecognized options.  */
1191e72d8d2Sderaadt 
1201e72d8d2Sderaadt int opterr = 1;
1211e72d8d2Sderaadt 
1221e72d8d2Sderaadt /* Set to an option character which was unrecognized.
1231e72d8d2Sderaadt    This must be initialized on some systems to avoid linking in the
1241e72d8d2Sderaadt    system's own getopt implementation.  */
1251e72d8d2Sderaadt 
1261e72d8d2Sderaadt int optopt = '?';
1271e72d8d2Sderaadt 
1281e72d8d2Sderaadt /* Describe how to deal with options that follow non-option ARGV-elements.
1291e72d8d2Sderaadt 
1301e72d8d2Sderaadt    If the caller did not specify anything,
1311e72d8d2Sderaadt    the default is REQUIRE_ORDER if the environment variable
1321e72d8d2Sderaadt    POSIXLY_CORRECT is defined, PERMUTE otherwise.
1331e72d8d2Sderaadt 
1341e72d8d2Sderaadt    REQUIRE_ORDER means don't recognize them as options;
1351e72d8d2Sderaadt    stop option processing when the first non-option is seen.
1361e72d8d2Sderaadt    This is what Unix does.
1371e72d8d2Sderaadt    This mode of operation is selected by either setting the environment
1381e72d8d2Sderaadt    variable POSIXLY_CORRECT, or using `+' as the first character
1391e72d8d2Sderaadt    of the list of option characters.
1401e72d8d2Sderaadt 
1411e72d8d2Sderaadt    PERMUTE is the default.  We permute the contents of ARGV as we scan,
1421e72d8d2Sderaadt    so that eventually all the non-options are at the end.  This allows options
1431e72d8d2Sderaadt    to be given in any order, even with programs that were not written to
1441e72d8d2Sderaadt    expect this.
1451e72d8d2Sderaadt 
1461e72d8d2Sderaadt    RETURN_IN_ORDER is an option available to programs that were written
1471e72d8d2Sderaadt    to expect options and other ARGV-elements in any order and that care about
1481e72d8d2Sderaadt    the ordering of the two.  We describe each non-option ARGV-element
1491e72d8d2Sderaadt    as if it were the argument of an option with character code 1.
1501e72d8d2Sderaadt    Using `-' as the first character of the list of option characters
1511e72d8d2Sderaadt    selects this mode of operation.
1521e72d8d2Sderaadt 
1531e72d8d2Sderaadt    The special argument `--' forces an end of option-scanning regardless
1541e72d8d2Sderaadt    of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
1551e72d8d2Sderaadt    `--' can cause `getopt' to return EOF with `optind' != ARGC.  */
1561e72d8d2Sderaadt 
1571e72d8d2Sderaadt static enum
1581e72d8d2Sderaadt {
1591e72d8d2Sderaadt   REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
1601e72d8d2Sderaadt } ordering;
1611e72d8d2Sderaadt 
1621e72d8d2Sderaadt /* Value of POSIXLY_CORRECT environment variable.  */
1631e72d8d2Sderaadt static char *posixly_correct;
1641e72d8d2Sderaadt 
1651e72d8d2Sderaadt #ifdef	__GNU_LIBRARY__
1661e72d8d2Sderaadt /* We want to avoid inclusion of string.h with non-GNU libraries
1671e72d8d2Sderaadt    because there are many ways it can cause trouble.
1681e72d8d2Sderaadt    On some systems, it contains special magic macros that don't work
1691e72d8d2Sderaadt    in GCC.  */
1701e72d8d2Sderaadt #include <string.h>
1711e72d8d2Sderaadt #define	my_index	strchr
1721e72d8d2Sderaadt #else
1731e72d8d2Sderaadt 
1741e72d8d2Sderaadt /* Avoid depending on library functions or files
1751e72d8d2Sderaadt    whose names are inconsistent.  */
1761e72d8d2Sderaadt 
1771e72d8d2Sderaadt char *getenv ();
1781e72d8d2Sderaadt 
1791e72d8d2Sderaadt static char *
my_index(str,chr)1801e72d8d2Sderaadt my_index (str, chr)
1811e72d8d2Sderaadt      const char *str;
1821e72d8d2Sderaadt      int chr;
1831e72d8d2Sderaadt {
1841e72d8d2Sderaadt   while (*str)
1851e72d8d2Sderaadt     {
1861e72d8d2Sderaadt       if (*str == chr)
1871e72d8d2Sderaadt 	return (char *) str;
1881e72d8d2Sderaadt       str++;
1891e72d8d2Sderaadt     }
1901e72d8d2Sderaadt   return 0;
1911e72d8d2Sderaadt }
1921e72d8d2Sderaadt 
1931e72d8d2Sderaadt /* If using GCC, we can safely declare strlen this way.
1941e72d8d2Sderaadt    If not using GCC, it is ok not to declare it.  */
1951e72d8d2Sderaadt #ifdef __GNUC__
1961e72d8d2Sderaadt /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
1971e72d8d2Sderaadt    That was relevant to code that was here before.  */
1981e72d8d2Sderaadt #ifndef __STDC__
1991e72d8d2Sderaadt /* gcc with -traditional declares the built-in strlen to return int,
2001e72d8d2Sderaadt    and has done so at least since version 2.4.5. -- rms.  */
2011e72d8d2Sderaadt extern int strlen (const char *);
2021e72d8d2Sderaadt #endif /* not __STDC__ */
2031e72d8d2Sderaadt #endif /* __GNUC__ */
2041e72d8d2Sderaadt 
2051e72d8d2Sderaadt #endif /* not __GNU_LIBRARY__ */
2061e72d8d2Sderaadt 
2071e72d8d2Sderaadt /* Handle permutation of arguments.  */
2081e72d8d2Sderaadt 
2091e72d8d2Sderaadt /* Describe the part of ARGV that contains non-options that have
2101e72d8d2Sderaadt    been skipped.  `first_nonopt' is the index in ARGV of the first of them;
2111e72d8d2Sderaadt    `last_nonopt' is the index after the last of them.  */
2121e72d8d2Sderaadt 
2131e72d8d2Sderaadt static int first_nonopt;
2141e72d8d2Sderaadt static int last_nonopt;
2151e72d8d2Sderaadt 
2161e72d8d2Sderaadt /* Exchange two adjacent subsequences of ARGV.
2171e72d8d2Sderaadt    One subsequence is elements [first_nonopt,last_nonopt)
2181e72d8d2Sderaadt    which contains all the non-options that have been skipped so far.
2191e72d8d2Sderaadt    The other is elements [last_nonopt,optind), which contains all
2201e72d8d2Sderaadt    the options processed since those non-options were skipped.
2211e72d8d2Sderaadt 
2221e72d8d2Sderaadt    `first_nonopt' and `last_nonopt' are relocated so that they describe
2231e72d8d2Sderaadt    the new indices of the non-options in ARGV after they are moved.  */
2241e72d8d2Sderaadt 
2251e72d8d2Sderaadt static void
exchange(argv)2261e72d8d2Sderaadt exchange (argv)
2271e72d8d2Sderaadt      char **argv;
2281e72d8d2Sderaadt {
2291e72d8d2Sderaadt   int bottom = first_nonopt;
2301e72d8d2Sderaadt   int middle = last_nonopt;
2311e72d8d2Sderaadt   int top = optind;
2321e72d8d2Sderaadt   char *tem;
2331e72d8d2Sderaadt 
2341e72d8d2Sderaadt   /* Exchange the shorter segment with the far end of the longer segment.
2351e72d8d2Sderaadt      That puts the shorter segment into the right place.
2361e72d8d2Sderaadt      It leaves the longer segment in the right place overall,
2371e72d8d2Sderaadt      but it consists of two parts that need to be swapped next.  */
2381e72d8d2Sderaadt 
2391e72d8d2Sderaadt   while (top > middle && middle > bottom)
2401e72d8d2Sderaadt     {
2411e72d8d2Sderaadt       if (top - middle > middle - bottom)
2421e72d8d2Sderaadt 	{
2431e72d8d2Sderaadt 	  /* Bottom segment is the short one.  */
2441e72d8d2Sderaadt 	  int len = middle - bottom;
2451e72d8d2Sderaadt 	  register int i;
2461e72d8d2Sderaadt 
2471e72d8d2Sderaadt 	  /* Swap it with the top part of the top segment.  */
2481e72d8d2Sderaadt 	  for (i = 0; i < len; i++)
2491e72d8d2Sderaadt 	    {
2501e72d8d2Sderaadt 	      tem = argv[bottom + i];
2511e72d8d2Sderaadt 	      argv[bottom + i] = argv[top - (middle - bottom) + i];
2521e72d8d2Sderaadt 	      argv[top - (middle - bottom) + i] = tem;
2531e72d8d2Sderaadt 	    }
2541e72d8d2Sderaadt 	  /* Exclude the moved bottom segment from further swapping.  */
2551e72d8d2Sderaadt 	  top -= len;
2561e72d8d2Sderaadt 	}
2571e72d8d2Sderaadt       else
2581e72d8d2Sderaadt 	{
2591e72d8d2Sderaadt 	  /* Top segment is the short one.  */
2601e72d8d2Sderaadt 	  int len = top - middle;
2611e72d8d2Sderaadt 	  register int i;
2621e72d8d2Sderaadt 
2631e72d8d2Sderaadt 	  /* Swap it with the bottom part of the bottom segment.  */
2641e72d8d2Sderaadt 	  for (i = 0; i < len; i++)
2651e72d8d2Sderaadt 	    {
2661e72d8d2Sderaadt 	      tem = argv[bottom + i];
2671e72d8d2Sderaadt 	      argv[bottom + i] = argv[middle + i];
2681e72d8d2Sderaadt 	      argv[middle + i] = tem;
2691e72d8d2Sderaadt 	    }
2701e72d8d2Sderaadt 	  /* Exclude the moved top segment from further swapping.  */
2711e72d8d2Sderaadt 	  bottom += len;
2721e72d8d2Sderaadt 	}
2731e72d8d2Sderaadt     }
2741e72d8d2Sderaadt 
2751e72d8d2Sderaadt   /* Update records for the slots the non-options now occupy.  */
2761e72d8d2Sderaadt 
2771e72d8d2Sderaadt   first_nonopt += (optind - last_nonopt);
2781e72d8d2Sderaadt   last_nonopt = optind;
2791e72d8d2Sderaadt }
2801e72d8d2Sderaadt 
2811e72d8d2Sderaadt /* Initialize the internal data when the first call is made.  */
2821e72d8d2Sderaadt 
2831e72d8d2Sderaadt static const char *
_getopt_initialize(optstring)2841e72d8d2Sderaadt _getopt_initialize (optstring)
2851e72d8d2Sderaadt      const char *optstring;
2861e72d8d2Sderaadt {
2871e72d8d2Sderaadt   /* Start processing options with ARGV-element 1 (since ARGV-element 0
2881e72d8d2Sderaadt      is the program name); the sequence of previously skipped
2891e72d8d2Sderaadt      non-option ARGV-elements is empty.  */
2901e72d8d2Sderaadt 
2911e72d8d2Sderaadt   first_nonopt = last_nonopt = optind = 1;
2921e72d8d2Sderaadt 
2931e72d8d2Sderaadt   nextchar = NULL;
2941e72d8d2Sderaadt 
2951e72d8d2Sderaadt   posixly_correct = getenv ("POSIXLY_CORRECT");
2961e72d8d2Sderaadt 
2971e72d8d2Sderaadt   /* Determine how to handle the ordering of options and nonoptions.  */
2981e72d8d2Sderaadt 
2991e72d8d2Sderaadt   if (optstring[0] == '-')
3001e72d8d2Sderaadt     {
3011e72d8d2Sderaadt       ordering = RETURN_IN_ORDER;
3021e72d8d2Sderaadt       ++optstring;
3031e72d8d2Sderaadt     }
3041e72d8d2Sderaadt   else if (optstring[0] == '+')
3051e72d8d2Sderaadt     {
3061e72d8d2Sderaadt       ordering = REQUIRE_ORDER;
3071e72d8d2Sderaadt       ++optstring;
3081e72d8d2Sderaadt     }
3091e72d8d2Sderaadt   else if (posixly_correct != NULL)
3101e72d8d2Sderaadt     ordering = REQUIRE_ORDER;
3111e72d8d2Sderaadt   else
3121e72d8d2Sderaadt     ordering = PERMUTE;
3131e72d8d2Sderaadt 
3141e72d8d2Sderaadt   return optstring;
3151e72d8d2Sderaadt }
3161e72d8d2Sderaadt 
3171e72d8d2Sderaadt /* Scan elements of ARGV (whose length is ARGC) for option characters
3181e72d8d2Sderaadt    given in OPTSTRING.
3191e72d8d2Sderaadt 
3201e72d8d2Sderaadt    If an element of ARGV starts with '-', and is not exactly "-" or "--",
3211e72d8d2Sderaadt    then it is an option element.  The characters of this element
3221e72d8d2Sderaadt    (aside from the initial '-') are option characters.  If `getopt'
3231e72d8d2Sderaadt    is called repeatedly, it returns successively each of the option characters
3241e72d8d2Sderaadt    from each of the option elements.
3251e72d8d2Sderaadt 
3261e72d8d2Sderaadt    If `getopt' finds another option character, it returns that character,
3271e72d8d2Sderaadt    updating `optind' and `nextchar' so that the next call to `getopt' can
3281e72d8d2Sderaadt    resume the scan with the following option character or ARGV-element.
3291e72d8d2Sderaadt 
3301e72d8d2Sderaadt    If there are no more option characters, `getopt' returns `EOF'.
3311e72d8d2Sderaadt    Then `optind' is the index in ARGV of the first ARGV-element
3321e72d8d2Sderaadt    that is not an option.  (The ARGV-elements have been permuted
3331e72d8d2Sderaadt    so that those that are not options now come last.)
3341e72d8d2Sderaadt 
3351e72d8d2Sderaadt    OPTSTRING is a string containing the legitimate option characters.
3361e72d8d2Sderaadt    If an option character is seen that is not listed in OPTSTRING,
3371e72d8d2Sderaadt    return '?' after printing an error message.  If you set `opterr' to
3381e72d8d2Sderaadt    zero, the error message is suppressed but we still return '?'.
3391e72d8d2Sderaadt 
3401e72d8d2Sderaadt    If a char in OPTSTRING is followed by a colon, that means it wants an arg,
3411e72d8d2Sderaadt    so the following text in the same ARGV-element, or the text of the following
3421e72d8d2Sderaadt    ARGV-element, is returned in `optarg'.  Two colons mean an option that
3431e72d8d2Sderaadt    wants an optional arg; if there is text in the current ARGV-element,
3441e72d8d2Sderaadt    it is returned in `optarg', otherwise `optarg' is set to zero.
3451e72d8d2Sderaadt 
3461e72d8d2Sderaadt    If OPTSTRING starts with `-' or `+', it requests different methods of
3471e72d8d2Sderaadt    handling the non-option ARGV-elements.
3481e72d8d2Sderaadt    See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
3491e72d8d2Sderaadt 
3501e72d8d2Sderaadt    Long-named options begin with `--' instead of `-'.
3511e72d8d2Sderaadt    Their names may be abbreviated as long as the abbreviation is unique
3521e72d8d2Sderaadt    or is an exact match for some defined option.  If they have an
3531e72d8d2Sderaadt    argument, it follows the option name in the same ARGV-element, separated
3541e72d8d2Sderaadt    from the option name by a `=', or else the in next ARGV-element.
3551e72d8d2Sderaadt    When `getopt' finds a long-named option, it returns 0 if that option's
3561e72d8d2Sderaadt    `flag' field is nonzero, the value of the option's `val' field
3571e72d8d2Sderaadt    if the `flag' field is zero.
3581e72d8d2Sderaadt 
3591e72d8d2Sderaadt    The elements of ARGV aren't really const, because we permute them.
3601e72d8d2Sderaadt    But we pretend they're const in the prototype to be compatible
3611e72d8d2Sderaadt    with other systems.
3621e72d8d2Sderaadt 
3631e72d8d2Sderaadt    LONGOPTS is a vector of `struct option' terminated by an
3641e72d8d2Sderaadt    element containing a name which is zero.
3651e72d8d2Sderaadt 
3661e72d8d2Sderaadt    LONGIND returns the index in LONGOPT of the long-named option found.
3671e72d8d2Sderaadt    It is only valid when a long-named option has been found by the most
3681e72d8d2Sderaadt    recent call.
3691e72d8d2Sderaadt 
3701e72d8d2Sderaadt    If LONG_ONLY is nonzero, '-' as well as '--' can introduce
3711e72d8d2Sderaadt    long-named options.  */
3721e72d8d2Sderaadt 
3731e72d8d2Sderaadt int
_getopt_internal(argc,argv,optstring,longopts,longind,long_only)3741e72d8d2Sderaadt _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
3751e72d8d2Sderaadt      int argc;
3761e72d8d2Sderaadt      char *const *argv;
3771e72d8d2Sderaadt      const char *optstring;
3781e72d8d2Sderaadt      const struct option *longopts;
3791e72d8d2Sderaadt      int *longind;
3801e72d8d2Sderaadt      int long_only;
3811e72d8d2Sderaadt {
3821e72d8d2Sderaadt   optarg = NULL;
3831e72d8d2Sderaadt 
3841e72d8d2Sderaadt   if (optind == 0)
3851e72d8d2Sderaadt     optstring = _getopt_initialize (optstring);
3861e72d8d2Sderaadt 
3871e72d8d2Sderaadt   if (nextchar == NULL || *nextchar == '\0')
3881e72d8d2Sderaadt     {
3891e72d8d2Sderaadt       /* Advance to the next ARGV-element.  */
3901e72d8d2Sderaadt 
3911e72d8d2Sderaadt       if (ordering == PERMUTE)
3921e72d8d2Sderaadt 	{
3931e72d8d2Sderaadt 	  /* If we have just processed some options following some non-options,
3941e72d8d2Sderaadt 	     exchange them so that the options come first.  */
3951e72d8d2Sderaadt 
3961e72d8d2Sderaadt 	  if (first_nonopt != last_nonopt && last_nonopt != optind)
3971e72d8d2Sderaadt 	    exchange ((char **) argv);
3981e72d8d2Sderaadt 	  else if (last_nonopt != optind)
3991e72d8d2Sderaadt 	    first_nonopt = optind;
4001e72d8d2Sderaadt 
4011e72d8d2Sderaadt 	  /* Skip any additional non-options
4021e72d8d2Sderaadt 	     and extend the range of non-options previously skipped.  */
4031e72d8d2Sderaadt 
4041e72d8d2Sderaadt 	  while (optind < argc
4051e72d8d2Sderaadt 		 && (argv[optind][0] != '-' || argv[optind][1] == '\0'))
4061e72d8d2Sderaadt 	    optind++;
4071e72d8d2Sderaadt 	  last_nonopt = optind;
4081e72d8d2Sderaadt 	}
4091e72d8d2Sderaadt 
4101e72d8d2Sderaadt       /* The special ARGV-element `--' means premature end of options.
4111e72d8d2Sderaadt 	 Skip it like a null option,
4121e72d8d2Sderaadt 	 then exchange with previous non-options as if it were an option,
4131e72d8d2Sderaadt 	 then skip everything else like a non-option.  */
4141e72d8d2Sderaadt 
4151e72d8d2Sderaadt       if (optind != argc && !strcmp (argv[optind], "--"))
4161e72d8d2Sderaadt 	{
4171e72d8d2Sderaadt 	  optind++;
4181e72d8d2Sderaadt 
4191e72d8d2Sderaadt 	  if (first_nonopt != last_nonopt && last_nonopt != optind)
4201e72d8d2Sderaadt 	    exchange ((char **) argv);
4211e72d8d2Sderaadt 	  else if (first_nonopt == last_nonopt)
4221e72d8d2Sderaadt 	    first_nonopt = optind;
4231e72d8d2Sderaadt 	  last_nonopt = argc;
4241e72d8d2Sderaadt 
4251e72d8d2Sderaadt 	  optind = argc;
4261e72d8d2Sderaadt 	}
4271e72d8d2Sderaadt 
4281e72d8d2Sderaadt       /* If we have done all the ARGV-elements, stop the scan
4291e72d8d2Sderaadt 	 and back over any non-options that we skipped and permuted.  */
4301e72d8d2Sderaadt 
4311e72d8d2Sderaadt       if (optind == argc)
4321e72d8d2Sderaadt 	{
4331e72d8d2Sderaadt 	  /* Set the next-arg-index to point at the non-options
4341e72d8d2Sderaadt 	     that we previously skipped, so the caller will digest them.  */
4351e72d8d2Sderaadt 	  if (first_nonopt != last_nonopt)
4361e72d8d2Sderaadt 	    optind = first_nonopt;
4371e72d8d2Sderaadt 	  return EOF;
4381e72d8d2Sderaadt 	}
4391e72d8d2Sderaadt 
4401e72d8d2Sderaadt       /* If we have come to a non-option and did not permute it,
4411e72d8d2Sderaadt 	 either stop the scan or describe it to the caller and pass it by.  */
4421e72d8d2Sderaadt 
4431e72d8d2Sderaadt       if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))
4441e72d8d2Sderaadt 	{
4451e72d8d2Sderaadt 	  if (ordering == REQUIRE_ORDER)
4461e72d8d2Sderaadt 	    return EOF;
4471e72d8d2Sderaadt 	  optarg = argv[optind++];
4481e72d8d2Sderaadt 	  return 1;
4491e72d8d2Sderaadt 	}
4501e72d8d2Sderaadt 
4511e72d8d2Sderaadt       /* We have found another option-ARGV-element.
4521e72d8d2Sderaadt 	 Skip the initial punctuation.  */
4531e72d8d2Sderaadt 
4541e72d8d2Sderaadt       nextchar = (argv[optind] + 1
4551e72d8d2Sderaadt 		  + (longopts != NULL && argv[optind][1] == '-'));
4561e72d8d2Sderaadt     }
4571e72d8d2Sderaadt 
4581e72d8d2Sderaadt   /* Decode the current option-ARGV-element.  */
4591e72d8d2Sderaadt 
4601e72d8d2Sderaadt   /* Check whether the ARGV-element is a long option.
4611e72d8d2Sderaadt 
4621e72d8d2Sderaadt      If long_only and the ARGV-element has the form "-f", where f is
4631e72d8d2Sderaadt      a valid short option, don't consider it an abbreviated form of
4641e72d8d2Sderaadt      a long option that starts with f.  Otherwise there would be no
4651e72d8d2Sderaadt      way to give the -f short option.
4661e72d8d2Sderaadt 
4671e72d8d2Sderaadt      On the other hand, if there's a long option "fubar" and
4681e72d8d2Sderaadt      the ARGV-element is "-fu", do consider that an abbreviation of
4691e72d8d2Sderaadt      the long option, just like "--fu", and not "-f" with arg "u".
4701e72d8d2Sderaadt 
4711e72d8d2Sderaadt      This distinction seems to be the most useful approach.  */
4721e72d8d2Sderaadt 
4731e72d8d2Sderaadt   if (longopts != NULL
4741e72d8d2Sderaadt       && (argv[optind][1] == '-'
4751e72d8d2Sderaadt 	  || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
4761e72d8d2Sderaadt     {
4771e72d8d2Sderaadt       char *nameend;
4781e72d8d2Sderaadt       const struct option *p;
4791e72d8d2Sderaadt       const struct option *pfound = NULL;
4801e72d8d2Sderaadt       int exact = 0;
4811e72d8d2Sderaadt       int ambig = 0;
4821e72d8d2Sderaadt       int indfound;
4831e72d8d2Sderaadt       int option_index;
4841e72d8d2Sderaadt 
4851e72d8d2Sderaadt       for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
4861e72d8d2Sderaadt 	/* Do nothing.  */ ;
4871e72d8d2Sderaadt 
4881e72d8d2Sderaadt       /* Test all long options for either exact match
4891e72d8d2Sderaadt 	 or abbreviated matches.  */
4901e72d8d2Sderaadt       for (p = longopts, option_index = 0; p->name; p++, option_index++)
4911e72d8d2Sderaadt 	if (!strncmp (p->name, nextchar, nameend - nextchar))
4921e72d8d2Sderaadt 	  {
4931e72d8d2Sderaadt 	    if (nameend - nextchar == (int) strlen (p->name))
4941e72d8d2Sderaadt 	      {
4951e72d8d2Sderaadt 		/* Exact match found.  */
4961e72d8d2Sderaadt 		pfound = p;
4971e72d8d2Sderaadt 		indfound = option_index;
4981e72d8d2Sderaadt 		exact = 1;
4991e72d8d2Sderaadt 		break;
5001e72d8d2Sderaadt 	      }
5011e72d8d2Sderaadt 	    else if (pfound == NULL)
5021e72d8d2Sderaadt 	      {
5031e72d8d2Sderaadt 		/* First nonexact match found.  */
5041e72d8d2Sderaadt 		pfound = p;
5051e72d8d2Sderaadt 		indfound = option_index;
5061e72d8d2Sderaadt 	      }
5071e72d8d2Sderaadt 	    else
5081e72d8d2Sderaadt 	      /* Second or later nonexact match found.  */
5091e72d8d2Sderaadt 	      ambig = 1;
5101e72d8d2Sderaadt 	  }
5111e72d8d2Sderaadt 
5121e72d8d2Sderaadt       if (ambig && !exact)
5131e72d8d2Sderaadt 	{
5141e72d8d2Sderaadt 	  if (opterr)
5151e72d8d2Sderaadt 	    fprintf (stderr, "%s: option `%s' is ambiguous\n",
5161e72d8d2Sderaadt 		     argv[0], argv[optind]);
5171e72d8d2Sderaadt 	  nextchar += strlen (nextchar);
5181e72d8d2Sderaadt 	  optind++;
5191e72d8d2Sderaadt 	  return '?';
5201e72d8d2Sderaadt 	}
5211e72d8d2Sderaadt 
5221e72d8d2Sderaadt       if (pfound != NULL)
5231e72d8d2Sderaadt 	{
5241e72d8d2Sderaadt 	  option_index = indfound;
5251e72d8d2Sderaadt 	  optind++;
5261e72d8d2Sderaadt 	  if (*nameend)
5271e72d8d2Sderaadt 	    {
5281e72d8d2Sderaadt 	      /* Don't test has_arg with >, because some C compilers don't
5291e72d8d2Sderaadt 		 allow it to be used on enums.  */
5301e72d8d2Sderaadt 	      if (pfound->has_arg)
5311e72d8d2Sderaadt 		optarg = nameend + 1;
5321e72d8d2Sderaadt 	      else
5331e72d8d2Sderaadt 		{
5341e72d8d2Sderaadt 		  if (opterr)
5351e72d8d2Sderaadt 		    {
5361e72d8d2Sderaadt 		      if (argv[optind - 1][1] == '-')
5371e72d8d2Sderaadt 			/* --option */
5381e72d8d2Sderaadt 			fprintf (stderr,
5391e72d8d2Sderaadt 				 "%s: option `--%s' doesn't allow an argument\n",
5401e72d8d2Sderaadt 				 argv[0], pfound->name);
5411e72d8d2Sderaadt 		      else
5421e72d8d2Sderaadt 			/* +option or -option */
5431e72d8d2Sderaadt 			fprintf (stderr,
5441e72d8d2Sderaadt 			     "%s: option `%c%s' doesn't allow an argument\n",
5451e72d8d2Sderaadt 			     argv[0], argv[optind - 1][0], pfound->name);
5461e72d8d2Sderaadt 		    }
5471e72d8d2Sderaadt 		  nextchar += strlen (nextchar);
5481e72d8d2Sderaadt 		  return '?';
5491e72d8d2Sderaadt 		}
5501e72d8d2Sderaadt 	    }
5511e72d8d2Sderaadt 	  else if (pfound->has_arg == 1)
5521e72d8d2Sderaadt 	    {
5531e72d8d2Sderaadt 	      if (optind < argc)
5541e72d8d2Sderaadt 		optarg = argv[optind++];
5551e72d8d2Sderaadt 	      else
5561e72d8d2Sderaadt 		{
5571e72d8d2Sderaadt 		  if (opterr)
5581e72d8d2Sderaadt 		    fprintf (stderr, "%s: option `%s' requires an argument\n",
5591e72d8d2Sderaadt 			     argv[0], argv[optind - 1]);
5601e72d8d2Sderaadt 		  nextchar += strlen (nextchar);
5611e72d8d2Sderaadt 		  return optstring[0] == ':' ? ':' : '?';
5621e72d8d2Sderaadt 		}
5631e72d8d2Sderaadt 	    }
5641e72d8d2Sderaadt 	  nextchar += strlen (nextchar);
5651e72d8d2Sderaadt 	  if (longind != NULL)
5661e72d8d2Sderaadt 	    *longind = option_index;
5671e72d8d2Sderaadt 	  if (pfound->flag)
5681e72d8d2Sderaadt 	    {
5691e72d8d2Sderaadt 	      *(pfound->flag) = pfound->val;
5701e72d8d2Sderaadt 	      return 0;
5711e72d8d2Sderaadt 	    }
5721e72d8d2Sderaadt 	  return pfound->val;
5731e72d8d2Sderaadt 	}
5741e72d8d2Sderaadt 
5751e72d8d2Sderaadt       /* Can't find it as a long option.  If this is not getopt_long_only,
5761e72d8d2Sderaadt 	 or the option starts with '--' or is not a valid short
5771e72d8d2Sderaadt 	 option, then it's an error.
5781e72d8d2Sderaadt 	 Otherwise interpret it as a short option.  */
5791e72d8d2Sderaadt       if (!long_only || argv[optind][1] == '-'
5801e72d8d2Sderaadt 	  || my_index (optstring, *nextchar) == NULL)
5811e72d8d2Sderaadt 	{
5821e72d8d2Sderaadt 	  if (opterr)
5831e72d8d2Sderaadt 	    {
5841e72d8d2Sderaadt 	      if (argv[optind][1] == '-')
5851e72d8d2Sderaadt 		/* --option */
5861e72d8d2Sderaadt 		fprintf (stderr, "%s: unrecognized option `--%s'\n",
5871e72d8d2Sderaadt 			 argv[0], nextchar);
5881e72d8d2Sderaadt 	      else
5891e72d8d2Sderaadt 		/* +option or -option */
5901e72d8d2Sderaadt 		fprintf (stderr, "%s: unrecognized option `%c%s'\n",
5911e72d8d2Sderaadt 			 argv[0], argv[optind][0], nextchar);
5921e72d8d2Sderaadt 	    }
5931e72d8d2Sderaadt 	  nextchar = (char *) "";
5941e72d8d2Sderaadt 	  optind++;
5951e72d8d2Sderaadt 	  return '?';
5961e72d8d2Sderaadt 	}
5971e72d8d2Sderaadt     }
5981e72d8d2Sderaadt 
5991e72d8d2Sderaadt   /* Look at and handle the next short option-character.  */
6001e72d8d2Sderaadt 
6011e72d8d2Sderaadt   {
6021e72d8d2Sderaadt     char c = *nextchar++;
6031e72d8d2Sderaadt     char *temp = my_index (optstring, c);
6041e72d8d2Sderaadt 
6051e72d8d2Sderaadt     /* Increment `optind' when we start to process its last character.  */
6061e72d8d2Sderaadt     if (*nextchar == '\0')
6071e72d8d2Sderaadt       ++optind;
6081e72d8d2Sderaadt 
6091e72d8d2Sderaadt     if (temp == NULL || c == ':')
6101e72d8d2Sderaadt       {
6111e72d8d2Sderaadt 	if (opterr)
6121e72d8d2Sderaadt 	  {
6131e72d8d2Sderaadt 	    if (posixly_correct)
6141e72d8d2Sderaadt 	      /* 1003.2 specifies the format of this message.  */
6151e72d8d2Sderaadt 	      fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
6161e72d8d2Sderaadt 	    else
6171e72d8d2Sderaadt 	      fprintf (stderr, "%s: invalid option -- %c\n", argv[0], c);
6181e72d8d2Sderaadt 	  }
6191e72d8d2Sderaadt 	optopt = c;
6201e72d8d2Sderaadt 	return '?';
6211e72d8d2Sderaadt       }
6221e72d8d2Sderaadt     if (temp[1] == ':')
6231e72d8d2Sderaadt       {
6241e72d8d2Sderaadt 	if (temp[2] == ':')
6251e72d8d2Sderaadt 	  {
6261e72d8d2Sderaadt 	    /* This is an option that accepts an argument optionally.  */
6271e72d8d2Sderaadt 	    if (*nextchar != '\0')
6281e72d8d2Sderaadt 	      {
6291e72d8d2Sderaadt 		optarg = nextchar;
6301e72d8d2Sderaadt 		optind++;
6311e72d8d2Sderaadt 	      }
6321e72d8d2Sderaadt 	    else
6331e72d8d2Sderaadt 	      optarg = NULL;
6341e72d8d2Sderaadt 	    nextchar = NULL;
6351e72d8d2Sderaadt 	  }
6361e72d8d2Sderaadt 	else
6371e72d8d2Sderaadt 	  {
6381e72d8d2Sderaadt 	    /* This is an option that requires an argument.  */
6391e72d8d2Sderaadt 	    if (*nextchar != '\0')
6401e72d8d2Sderaadt 	      {
6411e72d8d2Sderaadt 		optarg = nextchar;
6421e72d8d2Sderaadt 		/* If we end this ARGV-element by taking the rest as an arg,
6431e72d8d2Sderaadt 		   we must advance to the next element now.  */
6441e72d8d2Sderaadt 		optind++;
6451e72d8d2Sderaadt 	      }
6461e72d8d2Sderaadt 	    else if (optind == argc)
6471e72d8d2Sderaadt 	      {
6481e72d8d2Sderaadt 		if (opterr)
6491e72d8d2Sderaadt 		  {
6501e72d8d2Sderaadt 		    /* 1003.2 specifies the format of this message.  */
6511e72d8d2Sderaadt 		    fprintf (stderr, "%s: option requires an argument -- %c\n",
6521e72d8d2Sderaadt 			     argv[0], c);
6531e72d8d2Sderaadt 		  }
6541e72d8d2Sderaadt 		optopt = c;
6551e72d8d2Sderaadt 		if (optstring[0] == ':')
6561e72d8d2Sderaadt 		  c = ':';
6571e72d8d2Sderaadt 		else
6581e72d8d2Sderaadt 		  c = '?';
6591e72d8d2Sderaadt 	      }
6601e72d8d2Sderaadt 	    else
6611e72d8d2Sderaadt 	      /* We already incremented `optind' once;
6621e72d8d2Sderaadt 		 increment it again when taking next ARGV-elt as argument.  */
6631e72d8d2Sderaadt 	      optarg = argv[optind++];
6641e72d8d2Sderaadt 	    nextchar = NULL;
6651e72d8d2Sderaadt 	  }
6661e72d8d2Sderaadt       }
6671e72d8d2Sderaadt     return c;
6681e72d8d2Sderaadt   }
6691e72d8d2Sderaadt }
6701e72d8d2Sderaadt 
6711e72d8d2Sderaadt int
getopt(argc,argv,optstring)6721e72d8d2Sderaadt getopt (argc, argv, optstring)
6731e72d8d2Sderaadt      int argc;
6741e72d8d2Sderaadt      char *const *argv;
6751e72d8d2Sderaadt      const char *optstring;
6761e72d8d2Sderaadt {
6771e72d8d2Sderaadt   return _getopt_internal (argc, argv, optstring,
6781e72d8d2Sderaadt 			   (const struct option *) 0,
6791e72d8d2Sderaadt 			   (int *) 0,
6801e72d8d2Sderaadt 			   0);
6811e72d8d2Sderaadt }
6821e72d8d2Sderaadt 
6831e72d8d2Sderaadt #endif	/* _LIBC or not __GNU_LIBRARY__.  */
6841e72d8d2Sderaadt 
6851e72d8d2Sderaadt #ifdef TEST
6861e72d8d2Sderaadt 
6871e72d8d2Sderaadt /* Compile with -DTEST to make an executable for use in testing
6881e72d8d2Sderaadt    the above definition of `getopt'.  */
6891e72d8d2Sderaadt 
6901e72d8d2Sderaadt int
main(argc,argv)6911e72d8d2Sderaadt main (argc, argv)
6921e72d8d2Sderaadt      int argc;
6931e72d8d2Sderaadt      char **argv;
6941e72d8d2Sderaadt {
6951e72d8d2Sderaadt   int c;
6961e72d8d2Sderaadt   int digit_optind = 0;
6971e72d8d2Sderaadt 
6981e72d8d2Sderaadt   while (1)
6991e72d8d2Sderaadt     {
7001e72d8d2Sderaadt       int this_option_optind = optind ? optind : 1;
7011e72d8d2Sderaadt 
7021e72d8d2Sderaadt       c = getopt (argc, argv, "abc:d:0123456789");
7031e72d8d2Sderaadt       if (c == EOF)
7041e72d8d2Sderaadt 	break;
7051e72d8d2Sderaadt 
7061e72d8d2Sderaadt       switch (c)
7071e72d8d2Sderaadt 	{
7081e72d8d2Sderaadt 	case '0':
7091e72d8d2Sderaadt 	case '1':
7101e72d8d2Sderaadt 	case '2':
7111e72d8d2Sderaadt 	case '3':
7121e72d8d2Sderaadt 	case '4':
7131e72d8d2Sderaadt 	case '5':
7141e72d8d2Sderaadt 	case '6':
7151e72d8d2Sderaadt 	case '7':
7161e72d8d2Sderaadt 	case '8':
7171e72d8d2Sderaadt 	case '9':
7181e72d8d2Sderaadt 	  if (digit_optind != 0 && digit_optind != this_option_optind)
7191e72d8d2Sderaadt 	    printf ("digits occur in two different argv-elements.\n");
7201e72d8d2Sderaadt 	  digit_optind = this_option_optind;
7211e72d8d2Sderaadt 	  printf ("option %c\n", c);
7221e72d8d2Sderaadt 	  break;
7231e72d8d2Sderaadt 
7241e72d8d2Sderaadt 	case 'a':
7251e72d8d2Sderaadt 	  printf ("option a\n");
7261e72d8d2Sderaadt 	  break;
7271e72d8d2Sderaadt 
7281e72d8d2Sderaadt 	case 'b':
7291e72d8d2Sderaadt 	  printf ("option b\n");
7301e72d8d2Sderaadt 	  break;
7311e72d8d2Sderaadt 
7321e72d8d2Sderaadt 	case 'c':
7331e72d8d2Sderaadt 	  printf ("option c with value `%s'\n", optarg);
7341e72d8d2Sderaadt 	  break;
7351e72d8d2Sderaadt 
7361e72d8d2Sderaadt 	case '?':
7371e72d8d2Sderaadt 	  break;
7381e72d8d2Sderaadt 
7391e72d8d2Sderaadt 	default:
7401e72d8d2Sderaadt 	  printf ("?? getopt returned character code 0%o ??\n", c);
7411e72d8d2Sderaadt 	}
7421e72d8d2Sderaadt     }
7431e72d8d2Sderaadt 
7441e72d8d2Sderaadt   if (optind < argc)
7451e72d8d2Sderaadt     {
7461e72d8d2Sderaadt       printf ("non-option ARGV-elements: ");
7471e72d8d2Sderaadt       while (optind < argc)
7481e72d8d2Sderaadt 	printf ("%s ", argv[optind++]);
7491e72d8d2Sderaadt       printf ("\n");
7501e72d8d2Sderaadt     }
7511e72d8d2Sderaadt 
7521e72d8d2Sderaadt   exit (0);
7531e72d8d2Sderaadt }
7541e72d8d2Sderaadt 
7551e72d8d2Sderaadt #endif /* TEST */
756