packages/support/src/getopt.c

Go to the documentation of this file.
00001 /*
00002 *  Copyright (C) 2007 Reinhard Prix
00003 *
00004 *  This program is free software; you can redistribute it and/or modify
00005 *  it under the terms of the GNU General Public License as published by
00006 *  the Free Software Foundation; either version 2 of the License, or
00007 *  (at your option) any later version.
00008 *
00009 *  This program is distributed in the hope that it will be useful,
00010 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 *  GNU General Public License for more details.
00013 *
00014 *  You should have received a copy of the GNU General Public License
00015 *  along with with program; see the file COPYING. If not, write to the
00016 *  Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00017 *  MA  02111-1307  USA
00018 */
00019 
00020 /* Getopt for GNU.
00021    NOTE: getopt is now part of the C library, so if you don't know what
00022    "Keep this file name-space clean" means, talk to drepper@gnu.org
00023    before changing it!
00024    Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001
00025         Free Software Foundation, Inc.
00026    This file is part of the GNU C Library.
00027 
00028    The GNU C Library is free software; you can redistribute it and/or
00029    modify it under the terms of the GNU Lesser General Public
00030    License as published by the Free Software Foundation; either
00031    version 2.1 of the License, or (at your option) any later version.
00032 
00033    The GNU C Library is distributed in the hope that it will be useful,
00034    but WITHOUT ANY WARRANTY; without even the implied warranty of
00035    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00036    Lesser General Public License for more details.
00037 
00038    You should have received a copy of the GNU Lesser General Public
00039    License along with the GNU C Library; if not, write to the Free
00040    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00041    02111-1307 USA.  */
00042 
00043 /* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
00044    Ditto for AIX 3.2 and <stdlib.h>.  */
00045 #ifndef _NO_PROTO
00046 # define _NO_PROTO
00047 #endif
00048 
00049 #ifdef HAVE_CONFIG_H
00050 # include <config.h>
00051 #endif
00052 
00053 #if !defined __STDC__ || !__STDC__
00054 /* This is a separate conditional since some stdc systems
00055    reject `defined (const)'.  */
00056 # ifndef const
00057 #  define const
00058 # endif
00059 #endif
00060 
00061 #include <stdio.h>
00062 
00063 /* Comment out all this code if we are using the GNU C Library, and are not
00064    actually compiling the library itself.  This code is part of the GNU C
00065    Library, but also included in many other GNU distributions.  Compiling
00066    and linking in this code is a waste when using the GNU C library
00067    (especially if it is a shared library).  Rather than having every GNU
00068    program understand `configure --with-gnu-libc' and omit the object files,
00069    it is simpler to just do this in the source for each such file.  */
00070 
00071 #define GETOPT_INTERFACE_VERSION 2
00072 #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
00073 # include <gnu-versions.h>
00074 # if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
00075 #  define ELIDE_CODE
00076 # endif
00077 #endif
00078 
00079 #ifndef ELIDE_CODE
00080 
00081 
00082 /* This needs to come after some library #include
00083    to get __GNU_LIBRARY__ defined.  */
00084 #ifdef  __GNU_LIBRARY__
00085 /* Don't include stdlib.h for non-GNU C libraries because some of them
00086    contain conflicting prototypes for getopt.  */
00087 # include <stdlib.h>
00088 # include <unistd.h>
00089 #endif  /* GNU C library.  */
00090 
00091 #include <stdlib.h>
00092 
00093 #ifdef VMS
00094 # include <unixlib.h>
00095 # if HAVE_STRING_H - 0
00096 #  include <string.h>
00097 # endif
00098 #endif
00099 
00100 #ifndef _
00101 /* This is for other GNU distributions with internationalized messages.  */
00102 # if defined HAVE_LIBINTL_H || defined _LIBC
00103 #  include <libintl.h>
00104 #  ifndef _
00105 #   define _(msgid)     gettext (msgid)
00106 #  endif
00107 # else
00108 #  define _(msgid)      (msgid)
00109 # endif
00110 #endif
00111 
00112 /* This version of `getopt' appears to the caller like standard Unix `getopt'
00113    but it behaves differently for the user, since it allows the user
00114    to intersperse the options with the other arguments.
00115 
00116    As `getopt' works, it permutes the elements of ARGV so that,
00117    when it is done, all the options precede everything else.  Thus
00118    all application programs are extended to handle flexible argument order.
00119 
00120    Setting the environment variable POSIXLY_CORRECT disables permutation.
00121    Then the behavior is completely standard.
00122 
00123    GNU application programs can use a third alternative mode in which
00124    they can distinguish the relative order of options and other arguments.  */
00125 
00126 #include "getopt.h"
00127 
00128 /* For communication from `getopt' to the caller.
00129    When `getopt' finds an option that takes an argument,
00130    the argument value is returned here.
00131    Also, when `ordering' is RETURN_IN_ORDER,
00132    each non-option ARGV-element is returned here.  */
00133 
00134 char *optarg;
00135 
00136 /* Index in ARGV of the next element to be scanned.
00137    This is used for communication to and from the caller
00138    and for communication between successive calls to `getopt'.
00139 
00140    On entry to `getopt', zero means this is the first call; initialize.
00141 
00142    When `getopt' returns -1, this is the index of the first of the
00143    non-option elements that the caller should itself scan.
00144 
00145    Otherwise, `optind' communicates from one call to the next
00146    how much of ARGV has been scanned so far.  */
00147 
00148 /* 1003.2 says this must be 1 before any call.  */
00149 int optind = 1;
00150 
00151 /* Formerly, initialization of getopt depended on optind==0, which
00152    causes problems with re-calling getopt as programs generally don't
00153    know that. */
00154 
00155 int __getopt_initialized;
00156 
00157 /* The next char to be scanned in the option-element
00158    in which the last option character we returned was found.
00159    This allows us to pick up the scan where we left off.
00160 
00161    If this is zero, or a null string, it means resume the scan
00162    by advancing to the next ARGV-element.  */
00163 
00164 static char *nextchar;
00165 
00166 /* Callers store zero here to inhibit the error message
00167    for unrecognized options.  */
00168 
00169 int opterr = 1;
00170 
00171 /* Set to an option character which was unrecognized.
00172    This must be initialized on some systems to avoid linking in the
00173    system's own getopt implementation.  */
00174 
00175 int optopt = '?';
00176 
00177 /* Describe how to deal with options that follow non-option ARGV-elements.
00178 
00179    If the caller did not specify anything,
00180    the default is REQUIRE_ORDER if the environment variable
00181    POSIXLY_CORRECT is defined, PERMUTE otherwise.
00182 
00183    REQUIRE_ORDER means don't recognize them as options;
00184    stop option processing when the first non-option is seen.
00185    This is what Unix does.
00186    This mode of operation is selected by either setting the environment
00187    variable POSIXLY_CORRECT, or using `+' as the first character
00188    of the list of option characters.
00189 
00190    PERMUTE is the default.  We permute the contents of ARGV as we scan,
00191    so that eventually all the non-options are at the end.  This allows options
00192    to be given in any order, even with programs that were not written to
00193    expect this.
00194 
00195    RETURN_IN_ORDER is an option available to programs that were written
00196    to expect options and other ARGV-elements in any order and that care about
00197    the ordering of the two.  We describe each non-option ARGV-element
00198    as if it were the argument of an option with character code 1.
00199    Using `-' as the first character of the list of option characters
00200    selects this mode of operation.
00201 
00202    The special argument `--' forces an end of option-scanning regardless
00203    of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
00204    `--' can cause `getopt' to return -1 with `optind' != ARGC.  */
00205 
00206 static enum
00207 {
00208   REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
00209 } ordering;
00210 
00211 /* Value of POSIXLY_CORRECT environment variable.  */
00212 static char *posixly_correct;
00213 
00214 #ifdef  __GNU_LIBRARY__
00215 /* We want to avoid inclusion of string.h with non-GNU libraries
00216    because there are many ways it can cause trouble.
00217    On some systems, it contains special magic macros that don't work
00218    in GCC.  */
00219 # include <string.h>
00220 # define my_index       strchr
00221 #else
00222 
00223 # if HAVE_STRING_H
00224 #  include <string.h>
00225 # else
00226 #  include <strings.h>
00227 # endif
00228 
00229 /* Avoid depending on library functions or files
00230    whose names are inconsistent.  */
00231 
00232 #ifndef getenv
00233 /* extern char *getenv (); */
00234 #endif
00235 
00236 static char *
00237 my_index (const char *str, int chr)
00238 {
00239   while (*str)
00240     {
00241       if (*str == chr)
00242         return (char *) str;
00243       str++;
00244     }
00245   return 0;
00246 }
00247 
00248 /* If using GCC, we can safely declare strlen this way.
00249    If not using GCC, it is ok not to declare it.  */
00250 #ifdef __GNUC__
00251 /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
00252    That was relevant to code that was here before.  */
00253 # if (!defined __STDC__ || !__STDC__) && !defined strlen
00254 /* gcc with -traditional declares the built-in strlen to return int,
00255    and has done so at least since version 2.4.5. -- rms.  */
00256 extern int strlen (const char *);
00257 # endif /* not __STDC__ */
00258 #endif /* __GNUC__ */
00259 
00260 #endif /* not __GNU_LIBRARY__ */
00261 
00262 /* Handle permutation of arguments.  */
00263 
00264 /* Describe the part of ARGV that contains non-options that have
00265    been skipped.  `first_nonopt' is the index in ARGV of the first of them;
00266    `last_nonopt' is the index after the last of them.  */
00267 
00268 static int first_nonopt;
00269 static int last_nonopt;
00270 
00271 #ifdef _LIBC
00272 /* Stored original parameters.
00273    XXX This is no good solution.  We should rather copy the args so
00274    that we can compare them later.  But we must not use malloc(3).  */
00275 extern int __libc_argc;
00276 extern char **__libc_argv;
00277 
00278 /* Bash 2.0 gives us an environment variable containing flags
00279    indicating ARGV elements that should not be considered arguments.  */
00280 
00281 # ifdef USE_NONOPTION_FLAGS
00282 /* Defined in getopt_init.c  */
00283 extern char *__getopt_nonoption_flags;
00284 
00285 static int nonoption_flags_max_len;
00286 static int nonoption_flags_len;
00287 # endif
00288 
00289 # ifdef USE_NONOPTION_FLAGS
00290 #  define SWAP_FLAGS(ch1, ch2) \
00291   if (nonoption_flags_len > 0)                                                \
00292     {                                                                         \
00293       char __tmp = __getopt_nonoption_flags[ch1];                             \
00294       __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2];          \
00295       __getopt_nonoption_flags[ch2] = __tmp;                                  \
00296     }
00297 # else
00298 #  define SWAP_FLAGS(ch1, ch2)
00299 # endif
00300 #else   /* !_LIBC */
00301 # define SWAP_FLAGS(ch1, ch2)
00302 #endif  /* _LIBC */
00303 
00304 /* Exchange two adjacent subsequences of ARGV.
00305    One subsequence is elements [first_nonopt,last_nonopt)
00306    which contains all the non-options that have been skipped so far.
00307    The other is elements [last_nonopt,optind), which contains all
00308    the options processed since those non-options were skipped.
00309 
00310    `first_nonopt' and `last_nonopt' are relocated so that they describe
00311    the new indices of the non-options in ARGV after they are moved.  */
00312 
00313 #if defined __STDC__ && __STDC__
00314 static void exchange (char **);
00315 #endif
00316 
00317 static void
00318 exchange (char **argv)
00319 {
00320   int bottom = first_nonopt;
00321   int middle = last_nonopt;
00322   int top = optind;
00323   char *tem;
00324 
00325   /* Exchange the shorter segment with the far end of the longer segment.
00326      That puts the shorter segment into the right place.
00327      It leaves the longer segment in the right place overall,
00328      but it consists of two parts that need to be swapped next.  */
00329 
00330 #if defined _LIBC && defined USE_NONOPTION_FLAGS
00331   /* First make sure the handling of the `__getopt_nonoption_flags'
00332      string can work normally.  Our top argument must be in the range
00333      of the string.  */
00334   if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len)
00335     {
00336       /* We must extend the array.  The user plays games with us and
00337          presents new arguments.  */
00338       char *new_str = malloc (top + 1);
00339       if (new_str == NULL)
00340         nonoption_flags_len = nonoption_flags_max_len = 0;
00341       else
00342         {
00343           memset (__mempcpy (new_str, __getopt_nonoption_flags,
00344                              nonoption_flags_max_len),
00345                   '\0', top + 1 - nonoption_flags_max_len);
00346           nonoption_flags_max_len = top + 1;
00347           __getopt_nonoption_flags = new_str;
00348         }
00349     }
00350 #endif
00351 
00352   while (top > middle && middle > bottom)
00353     {
00354       if (top - middle > middle - bottom)
00355         {
00356           /* Bottom segment is the short one.  */
00357           int len = middle - bottom;
00358           register int i;
00359 
00360           /* Swap it with the top part of the top segment.  */
00361           for (i = 0; i < len; i++)
00362             {
00363               tem = argv[bottom + i];
00364               argv[bottom + i] = argv[top - (middle - bottom) + i];
00365               argv[top - (middle - bottom) + i] = tem;
00366               SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
00367             }
00368           /* Exclude the moved bottom segment from further swapping.  */
00369           top -= len;
00370         }
00371       else
00372         {
00373           /* Top segment is the short one.  */
00374           int len = top - middle;
00375           register int i;
00376 
00377           /* Swap it with the bottom part of the bottom segment.  */
00378           for (i = 0; i < len; i++)
00379             {
00380               tem = argv[bottom + i];
00381               argv[bottom + i] = argv[middle + i];
00382               argv[middle + i] = tem;
00383               SWAP_FLAGS (bottom + i, middle + i);
00384             }
00385           /* Exclude the moved top segment from further swapping.  */
00386           bottom += len;
00387         }
00388     }
00389 
00390   /* Update records for the slots the non-options now occupy.  */
00391 
00392   first_nonopt += (optind - last_nonopt);
00393   last_nonopt = optind;
00394 }
00395 
00396 /* Initialize the internal data when the first call is made.  */
00397 
00398 #if defined __STDC__ && __STDC__
00399 static const char *_getopt_initialize (int, char *const *, const char *);
00400 #endif
00401 static const char *
00402 _getopt_initialize (int argc, char *const *argv, const char *optstring)
00403 {
00404   /* Start processing options with ARGV-element 1 (since ARGV-element 0
00405      is the program name); the sequence of previously skipped
00406      non-option ARGV-elements is empty.  */
00407 
00408   first_nonopt = last_nonopt = optind;
00409 
00410   nextchar = NULL;
00411 
00412   posixly_correct = getenv ("POSIXLY_CORRECT");
00413 
00414   /* Determine how to handle the ordering of options and nonoptions.  */
00415 
00416   if (optstring[0] == '-')
00417     {
00418       ordering = RETURN_IN_ORDER;
00419       ++optstring;
00420     }
00421   else if (optstring[0] == '+')
00422     {
00423       ordering = REQUIRE_ORDER;
00424       ++optstring;
00425     }
00426   else if (posixly_correct != NULL)
00427     ordering = REQUIRE_ORDER;
00428   else
00429     ordering = PERMUTE;
00430 
00431 #if defined _LIBC && defined USE_NONOPTION_FLAGS
00432   if (posixly_correct == NULL
00433       && argc == __libc_argc && argv == __libc_argv)
00434     {
00435       if (nonoption_flags_max_len == 0)
00436         {
00437           if (__getopt_nonoption_flags == NULL
00438               || __getopt_nonoption_flags[0] == '\0')
00439             nonoption_flags_max_len = -1;
00440           else
00441             {
00442               const char *orig_str = __getopt_nonoption_flags;
00443               int len = nonoption_flags_max_len = strlen (orig_str);
00444               if (nonoption_flags_max_len < argc)
00445                 nonoption_flags_max_len = argc;
00446               __getopt_nonoption_flags =
00447                 (char *) malloc (nonoption_flags_max_len);
00448               if (__getopt_nonoption_flags == NULL)
00449                 nonoption_flags_max_len = -1;
00450               else
00451                 memset (__mempcpy (__getopt_nonoption_flags, orig_str, len),
00452                         '\0', nonoption_flags_max_len - len);
00453             }
00454         }
00455       nonoption_flags_len = nonoption_flags_max_len;
00456     }
00457   else
00458     nonoption_flags_len = 0;
00459 #endif
00460 
00461   return optstring;
00462 }
00463 
00464 /* Scan elements of ARGV (whose length is ARGC) for option characters
00465    given in OPTSTRING.
00466 
00467    If an element of ARGV starts with '-', and is not exactly "-" or "--",
00468    then it is an option element.  The characters of this element
00469    (aside from the initial '-') are option characters.  If `getopt'
00470    is called repeatedly, it returns successively each of the option characters
00471    from each of the option elements.
00472 
00473    If `getopt' finds another option character, it returns that character,
00474    updating `optind' and `nextchar' so that the next call to `getopt' can
00475    resume the scan with the following option character or ARGV-element.
00476 
00477    If there are no more option characters, `getopt' returns -1.
00478    Then `optind' is the index in ARGV of the first ARGV-element
00479    that is not an option.  (The ARGV-elements have been permuted
00480    so that those that are not options now come last.)
00481 
00482    OPTSTRING is a string containing the legitimate option characters.
00483    If an option character is seen that is not listed in OPTSTRING,
00484    return '?' after printing an error message.  If you set `opterr' to
00485    zero, the error message is suppressed but we still return '?'.
00486 
00487    If a char in OPTSTRING is followed by a colon, that means it wants an arg,
00488    so the following text in the same ARGV-element, or the text of the following
00489    ARGV-element, is returned in `optarg'.  Two colons mean an option that
00490    wants an optional arg; if there is text in the current ARGV-element,
00491    it is returned in `optarg', otherwise `optarg' is set to zero.
00492 
00493    If OPTSTRING starts with `-' or `+', it requests different methods of
00494    handling the non-option ARGV-elements.
00495    See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
00496 
00497    Long-named options begin with `--' instead of `-'.
00498    Their names may be abbreviated as long as the abbreviation is unique
00499    or is an exact match for some defined option.  If they have an
00500    argument, it follows the option name in the same ARGV-element, separated
00501    from the option name by a `=', or else the in next ARGV-element.
00502    When `getopt' finds a long-named option, it returns 0 if that option's
00503    `flag' field is nonzero, the value of the option's `val' field
00504    if the `flag' field is zero.
00505 
00506    The elements of ARGV aren't really const, because we permute them.
00507    But we pretend they're const in the prototype to be compatible
00508    with other systems.
00509 
00510    LONGOPTS is a vector of `struct option' terminated by an
00511    element containing a name which is zero.
00512 
00513    LONGIND returns the index in LONGOPT of the long-named option found.
00514    It is only valid when a long-named option has been found by the most
00515    recent call.
00516 
00517    If LONG_ONLY is nonzero, '-' as well as '--' can introduce
00518    long-named options.  */
00519 
00520 int
00521 _getopt_internal (int argc, char *const *argv, const char *optstring,
00522                   const struct option *longopts, int *longind, int long_only)
00523 {
00524   int print_errors = opterr;
00525   if (optstring[0] == ':')
00526     print_errors = 0;
00527 
00528   if (argc < 1)
00529     return -1;
00530 
00531   optarg = NULL;
00532 
00533   if (optind == 0 || !__getopt_initialized)
00534     {
00535       if (optind == 0)
00536         optind = 1;     /* Don't scan ARGV[0], the program name.  */
00537       optstring = _getopt_initialize (argc, argv, optstring);
00538       __getopt_initialized = 1;
00539     }
00540 
00541   /* Test whether ARGV[optind] points to a non-option argument.
00542      Either it does not have option syntax, or there is an environment flag
00543      from the shell indicating it is not an option.  The later information
00544      is only used when the used in the GNU libc.  */
00545 #if defined _LIBC && defined USE_NONOPTION_FLAGS
00546 # define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0'       \
00547                       || (optind < nonoption_flags_len                        \
00548                           && __getopt_nonoption_flags[optind] == '1'))
00549 #else
00550 # define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
00551 #endif
00552 
00553   if (nextchar == NULL || *nextchar == '\0')
00554     {
00555       /* Advance to the next ARGV-element.  */
00556 
00557       /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
00558          moved back by the user (who may also have changed the arguments).  */
00559       if (last_nonopt > optind)
00560         last_nonopt = optind;
00561       if (first_nonopt > optind)
00562         first_nonopt = optind;
00563 
00564       if (ordering == PERMUTE)
00565         {
00566           /* If we have just processed some options following some non-options,
00567              exchange them so that the options come first.  */
00568 
00569           if (first_nonopt != last_nonopt && last_nonopt != optind)
00570             exchange ((char **) argv);
00571           else if (last_nonopt != optind)
00572             first_nonopt = optind;
00573 
00574           /* Skip any additional non-options
00575              and extend the range of non-options previously skipped.  */
00576 
00577           while (optind < argc && NONOPTION_P)
00578             optind++;
00579           last_nonopt = optind;
00580         }
00581 
00582       /* The special ARGV-element `--' means premature end of options.
00583          Skip it like a null option,
00584          then exchange with previous non-options as if it were an option,
00585          then skip everything else like a non-option.  */
00586 
00587       if (optind != argc && !strcmp (argv[optind], "--"))
00588         {
00589           optind++;
00590 
00591           if (first_nonopt != last_nonopt && last_nonopt != optind)
00592             exchange ((char **) argv);
00593           else if (first_nonopt == last_nonopt)
00594             first_nonopt = optind;
00595           last_nonopt = argc;
00596 
00597           optind = argc;
00598         }
00599 
00600       /* If we have done all the ARGV-elements, stop the scan
00601          and back over any non-options that we skipped and permuted.  */
00602 
00603       if (optind == argc)
00604         {
00605           /* Set the next-arg-index to point at the non-options
00606              that we previously skipped, so the caller will digest them.  */
00607           if (first_nonopt != last_nonopt)
00608             optind = first_nonopt;
00609           return -1;
00610         }
00611 
00612       /* If we have come to a non-option and did not permute it,
00613          either stop the scan or describe it to the caller and pass it by.  */
00614 
00615       if (NONOPTION_P)
00616         {
00617           if (ordering == REQUIRE_ORDER)
00618             return -1;
00619           optarg = argv[optind++];
00620           return 1;
00621         }
00622 
00623       /* We have found another option-ARGV-element.
00624          Skip the initial punctuation.  */
00625 
00626       nextchar = (argv[optind] + 1
00627                   + (longopts != NULL && argv[optind][1] == '-'));
00628     }
00629 
00630   /* Decode the current option-ARGV-element.  */
00631 
00632   /* Check whether the ARGV-element is a long option.
00633 
00634      If long_only and the ARGV-element has the form "-f", where f is
00635      a valid short option, don't consider it an abbreviated form of
00636      a long option that starts with f.  Otherwise there would be no
00637      way to give the -f short option.
00638 
00639      On the other hand, if there's a long option "fubar" and
00640      the ARGV-element is "-fu", do consider that an abbreviation of
00641      the long option, just like "--fu", and not "-f" with arg "u".
00642 
00643      This distinction seems to be the most useful approach.  */
00644 
00645   if (longopts != NULL
00646       && (argv[optind][1] == '-'
00647           || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
00648     {
00649       char *nameend;
00650       const struct option *p;
00651       const struct option *pfound = NULL;
00652       int exact = 0;
00653       int ambig = 0;
00654       int indfound = -1;
00655       int option_index;
00656 
00657       for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
00658         /* Do nothing.  */ ;
00659 
00660       /* Test all long options for either exact match
00661          or abbreviated matches.  */
00662       for (p = longopts, option_index = 0; p->name; p++, option_index++)
00663         if (!strncmp (p->name, nextchar, nameend - nextchar))
00664           {
00665             if ((unsigned int) (nameend - nextchar)
00666                 == (unsigned int) strlen (p->name))
00667               {
00668                 /* Exact match found.  */
00669                 pfound = p;
00670                 indfound = option_index;
00671                 exact = 1;
00672                 break;
00673               }
00674             else if (pfound == NULL)
00675               {
00676                 /* First nonexact match found.  */
00677                 pfound = p;
00678                 indfound = option_index;
00679               }
00680             else if (long_only
00681                      || pfound->has_arg != p->has_arg
00682                      || pfound->flag != p->flag
00683                      || pfound->val != p->val)
00684               /* Second or later nonexact match found.  */
00685               ambig = 1;
00686           }
00687 
00688       if (ambig && !exact)
00689         {
00690           if (print_errors)
00691             fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
00692                      argv[0], argv[optind]);
00693           nextchar += strlen (nextchar);
00694           optind++;
00695           optopt = 0;
00696           return '?';
00697         }
00698 
00699       if (pfound != NULL)
00700         {
00701           option_index = indfound;
00702           optind++;
00703           if (*nameend)
00704             {
00705               /* Don't test has_arg with >, because some C compilers don't
00706                  allow it to be used on enums.  */
00707               if (pfound->has_arg)
00708                 optarg = nameend + 1;
00709               else
00710                 {
00711                   if (print_errors)
00712                     {
00713                       if (argv[optind - 1][1] == '-')
00714                         /* --option */
00715                         fprintf (stderr,
00716                                  _("%s: option `--%s' doesn't allow an argument\n"),
00717                                  argv[0], pfound->name);
00718                       else
00719                         /* +option or -option */
00720                         fprintf (stderr,
00721                                  _("%s: option `%c%s' doesn't allow an argument\n"),
00722                                  argv[0], argv[optind - 1][0], pfound->name);
00723                     }
00724 
00725                   nextchar += strlen (nextchar);
00726 
00727                   optopt = pfound->val;
00728                   return '?';
00729                 }
00730             }
00731           else if (pfound->has_arg == 1)
00732             {
00733               if (optind < argc)
00734                 optarg = argv[optind++];
00735               else
00736                 {
00737                   if (print_errors)
00738                     fprintf (stderr,
00739                            _("%s: option `%s' requires an argument\n"),
00740                            argv[0], argv[optind - 1]);
00741                   nextchar += strlen (nextchar);
00742                   optopt = pfound->val;
00743                   return optstring[0] == ':' ? ':' : '?';
00744                 }
00745             }
00746           nextchar += strlen (nextchar);
00747           if (longind != NULL)
00748             *longind = option_index;
00749           if (pfound->flag)
00750             {
00751               *(pfound->flag) = pfound->val;
00752               return 0;
00753             }
00754           return pfound->val;
00755         }
00756 
00757       /* Can't find it as a long option.  If this is not getopt_long_only,
00758          or the option starts with '--' or is not a valid short
00759          option, then it's an error.
00760          Otherwise interpret it as a short option.  */
00761       if (!long_only || argv[optind][1] == '-'
00762           || my_index (optstring, *nextchar) == NULL)
00763         {
00764           if (print_errors)
00765             {
00766               if (argv[optind][1] == '-')
00767                 /* --option */
00768                 fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
00769                          argv[0], nextchar);
00770               else
00771                 /* +option or -option */
00772                 fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
00773                          argv[0], argv[optind][0], nextchar);
00774             }
00775           nextchar = (char *) "";
00776           optind++;
00777           optopt = 0;
00778           return '?';
00779         }
00780     }
00781 
00782   /* Look at and handle the next short option-character.  */
00783 
00784   {
00785     char c = *nextchar++;
00786     char *temp = my_index (optstring, c);
00787 
00788     /* Increment `optind' when we start to process its last character.  */
00789     if (*nextchar == '\0')
00790       ++optind;
00791 
00792     if (temp == NULL || c == ':')
00793       {
00794         if (print_errors)
00795           {
00796             if (posixly_correct)
00797               /* 1003.2 specifies the format of this message.  */
00798               fprintf (stderr, _("%s: illegal option -- %c\n"),
00799                        argv[0], c);
00800             else
00801               fprintf (stderr, _("%s: invalid option -- %c\n"),
00802                        argv[0], c);
00803           }
00804         optopt = c;
00805         return '?';
00806       }
00807     /* Convenience. Treat POSIX -W foo same as long option --foo */
00808     if (temp[0] == 'W' && temp[1] == ';')
00809       {
00810         char *nameend;
00811         const struct option *p;
00812         const struct option *pfound = NULL;
00813         int exact = 0;
00814         int ambig = 0;
00815         int indfound = 0;
00816         int option_index;
00817 
00818         /* This is an option that requires an argument.  */
00819         if (*nextchar != '\0')
00820           {
00821             optarg = nextchar;
00822             /* If we end this ARGV-element by taking the rest as an arg,
00823                we must advance to the next element now.  */
00824             optind++;
00825           }
00826         else if (optind == argc)
00827           {
00828             if (print_errors)
00829               {
00830                 /* 1003.2 specifies the format of this message.  */
00831                 fprintf (stderr, _("%s: option requires an argument -- %c\n"),
00832                          argv[0], c);
00833               }
00834             optopt = c;
00835             if (optstring[0] == ':')
00836               c = ':';
00837             else
00838               c = '?';
00839             return c;
00840           }
00841         else
00842           /* We already incremented `optind' once;
00843              increment it again when taking next ARGV-elt as argument.  */
00844           optarg = argv[optind++];
00845 
00846         /* optarg is now the argument, see if it's in the
00847            table of longopts.  */
00848 
00849         for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++)
00850           /* Do nothing.  */ ;
00851 
00852         /* Test all long options for either exact match
00853            or abbreviated matches.  */
00854         for (p = longopts, option_index = 0; p->name; p++, option_index++)
00855           if (!strncmp (p->name, nextchar, nameend - nextchar))
00856             {
00857               if ((unsigned int) (nameend - nextchar) == strlen (p->name))
00858                 {
00859                   /* Exact match found.  */
00860                   pfound = p;
00861                   indfound = option_index;
00862                   exact = 1;
00863                   break;
00864                 }
00865               else if (pfound == NULL)
00866                 {
00867                   /* First nonexact match found.  */
00868                   pfound = p;
00869                   indfound = option_index;
00870                 }
00871               else
00872                 /* Second or later nonexact match found.  */
00873                 ambig = 1;
00874             }
00875         if (ambig && !exact)
00876           {
00877             if (print_errors)
00878               fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
00879                        argv[0], argv[optind]);
00880             nextchar += strlen (nextchar);
00881             optind++;
00882             return '?';
00883           }
00884         if (pfound != NULL)
00885           {
00886             option_index = indfound;
00887             if (*nameend)
00888               {
00889                 /* Don't test has_arg with >, because some C compilers don't
00890                    allow it to be used on enums.  */
00891                 if (pfound->has_arg)
00892                   optarg = nameend + 1;
00893                 else
00894                   {
00895                     if (print_errors)
00896                       fprintf (stderr, _("\
00897 %s: option `-W %s' doesn't allow an argument\n"),
00898                                argv[0], pfound->name);
00899 
00900                     nextchar += strlen (nextchar);
00901                     return '?';
00902                   }
00903               }
00904             else if (pfound->has_arg == 1)
00905               {
00906                 if (optind < argc)
00907                   optarg = argv[optind++];
00908                 else
00909                   {
00910                     if (print_errors)
00911                       fprintf (stderr,
00912                                _("%s: option `%s' requires an argument\n"),
00913                                argv[0], argv[optind - 1]);
00914                     nextchar += strlen (nextchar);
00915                     return optstring[0] == ':' ? ':' : '?';
00916                   }
00917               }
00918             nextchar += strlen (nextchar);
00919             if (longind != NULL)
00920               *longind = option_index;
00921             if (pfound->flag)
00922               {
00923                 *(pfound->flag) = pfound->val;
00924                 return 0;
00925               }
00926             return pfound->val;
00927           }
00928           nextchar = NULL;
00929           return 'W';   /* Let the application handle it.   */
00930       }
00931     if (temp[1] == ':')
00932       {
00933         if (temp[2] == ':')
00934           {
00935             /* This is an option that accepts an argument optionally.  */
00936             if (*nextchar != '\0')
00937               {
00938                 optarg = nextchar;
00939                 optind++;
00940               }
00941             else
00942               optarg = NULL;
00943             nextchar = NULL;
00944           }
00945         else
00946           {
00947             /* This is an option that requires an argument.  */
00948             if (*nextchar != '\0')
00949               {
00950                 optarg = nextchar;
00951                 /* If we end this ARGV-element by taking the rest as an arg,
00952                    we must advance to the next element now.  */
00953                 optind++;
00954               }
00955             else if (optind == argc)
00956               {
00957                 if (print_errors)
00958                   {
00959                     /* 1003.2 specifies the format of this message.  */
00960                     fprintf (stderr,
00961                              _("%s: option requires an argument -- %c\n"),
00962                              argv[0], c);
00963                   }
00964                 optopt = c;
00965                 if (optstring[0] == ':')
00966                   c = ':';
00967                 else
00968                   c = '?';
00969               }
00970             else
00971               /* We already incremented `optind' once;
00972                  increment it again when taking next ARGV-elt as argument.  */
00973               optarg = argv[optind++];
00974             nextchar = NULL;
00975           }
00976       }
00977     return c;
00978   }
00979 }
00980 
00981 int
00982 getopt (int argc, char *const *argv, const char *optstring)
00983 {
00984   return _getopt_internal (argc, argv, optstring,
00985                            (const struct option *) 0,
00986                            (int *) 0,
00987                            0);
00988 }
00989 
00990 #endif  /* Not ELIDE_CODE.  */
00991 
00992 #ifdef TEST
00993 
00994 /* Compile with -DTEST to make an executable for use in testing
00995    the above definition of `getopt'.  */
00996 
00997 int
00998 main (int argc, char **argv)
00999 {
01000   int c;
01001   int digit_optind = 0;
01002 
01003   while (1)
01004     {
01005       int this_option_optind = optind ? optind : 1;
01006 
01007       c = getopt (argc, argv, "abc:d:0123456789");
01008       if (c == -1)
01009         break;
01010 
01011       switch (c)
01012         {
01013         case '0':
01014         case '1':
01015         case '2':
01016         case '3':
01017         case '4':
01018         case '5':
01019         case '6':
01020         case '7':
01021         case '8':
01022         case '9':
01023           if (digit_optind != 0 && digit_optind != this_option_optind)
01024             printf ("digits occur in two different argv-elements.\n");
01025           digit_optind = this_option_optind;
01026           printf ("option %c\n", c);
01027           break;
01028 
01029         case 'a':
01030           printf ("option a\n");
01031           break;
01032 
01033         case 'b':
01034           printf ("option b\n");
01035           break;
01036 
01037         case 'c':
01038           printf ("option c with value `%s'\n", optarg);
01039           break;
01040 
01041         case '?':
01042           break;
01043 
01044         default:
01045           printf ("?? getopt returned character code 0%o ??\n", c);
01046         }
01047     }
01048 
01049   if (optind < argc)
01050     {
01051       printf ("non-option ARGV-elements: ");
01052       while (optind < argc)
01053         printf ("%s ", argv[optind++]);
01054       printf ("\n");
01055     }
01056 
01057   exit (0);
01058 }
01059 
01060 #endif /* TEST */

Generated on Mon Oct 6 02:31:35 2008 for LAL by  doxygen 1.5.2