1*9663SMark.Logan@Sun.COM /* Getopt for GNU. 2*9663SMark.Logan@Sun.COM NOTE: getopt is now part of the C library, so if you don't know what 3*9663SMark.Logan@Sun.COM "Keep this file name-space clean" means, talk to drepper@gnu.org 4*9663SMark.Logan@Sun.COM before changing it! 5*9663SMark.Logan@Sun.COM Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002,2003,2004,2006 6*9663SMark.Logan@Sun.COM Free Software Foundation, Inc. 7*9663SMark.Logan@Sun.COM This file is part of the GNU C Library. 8*9663SMark.Logan@Sun.COM 9*9663SMark.Logan@Sun.COM This program is free software; you can redistribute it and/or modify 10*9663SMark.Logan@Sun.COM it under the terms of the GNU General Public License as published by 11*9663SMark.Logan@Sun.COM the Free Software Foundation; either version 2, or (at your option) 12*9663SMark.Logan@Sun.COM any later version. 13*9663SMark.Logan@Sun.COM 14*9663SMark.Logan@Sun.COM This program is distributed in the hope that it will be useful, 15*9663SMark.Logan@Sun.COM but WITHOUT ANY WARRANTY; without even the implied warranty of 16*9663SMark.Logan@Sun.COM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17*9663SMark.Logan@Sun.COM GNU General Public License for more details. 18*9663SMark.Logan@Sun.COM 19*9663SMark.Logan@Sun.COM You should have received a copy of the GNU General Public License along 20*9663SMark.Logan@Sun.COM with this program; if not, write to the Free Software Foundation, 21*9663SMark.Logan@Sun.COM Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 22*9663SMark.Logan@Sun.COM 23*9663SMark.Logan@Sun.COM #ifndef _LIBC 24*9663SMark.Logan@Sun.COM # include <config.h> 25*9663SMark.Logan@Sun.COM #endif 26*9663SMark.Logan@Sun.COM 27*9663SMark.Logan@Sun.COM #include "getopt.h" 28*9663SMark.Logan@Sun.COM 29*9663SMark.Logan@Sun.COM #include <stdio.h> 30*9663SMark.Logan@Sun.COM #include <stdlib.h> 31*9663SMark.Logan@Sun.COM #include <string.h> 32*9663SMark.Logan@Sun.COM #include <unistd.h> 33*9663SMark.Logan@Sun.COM 34*9663SMark.Logan@Sun.COM #ifdef __VMS 35*9663SMark.Logan@Sun.COM # include <unixlib.h> 36*9663SMark.Logan@Sun.COM #endif 37*9663SMark.Logan@Sun.COM 38*9663SMark.Logan@Sun.COM #ifdef _LIBC 39*9663SMark.Logan@Sun.COM # include <libintl.h> 40*9663SMark.Logan@Sun.COM #else 41*9663SMark.Logan@Sun.COM # include "gettext.h" 42*9663SMark.Logan@Sun.COM # define _(msgid) gettext (msgid) 43*9663SMark.Logan@Sun.COM #endif 44*9663SMark.Logan@Sun.COM 45*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO 46*9663SMark.Logan@Sun.COM # include <wchar.h> 47*9663SMark.Logan@Sun.COM #endif 48*9663SMark.Logan@Sun.COM 49*9663SMark.Logan@Sun.COM #ifndef attribute_hidden 50*9663SMark.Logan@Sun.COM # define attribute_hidden 51*9663SMark.Logan@Sun.COM #endif 52*9663SMark.Logan@Sun.COM 53*9663SMark.Logan@Sun.COM /* Unlike standard Unix `getopt', functions like `getopt_long' 54*9663SMark.Logan@Sun.COM let the user intersperse the options with the other arguments. 55*9663SMark.Logan@Sun.COM 56*9663SMark.Logan@Sun.COM As `getopt_long' works, it permutes the elements of ARGV so that, 57*9663SMark.Logan@Sun.COM when it is done, all the options precede everything else. Thus 58*9663SMark.Logan@Sun.COM all application programs are extended to handle flexible argument order. 59*9663SMark.Logan@Sun.COM 60*9663SMark.Logan@Sun.COM Using `getopt' or setting the environment variable POSIXLY_CORRECT 61*9663SMark.Logan@Sun.COM disables permutation. 62*9663SMark.Logan@Sun.COM Then the application's behavior is completely standard. 63*9663SMark.Logan@Sun.COM 64*9663SMark.Logan@Sun.COM GNU application programs can use a third alternative mode in which 65*9663SMark.Logan@Sun.COM they can distinguish the relative order of options and other arguments. */ 66*9663SMark.Logan@Sun.COM 67*9663SMark.Logan@Sun.COM #include "getopt_int.h" 68*9663SMark.Logan@Sun.COM 69*9663SMark.Logan@Sun.COM /* For communication from `getopt' to the caller. 70*9663SMark.Logan@Sun.COM When `getopt' finds an option that takes an argument, 71*9663SMark.Logan@Sun.COM the argument value is returned here. 72*9663SMark.Logan@Sun.COM Also, when `ordering' is RETURN_IN_ORDER, 73*9663SMark.Logan@Sun.COM each non-option ARGV-element is returned here. */ 74*9663SMark.Logan@Sun.COM 75*9663SMark.Logan@Sun.COM char *optarg; 76*9663SMark.Logan@Sun.COM 77*9663SMark.Logan@Sun.COM /* Index in ARGV of the next element to be scanned. 78*9663SMark.Logan@Sun.COM This is used for communication to and from the caller 79*9663SMark.Logan@Sun.COM and for communication between successive calls to `getopt'. 80*9663SMark.Logan@Sun.COM 81*9663SMark.Logan@Sun.COM On entry to `getopt', zero means this is the first call; initialize. 82*9663SMark.Logan@Sun.COM 83*9663SMark.Logan@Sun.COM When `getopt' returns -1, this is the index of the first of the 84*9663SMark.Logan@Sun.COM non-option elements that the caller should itself scan. 85*9663SMark.Logan@Sun.COM 86*9663SMark.Logan@Sun.COM Otherwise, `optind' communicates from one call to the next 87*9663SMark.Logan@Sun.COM how much of ARGV has been scanned so far. */ 88*9663SMark.Logan@Sun.COM 89*9663SMark.Logan@Sun.COM /* 1003.2 says this must be 1 before any call. */ 90*9663SMark.Logan@Sun.COM int optind = 1; 91*9663SMark.Logan@Sun.COM 92*9663SMark.Logan@Sun.COM /* Callers store zero here to inhibit the error message 93*9663SMark.Logan@Sun.COM for unrecognized options. */ 94*9663SMark.Logan@Sun.COM 95*9663SMark.Logan@Sun.COM int opterr = 1; 96*9663SMark.Logan@Sun.COM 97*9663SMark.Logan@Sun.COM /* Set to an option character which was unrecognized. 98*9663SMark.Logan@Sun.COM This must be initialized on some systems to avoid linking in the 99*9663SMark.Logan@Sun.COM system's own getopt implementation. */ 100*9663SMark.Logan@Sun.COM 101*9663SMark.Logan@Sun.COM int optopt = '?'; 102*9663SMark.Logan@Sun.COM 103*9663SMark.Logan@Sun.COM /* Keep a global copy of all internal members of getopt_data. */ 104*9663SMark.Logan@Sun.COM 105*9663SMark.Logan@Sun.COM static struct _getopt_data getopt_data; 106*9663SMark.Logan@Sun.COM 107*9663SMark.Logan@Sun.COM 108*9663SMark.Logan@Sun.COM #if defined HAVE_DECL_GETENV && !HAVE_DECL_GETENV 109*9663SMark.Logan@Sun.COM extern char *getenv (); 110*9663SMark.Logan@Sun.COM #endif 111*9663SMark.Logan@Sun.COM 112*9663SMark.Logan@Sun.COM #ifdef _LIBC 113*9663SMark.Logan@Sun.COM /* Stored original parameters. 114*9663SMark.Logan@Sun.COM XXX This is no good solution. We should rather copy the args so 115*9663SMark.Logan@Sun.COM that we can compare them later. But we must not use malloc(3). */ 116*9663SMark.Logan@Sun.COM extern int __libc_argc; 117*9663SMark.Logan@Sun.COM extern char **__libc_argv; 118*9663SMark.Logan@Sun.COM 119*9663SMark.Logan@Sun.COM /* Bash 2.0 gives us an environment variable containing flags 120*9663SMark.Logan@Sun.COM indicating ARGV elements that should not be considered arguments. */ 121*9663SMark.Logan@Sun.COM 122*9663SMark.Logan@Sun.COM # ifdef USE_NONOPTION_FLAGS 123*9663SMark.Logan@Sun.COM /* Defined in getopt_init.c */ 124*9663SMark.Logan@Sun.COM extern char *__getopt_nonoption_flags; 125*9663SMark.Logan@Sun.COM # endif 126*9663SMark.Logan@Sun.COM 127*9663SMark.Logan@Sun.COM # ifdef USE_NONOPTION_FLAGS 128*9663SMark.Logan@Sun.COM # define SWAP_FLAGS(ch1, ch2) \ 129*9663SMark.Logan@Sun.COM if (d->__nonoption_flags_len > 0) \ 130*9663SMark.Logan@Sun.COM { \ 131*9663SMark.Logan@Sun.COM char __tmp = __getopt_nonoption_flags[ch1]; \ 132*9663SMark.Logan@Sun.COM __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ 133*9663SMark.Logan@Sun.COM __getopt_nonoption_flags[ch2] = __tmp; \ 134*9663SMark.Logan@Sun.COM } 135*9663SMark.Logan@Sun.COM # else 136*9663SMark.Logan@Sun.COM # define SWAP_FLAGS(ch1, ch2) 137*9663SMark.Logan@Sun.COM # endif 138*9663SMark.Logan@Sun.COM #else /* !_LIBC */ 139*9663SMark.Logan@Sun.COM # define SWAP_FLAGS(ch1, ch2) 140*9663SMark.Logan@Sun.COM #endif /* _LIBC */ 141*9663SMark.Logan@Sun.COM 142*9663SMark.Logan@Sun.COM /* Exchange two adjacent subsequences of ARGV. 143*9663SMark.Logan@Sun.COM One subsequence is elements [first_nonopt,last_nonopt) 144*9663SMark.Logan@Sun.COM which contains all the non-options that have been skipped so far. 145*9663SMark.Logan@Sun.COM The other is elements [last_nonopt,optind), which contains all 146*9663SMark.Logan@Sun.COM the options processed since those non-options were skipped. 147*9663SMark.Logan@Sun.COM 148*9663SMark.Logan@Sun.COM `first_nonopt' and `last_nonopt' are relocated so that they describe 149*9663SMark.Logan@Sun.COM the new indices of the non-options in ARGV after they are moved. */ 150*9663SMark.Logan@Sun.COM 151*9663SMark.Logan@Sun.COM static void 152*9663SMark.Logan@Sun.COM exchange (char **argv, struct _getopt_data *d) 153*9663SMark.Logan@Sun.COM { 154*9663SMark.Logan@Sun.COM int bottom = d->__first_nonopt; 155*9663SMark.Logan@Sun.COM int middle = d->__last_nonopt; 156*9663SMark.Logan@Sun.COM int top = d->optind; 157*9663SMark.Logan@Sun.COM char *tem; 158*9663SMark.Logan@Sun.COM 159*9663SMark.Logan@Sun.COM /* Exchange the shorter segment with the far end of the longer segment. 160*9663SMark.Logan@Sun.COM That puts the shorter segment into the right place. 161*9663SMark.Logan@Sun.COM It leaves the longer segment in the right place overall, 162*9663SMark.Logan@Sun.COM but it consists of two parts that need to be swapped next. */ 163*9663SMark.Logan@Sun.COM 164*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_NONOPTION_FLAGS 165*9663SMark.Logan@Sun.COM /* First make sure the handling of the `__getopt_nonoption_flags' 166*9663SMark.Logan@Sun.COM string can work normally. Our top argument must be in the range 167*9663SMark.Logan@Sun.COM of the string. */ 168*9663SMark.Logan@Sun.COM if (d->__nonoption_flags_len > 0 && top >= d->__nonoption_flags_max_len) 169*9663SMark.Logan@Sun.COM { 170*9663SMark.Logan@Sun.COM /* We must extend the array. The user plays games with us and 171*9663SMark.Logan@Sun.COM presents new arguments. */ 172*9663SMark.Logan@Sun.COM char *new_str = malloc (top + 1); 173*9663SMark.Logan@Sun.COM if (new_str == NULL) 174*9663SMark.Logan@Sun.COM d->__nonoption_flags_len = d->__nonoption_flags_max_len = 0; 175*9663SMark.Logan@Sun.COM else 176*9663SMark.Logan@Sun.COM { 177*9663SMark.Logan@Sun.COM memset (__mempcpy (new_str, __getopt_nonoption_flags, 178*9663SMark.Logan@Sun.COM d->__nonoption_flags_max_len), 179*9663SMark.Logan@Sun.COM '\0', top + 1 - d->__nonoption_flags_max_len); 180*9663SMark.Logan@Sun.COM d->__nonoption_flags_max_len = top + 1; 181*9663SMark.Logan@Sun.COM __getopt_nonoption_flags = new_str; 182*9663SMark.Logan@Sun.COM } 183*9663SMark.Logan@Sun.COM } 184*9663SMark.Logan@Sun.COM #endif 185*9663SMark.Logan@Sun.COM 186*9663SMark.Logan@Sun.COM while (top > middle && middle > bottom) 187*9663SMark.Logan@Sun.COM { 188*9663SMark.Logan@Sun.COM if (top - middle > middle - bottom) 189*9663SMark.Logan@Sun.COM { 190*9663SMark.Logan@Sun.COM /* Bottom segment is the short one. */ 191*9663SMark.Logan@Sun.COM int len = middle - bottom; 192*9663SMark.Logan@Sun.COM register int i; 193*9663SMark.Logan@Sun.COM 194*9663SMark.Logan@Sun.COM /* Swap it with the top part of the top segment. */ 195*9663SMark.Logan@Sun.COM for (i = 0; i < len; i++) 196*9663SMark.Logan@Sun.COM { 197*9663SMark.Logan@Sun.COM tem = argv[bottom + i]; 198*9663SMark.Logan@Sun.COM argv[bottom + i] = argv[top - (middle - bottom) + i]; 199*9663SMark.Logan@Sun.COM argv[top - (middle - bottom) + i] = tem; 200*9663SMark.Logan@Sun.COM SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); 201*9663SMark.Logan@Sun.COM } 202*9663SMark.Logan@Sun.COM /* Exclude the moved bottom segment from further swapping. */ 203*9663SMark.Logan@Sun.COM top -= len; 204*9663SMark.Logan@Sun.COM } 205*9663SMark.Logan@Sun.COM else 206*9663SMark.Logan@Sun.COM { 207*9663SMark.Logan@Sun.COM /* Top segment is the short one. */ 208*9663SMark.Logan@Sun.COM int len = top - middle; 209*9663SMark.Logan@Sun.COM register int i; 210*9663SMark.Logan@Sun.COM 211*9663SMark.Logan@Sun.COM /* Swap it with the bottom part of the bottom segment. */ 212*9663SMark.Logan@Sun.COM for (i = 0; i < len; i++) 213*9663SMark.Logan@Sun.COM { 214*9663SMark.Logan@Sun.COM tem = argv[bottom + i]; 215*9663SMark.Logan@Sun.COM argv[bottom + i] = argv[middle + i]; 216*9663SMark.Logan@Sun.COM argv[middle + i] = tem; 217*9663SMark.Logan@Sun.COM SWAP_FLAGS (bottom + i, middle + i); 218*9663SMark.Logan@Sun.COM } 219*9663SMark.Logan@Sun.COM /* Exclude the moved top segment from further swapping. */ 220*9663SMark.Logan@Sun.COM bottom += len; 221*9663SMark.Logan@Sun.COM } 222*9663SMark.Logan@Sun.COM } 223*9663SMark.Logan@Sun.COM 224*9663SMark.Logan@Sun.COM /* Update records for the slots the non-options now occupy. */ 225*9663SMark.Logan@Sun.COM 226*9663SMark.Logan@Sun.COM d->__first_nonopt += (d->optind - d->__last_nonopt); 227*9663SMark.Logan@Sun.COM d->__last_nonopt = d->optind; 228*9663SMark.Logan@Sun.COM } 229*9663SMark.Logan@Sun.COM 230*9663SMark.Logan@Sun.COM /* Initialize the internal data when the first call is made. */ 231*9663SMark.Logan@Sun.COM 232*9663SMark.Logan@Sun.COM static const char * 233*9663SMark.Logan@Sun.COM _getopt_initialize (int argc, char **argv, const char *optstring, 234*9663SMark.Logan@Sun.COM int posixly_correct, struct _getopt_data *d) 235*9663SMark.Logan@Sun.COM { 236*9663SMark.Logan@Sun.COM /* Start processing options with ARGV-element 1 (since ARGV-element 0 237*9663SMark.Logan@Sun.COM is the program name); the sequence of previously skipped 238*9663SMark.Logan@Sun.COM non-option ARGV-elements is empty. */ 239*9663SMark.Logan@Sun.COM 240*9663SMark.Logan@Sun.COM d->__first_nonopt = d->__last_nonopt = d->optind; 241*9663SMark.Logan@Sun.COM 242*9663SMark.Logan@Sun.COM d->__nextchar = NULL; 243*9663SMark.Logan@Sun.COM 244*9663SMark.Logan@Sun.COM d->__posixly_correct = posixly_correct || !!getenv ("POSIXLY_CORRECT"); 245*9663SMark.Logan@Sun.COM 246*9663SMark.Logan@Sun.COM /* Determine how to handle the ordering of options and nonoptions. */ 247*9663SMark.Logan@Sun.COM 248*9663SMark.Logan@Sun.COM if (optstring[0] == '-') 249*9663SMark.Logan@Sun.COM { 250*9663SMark.Logan@Sun.COM d->__ordering = RETURN_IN_ORDER; 251*9663SMark.Logan@Sun.COM ++optstring; 252*9663SMark.Logan@Sun.COM } 253*9663SMark.Logan@Sun.COM else if (optstring[0] == '+') 254*9663SMark.Logan@Sun.COM { 255*9663SMark.Logan@Sun.COM d->__ordering = REQUIRE_ORDER; 256*9663SMark.Logan@Sun.COM ++optstring; 257*9663SMark.Logan@Sun.COM } 258*9663SMark.Logan@Sun.COM else if (d->__posixly_correct) 259*9663SMark.Logan@Sun.COM d->__ordering = REQUIRE_ORDER; 260*9663SMark.Logan@Sun.COM else 261*9663SMark.Logan@Sun.COM d->__ordering = PERMUTE; 262*9663SMark.Logan@Sun.COM 263*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_NONOPTION_FLAGS 264*9663SMark.Logan@Sun.COM if (!d->__posixly_correct 265*9663SMark.Logan@Sun.COM && argc == __libc_argc && argv == __libc_argv) 266*9663SMark.Logan@Sun.COM { 267*9663SMark.Logan@Sun.COM if (d->__nonoption_flags_max_len == 0) 268*9663SMark.Logan@Sun.COM { 269*9663SMark.Logan@Sun.COM if (__getopt_nonoption_flags == NULL 270*9663SMark.Logan@Sun.COM || __getopt_nonoption_flags[0] == '\0') 271*9663SMark.Logan@Sun.COM d->__nonoption_flags_max_len = -1; 272*9663SMark.Logan@Sun.COM else 273*9663SMark.Logan@Sun.COM { 274*9663SMark.Logan@Sun.COM const char *orig_str = __getopt_nonoption_flags; 275*9663SMark.Logan@Sun.COM int len = d->__nonoption_flags_max_len = strlen (orig_str); 276*9663SMark.Logan@Sun.COM if (d->__nonoption_flags_max_len < argc) 277*9663SMark.Logan@Sun.COM d->__nonoption_flags_max_len = argc; 278*9663SMark.Logan@Sun.COM __getopt_nonoption_flags = 279*9663SMark.Logan@Sun.COM (char *) malloc (d->__nonoption_flags_max_len); 280*9663SMark.Logan@Sun.COM if (__getopt_nonoption_flags == NULL) 281*9663SMark.Logan@Sun.COM d->__nonoption_flags_max_len = -1; 282*9663SMark.Logan@Sun.COM else 283*9663SMark.Logan@Sun.COM memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), 284*9663SMark.Logan@Sun.COM '\0', d->__nonoption_flags_max_len - len); 285*9663SMark.Logan@Sun.COM } 286*9663SMark.Logan@Sun.COM } 287*9663SMark.Logan@Sun.COM d->__nonoption_flags_len = d->__nonoption_flags_max_len; 288*9663SMark.Logan@Sun.COM } 289*9663SMark.Logan@Sun.COM else 290*9663SMark.Logan@Sun.COM d->__nonoption_flags_len = 0; 291*9663SMark.Logan@Sun.COM #endif 292*9663SMark.Logan@Sun.COM 293*9663SMark.Logan@Sun.COM return optstring; 294*9663SMark.Logan@Sun.COM } 295*9663SMark.Logan@Sun.COM 296*9663SMark.Logan@Sun.COM /* Scan elements of ARGV (whose length is ARGC) for option characters 297*9663SMark.Logan@Sun.COM given in OPTSTRING. 298*9663SMark.Logan@Sun.COM 299*9663SMark.Logan@Sun.COM If an element of ARGV starts with '-', and is not exactly "-" or "--", 300*9663SMark.Logan@Sun.COM then it is an option element. The characters of this element 301*9663SMark.Logan@Sun.COM (aside from the initial '-') are option characters. If `getopt' 302*9663SMark.Logan@Sun.COM is called repeatedly, it returns successively each of the option characters 303*9663SMark.Logan@Sun.COM from each of the option elements. 304*9663SMark.Logan@Sun.COM 305*9663SMark.Logan@Sun.COM If `getopt' finds another option character, it returns that character, 306*9663SMark.Logan@Sun.COM updating `optind' and `nextchar' so that the next call to `getopt' can 307*9663SMark.Logan@Sun.COM resume the scan with the following option character or ARGV-element. 308*9663SMark.Logan@Sun.COM 309*9663SMark.Logan@Sun.COM If there are no more option characters, `getopt' returns -1. 310*9663SMark.Logan@Sun.COM Then `optind' is the index in ARGV of the first ARGV-element 311*9663SMark.Logan@Sun.COM that is not an option. (The ARGV-elements have been permuted 312*9663SMark.Logan@Sun.COM so that those that are not options now come last.) 313*9663SMark.Logan@Sun.COM 314*9663SMark.Logan@Sun.COM OPTSTRING is a string containing the legitimate option characters. 315*9663SMark.Logan@Sun.COM If an option character is seen that is not listed in OPTSTRING, 316*9663SMark.Logan@Sun.COM return '?' after printing an error message. If you set `opterr' to 317*9663SMark.Logan@Sun.COM zero, the error message is suppressed but we still return '?'. 318*9663SMark.Logan@Sun.COM 319*9663SMark.Logan@Sun.COM If a char in OPTSTRING is followed by a colon, that means it wants an arg, 320*9663SMark.Logan@Sun.COM so the following text in the same ARGV-element, or the text of the following 321*9663SMark.Logan@Sun.COM ARGV-element, is returned in `optarg'. Two colons mean an option that 322*9663SMark.Logan@Sun.COM wants an optional arg; if there is text in the current ARGV-element, 323*9663SMark.Logan@Sun.COM it is returned in `optarg', otherwise `optarg' is set to zero. 324*9663SMark.Logan@Sun.COM 325*9663SMark.Logan@Sun.COM If OPTSTRING starts with `-' or `+', it requests different methods of 326*9663SMark.Logan@Sun.COM handling the non-option ARGV-elements. 327*9663SMark.Logan@Sun.COM See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. 328*9663SMark.Logan@Sun.COM 329*9663SMark.Logan@Sun.COM Long-named options begin with `--' instead of `-'. 330*9663SMark.Logan@Sun.COM Their names may be abbreviated as long as the abbreviation is unique 331*9663SMark.Logan@Sun.COM or is an exact match for some defined option. If they have an 332*9663SMark.Logan@Sun.COM argument, it follows the option name in the same ARGV-element, separated 333*9663SMark.Logan@Sun.COM from the option name by a `=', or else the in next ARGV-element. 334*9663SMark.Logan@Sun.COM When `getopt' finds a long-named option, it returns 0 if that option's 335*9663SMark.Logan@Sun.COM `flag' field is nonzero, the value of the option's `val' field 336*9663SMark.Logan@Sun.COM if the `flag' field is zero. 337*9663SMark.Logan@Sun.COM 338*9663SMark.Logan@Sun.COM LONGOPTS is a vector of `struct option' terminated by an 339*9663SMark.Logan@Sun.COM element containing a name which is zero. 340*9663SMark.Logan@Sun.COM 341*9663SMark.Logan@Sun.COM LONGIND returns the index in LONGOPT of the long-named option found. 342*9663SMark.Logan@Sun.COM It is only valid when a long-named option has been found by the most 343*9663SMark.Logan@Sun.COM recent call. 344*9663SMark.Logan@Sun.COM 345*9663SMark.Logan@Sun.COM If LONG_ONLY is nonzero, '-' as well as '--' can introduce 346*9663SMark.Logan@Sun.COM long-named options. 347*9663SMark.Logan@Sun.COM 348*9663SMark.Logan@Sun.COM If POSIXLY_CORRECT is nonzero, behave as if the POSIXLY_CORRECT 349*9663SMark.Logan@Sun.COM environment variable were set. */ 350*9663SMark.Logan@Sun.COM 351*9663SMark.Logan@Sun.COM int 352*9663SMark.Logan@Sun.COM _getopt_internal_r (int argc, char **argv, const char *optstring, 353*9663SMark.Logan@Sun.COM const struct option *longopts, int *longind, 354*9663SMark.Logan@Sun.COM int long_only, int posixly_correct, struct _getopt_data *d) 355*9663SMark.Logan@Sun.COM { 356*9663SMark.Logan@Sun.COM int print_errors = d->opterr; 357*9663SMark.Logan@Sun.COM if (optstring[0] == ':') 358*9663SMark.Logan@Sun.COM print_errors = 0; 359*9663SMark.Logan@Sun.COM 360*9663SMark.Logan@Sun.COM if (argc < 1) 361*9663SMark.Logan@Sun.COM return -1; 362*9663SMark.Logan@Sun.COM 363*9663SMark.Logan@Sun.COM d->optarg = NULL; 364*9663SMark.Logan@Sun.COM 365*9663SMark.Logan@Sun.COM if (d->optind == 0 || !d->__initialized) 366*9663SMark.Logan@Sun.COM { 367*9663SMark.Logan@Sun.COM if (d->optind == 0) 368*9663SMark.Logan@Sun.COM d->optind = 1; /* Don't scan ARGV[0], the program name. */ 369*9663SMark.Logan@Sun.COM optstring = _getopt_initialize (argc, argv, optstring, 370*9663SMark.Logan@Sun.COM posixly_correct, d); 371*9663SMark.Logan@Sun.COM d->__initialized = 1; 372*9663SMark.Logan@Sun.COM } 373*9663SMark.Logan@Sun.COM 374*9663SMark.Logan@Sun.COM /* Test whether ARGV[optind] points to a non-option argument. 375*9663SMark.Logan@Sun.COM Either it does not have option syntax, or there is an environment flag 376*9663SMark.Logan@Sun.COM from the shell indicating it is not an option. The later information 377*9663SMark.Logan@Sun.COM is only used when the used in the GNU libc. */ 378*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_NONOPTION_FLAGS 379*9663SMark.Logan@Sun.COM # define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0' \ 380*9663SMark.Logan@Sun.COM || (d->optind < d->__nonoption_flags_len \ 381*9663SMark.Logan@Sun.COM && __getopt_nonoption_flags[d->optind] == '1')) 382*9663SMark.Logan@Sun.COM #else 383*9663SMark.Logan@Sun.COM # define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0') 384*9663SMark.Logan@Sun.COM #endif 385*9663SMark.Logan@Sun.COM 386*9663SMark.Logan@Sun.COM if (d->__nextchar == NULL || *d->__nextchar == '\0') 387*9663SMark.Logan@Sun.COM { 388*9663SMark.Logan@Sun.COM /* Advance to the next ARGV-element. */ 389*9663SMark.Logan@Sun.COM 390*9663SMark.Logan@Sun.COM /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been 391*9663SMark.Logan@Sun.COM moved back by the user (who may also have changed the arguments). */ 392*9663SMark.Logan@Sun.COM if (d->__last_nonopt > d->optind) 393*9663SMark.Logan@Sun.COM d->__last_nonopt = d->optind; 394*9663SMark.Logan@Sun.COM if (d->__first_nonopt > d->optind) 395*9663SMark.Logan@Sun.COM d->__first_nonopt = d->optind; 396*9663SMark.Logan@Sun.COM 397*9663SMark.Logan@Sun.COM if (d->__ordering == PERMUTE) 398*9663SMark.Logan@Sun.COM { 399*9663SMark.Logan@Sun.COM /* If we have just processed some options following some non-options, 400*9663SMark.Logan@Sun.COM exchange them so that the options come first. */ 401*9663SMark.Logan@Sun.COM 402*9663SMark.Logan@Sun.COM if (d->__first_nonopt != d->__last_nonopt 403*9663SMark.Logan@Sun.COM && d->__last_nonopt != d->optind) 404*9663SMark.Logan@Sun.COM exchange ((char **) argv, d); 405*9663SMark.Logan@Sun.COM else if (d->__last_nonopt != d->optind) 406*9663SMark.Logan@Sun.COM d->__first_nonopt = d->optind; 407*9663SMark.Logan@Sun.COM 408*9663SMark.Logan@Sun.COM /* Skip any additional non-options 409*9663SMark.Logan@Sun.COM and extend the range of non-options previously skipped. */ 410*9663SMark.Logan@Sun.COM 411*9663SMark.Logan@Sun.COM while (d->optind < argc && NONOPTION_P) 412*9663SMark.Logan@Sun.COM d->optind++; 413*9663SMark.Logan@Sun.COM d->__last_nonopt = d->optind; 414*9663SMark.Logan@Sun.COM } 415*9663SMark.Logan@Sun.COM 416*9663SMark.Logan@Sun.COM /* The special ARGV-element `--' means premature end of options. 417*9663SMark.Logan@Sun.COM Skip it like a null option, 418*9663SMark.Logan@Sun.COM then exchange with previous non-options as if it were an option, 419*9663SMark.Logan@Sun.COM then skip everything else like a non-option. */ 420*9663SMark.Logan@Sun.COM 421*9663SMark.Logan@Sun.COM if (d->optind != argc && !strcmp (argv[d->optind], "--")) 422*9663SMark.Logan@Sun.COM { 423*9663SMark.Logan@Sun.COM d->optind++; 424*9663SMark.Logan@Sun.COM 425*9663SMark.Logan@Sun.COM if (d->__first_nonopt != d->__last_nonopt 426*9663SMark.Logan@Sun.COM && d->__last_nonopt != d->optind) 427*9663SMark.Logan@Sun.COM exchange ((char **) argv, d); 428*9663SMark.Logan@Sun.COM else if (d->__first_nonopt == d->__last_nonopt) 429*9663SMark.Logan@Sun.COM d->__first_nonopt = d->optind; 430*9663SMark.Logan@Sun.COM d->__last_nonopt = argc; 431*9663SMark.Logan@Sun.COM 432*9663SMark.Logan@Sun.COM d->optind = argc; 433*9663SMark.Logan@Sun.COM } 434*9663SMark.Logan@Sun.COM 435*9663SMark.Logan@Sun.COM /* If we have done all the ARGV-elements, stop the scan 436*9663SMark.Logan@Sun.COM and back over any non-options that we skipped and permuted. */ 437*9663SMark.Logan@Sun.COM 438*9663SMark.Logan@Sun.COM if (d->optind == argc) 439*9663SMark.Logan@Sun.COM { 440*9663SMark.Logan@Sun.COM /* Set the next-arg-index to point at the non-options 441*9663SMark.Logan@Sun.COM that we previously skipped, so the caller will digest them. */ 442*9663SMark.Logan@Sun.COM if (d->__first_nonopt != d->__last_nonopt) 443*9663SMark.Logan@Sun.COM d->optind = d->__first_nonopt; 444*9663SMark.Logan@Sun.COM return -1; 445*9663SMark.Logan@Sun.COM } 446*9663SMark.Logan@Sun.COM 447*9663SMark.Logan@Sun.COM /* If we have come to a non-option and did not permute it, 448*9663SMark.Logan@Sun.COM either stop the scan or describe it to the caller and pass it by. */ 449*9663SMark.Logan@Sun.COM 450*9663SMark.Logan@Sun.COM if (NONOPTION_P) 451*9663SMark.Logan@Sun.COM { 452*9663SMark.Logan@Sun.COM if (d->__ordering == REQUIRE_ORDER) 453*9663SMark.Logan@Sun.COM return -1; 454*9663SMark.Logan@Sun.COM d->optarg = argv[d->optind++]; 455*9663SMark.Logan@Sun.COM return 1; 456*9663SMark.Logan@Sun.COM } 457*9663SMark.Logan@Sun.COM 458*9663SMark.Logan@Sun.COM /* We have found another option-ARGV-element. 459*9663SMark.Logan@Sun.COM Skip the initial punctuation. */ 460*9663SMark.Logan@Sun.COM 461*9663SMark.Logan@Sun.COM d->__nextchar = (argv[d->optind] + 1 462*9663SMark.Logan@Sun.COM + (longopts != NULL && argv[d->optind][1] == '-')); 463*9663SMark.Logan@Sun.COM } 464*9663SMark.Logan@Sun.COM 465*9663SMark.Logan@Sun.COM /* Decode the current option-ARGV-element. */ 466*9663SMark.Logan@Sun.COM 467*9663SMark.Logan@Sun.COM /* Check whether the ARGV-element is a long option. 468*9663SMark.Logan@Sun.COM 469*9663SMark.Logan@Sun.COM If long_only and the ARGV-element has the form "-f", where f is 470*9663SMark.Logan@Sun.COM a valid short option, don't consider it an abbreviated form of 471*9663SMark.Logan@Sun.COM a long option that starts with f. Otherwise there would be no 472*9663SMark.Logan@Sun.COM way to give the -f short option. 473*9663SMark.Logan@Sun.COM 474*9663SMark.Logan@Sun.COM On the other hand, if there's a long option "fubar" and 475*9663SMark.Logan@Sun.COM the ARGV-element is "-fu", do consider that an abbreviation of 476*9663SMark.Logan@Sun.COM the long option, just like "--fu", and not "-f" with arg "u". 477*9663SMark.Logan@Sun.COM 478*9663SMark.Logan@Sun.COM This distinction seems to be the most useful approach. */ 479*9663SMark.Logan@Sun.COM 480*9663SMark.Logan@Sun.COM if (longopts != NULL 481*9663SMark.Logan@Sun.COM && (argv[d->optind][1] == '-' 482*9663SMark.Logan@Sun.COM || (long_only && (argv[d->optind][2] 483*9663SMark.Logan@Sun.COM || !strchr (optstring, argv[d->optind][1]))))) 484*9663SMark.Logan@Sun.COM { 485*9663SMark.Logan@Sun.COM char *nameend; 486*9663SMark.Logan@Sun.COM const struct option *p; 487*9663SMark.Logan@Sun.COM const struct option *pfound = NULL; 488*9663SMark.Logan@Sun.COM int exact = 0; 489*9663SMark.Logan@Sun.COM int ambig = 0; 490*9663SMark.Logan@Sun.COM int indfound = -1; 491*9663SMark.Logan@Sun.COM int option_index; 492*9663SMark.Logan@Sun.COM 493*9663SMark.Logan@Sun.COM for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++) 494*9663SMark.Logan@Sun.COM /* Do nothing. */ ; 495*9663SMark.Logan@Sun.COM 496*9663SMark.Logan@Sun.COM /* Test all long options for either exact match 497*9663SMark.Logan@Sun.COM or abbreviated matches. */ 498*9663SMark.Logan@Sun.COM for (p = longopts, option_index = 0; p->name; p++, option_index++) 499*9663SMark.Logan@Sun.COM if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar)) 500*9663SMark.Logan@Sun.COM { 501*9663SMark.Logan@Sun.COM if ((unsigned int) (nameend - d->__nextchar) 502*9663SMark.Logan@Sun.COM == (unsigned int) strlen (p->name)) 503*9663SMark.Logan@Sun.COM { 504*9663SMark.Logan@Sun.COM /* Exact match found. */ 505*9663SMark.Logan@Sun.COM pfound = p; 506*9663SMark.Logan@Sun.COM indfound = option_index; 507*9663SMark.Logan@Sun.COM exact = 1; 508*9663SMark.Logan@Sun.COM break; 509*9663SMark.Logan@Sun.COM } 510*9663SMark.Logan@Sun.COM else if (pfound == NULL) 511*9663SMark.Logan@Sun.COM { 512*9663SMark.Logan@Sun.COM /* First nonexact match found. */ 513*9663SMark.Logan@Sun.COM pfound = p; 514*9663SMark.Logan@Sun.COM indfound = option_index; 515*9663SMark.Logan@Sun.COM } 516*9663SMark.Logan@Sun.COM else if (long_only 517*9663SMark.Logan@Sun.COM || pfound->has_arg != p->has_arg 518*9663SMark.Logan@Sun.COM || pfound->flag != p->flag 519*9663SMark.Logan@Sun.COM || pfound->val != p->val) 520*9663SMark.Logan@Sun.COM /* Second or later nonexact match found. */ 521*9663SMark.Logan@Sun.COM ambig = 1; 522*9663SMark.Logan@Sun.COM } 523*9663SMark.Logan@Sun.COM 524*9663SMark.Logan@Sun.COM if (ambig && !exact) 525*9663SMark.Logan@Sun.COM { 526*9663SMark.Logan@Sun.COM if (print_errors) 527*9663SMark.Logan@Sun.COM { 528*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO 529*9663SMark.Logan@Sun.COM char *buf; 530*9663SMark.Logan@Sun.COM 531*9663SMark.Logan@Sun.COM if (__asprintf (&buf, _("%s: option `%s' is ambiguous\n"), 532*9663SMark.Logan@Sun.COM argv[0], argv[d->optind]) >= 0) 533*9663SMark.Logan@Sun.COM { 534*9663SMark.Logan@Sun.COM _IO_flockfile (stderr); 535*9663SMark.Logan@Sun.COM 536*9663SMark.Logan@Sun.COM int old_flags2 = ((_IO_FILE *) stderr)->_flags2; 537*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; 538*9663SMark.Logan@Sun.COM 539*9663SMark.Logan@Sun.COM __fxprintf (NULL, "%s", buf); 540*9663SMark.Logan@Sun.COM 541*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 = old_flags2; 542*9663SMark.Logan@Sun.COM _IO_funlockfile (stderr); 543*9663SMark.Logan@Sun.COM 544*9663SMark.Logan@Sun.COM free (buf); 545*9663SMark.Logan@Sun.COM } 546*9663SMark.Logan@Sun.COM #else 547*9663SMark.Logan@Sun.COM fprintf (stderr, _("%s: option `%s' is ambiguous\n"), 548*9663SMark.Logan@Sun.COM argv[0], argv[d->optind]); 549*9663SMark.Logan@Sun.COM #endif 550*9663SMark.Logan@Sun.COM } 551*9663SMark.Logan@Sun.COM d->__nextchar += strlen (d->__nextchar); 552*9663SMark.Logan@Sun.COM d->optind++; 553*9663SMark.Logan@Sun.COM d->optopt = 0; 554*9663SMark.Logan@Sun.COM return '?'; 555*9663SMark.Logan@Sun.COM } 556*9663SMark.Logan@Sun.COM 557*9663SMark.Logan@Sun.COM if (pfound != NULL) 558*9663SMark.Logan@Sun.COM { 559*9663SMark.Logan@Sun.COM option_index = indfound; 560*9663SMark.Logan@Sun.COM d->optind++; 561*9663SMark.Logan@Sun.COM if (*nameend) 562*9663SMark.Logan@Sun.COM { 563*9663SMark.Logan@Sun.COM /* Don't test has_arg with >, because some C compilers don't 564*9663SMark.Logan@Sun.COM allow it to be used on enums. */ 565*9663SMark.Logan@Sun.COM if (pfound->has_arg) 566*9663SMark.Logan@Sun.COM d->optarg = nameend + 1; 567*9663SMark.Logan@Sun.COM else 568*9663SMark.Logan@Sun.COM { 569*9663SMark.Logan@Sun.COM if (print_errors) 570*9663SMark.Logan@Sun.COM { 571*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO 572*9663SMark.Logan@Sun.COM char *buf; 573*9663SMark.Logan@Sun.COM int n; 574*9663SMark.Logan@Sun.COM #endif 575*9663SMark.Logan@Sun.COM 576*9663SMark.Logan@Sun.COM if (argv[d->optind - 1][1] == '-') 577*9663SMark.Logan@Sun.COM { 578*9663SMark.Logan@Sun.COM /* --option */ 579*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO 580*9663SMark.Logan@Sun.COM n = __asprintf (&buf, _("\ 581*9663SMark.Logan@Sun.COM %s: option `--%s' doesn't allow an argument\n"), 582*9663SMark.Logan@Sun.COM argv[0], pfound->name); 583*9663SMark.Logan@Sun.COM #else 584*9663SMark.Logan@Sun.COM fprintf (stderr, _("\ 585*9663SMark.Logan@Sun.COM %s: option `--%s' doesn't allow an argument\n"), 586*9663SMark.Logan@Sun.COM argv[0], pfound->name); 587*9663SMark.Logan@Sun.COM #endif 588*9663SMark.Logan@Sun.COM } 589*9663SMark.Logan@Sun.COM else 590*9663SMark.Logan@Sun.COM { 591*9663SMark.Logan@Sun.COM /* +option or -option */ 592*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO 593*9663SMark.Logan@Sun.COM n = __asprintf (&buf, _("\ 594*9663SMark.Logan@Sun.COM %s: option `%c%s' doesn't allow an argument\n"), 595*9663SMark.Logan@Sun.COM argv[0], argv[d->optind - 1][0], 596*9663SMark.Logan@Sun.COM pfound->name); 597*9663SMark.Logan@Sun.COM #else 598*9663SMark.Logan@Sun.COM fprintf (stderr, _("\ 599*9663SMark.Logan@Sun.COM %s: option `%c%s' doesn't allow an argument\n"), 600*9663SMark.Logan@Sun.COM argv[0], argv[d->optind - 1][0], 601*9663SMark.Logan@Sun.COM pfound->name); 602*9663SMark.Logan@Sun.COM #endif 603*9663SMark.Logan@Sun.COM } 604*9663SMark.Logan@Sun.COM 605*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO 606*9663SMark.Logan@Sun.COM if (n >= 0) 607*9663SMark.Logan@Sun.COM { 608*9663SMark.Logan@Sun.COM _IO_flockfile (stderr); 609*9663SMark.Logan@Sun.COM 610*9663SMark.Logan@Sun.COM int old_flags2 = ((_IO_FILE *) stderr)->_flags2; 611*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 612*9663SMark.Logan@Sun.COM |= _IO_FLAGS2_NOTCANCEL; 613*9663SMark.Logan@Sun.COM 614*9663SMark.Logan@Sun.COM __fxprintf (NULL, "%s", buf); 615*9663SMark.Logan@Sun.COM 616*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 = old_flags2; 617*9663SMark.Logan@Sun.COM _IO_funlockfile (stderr); 618*9663SMark.Logan@Sun.COM 619*9663SMark.Logan@Sun.COM free (buf); 620*9663SMark.Logan@Sun.COM } 621*9663SMark.Logan@Sun.COM #endif 622*9663SMark.Logan@Sun.COM } 623*9663SMark.Logan@Sun.COM 624*9663SMark.Logan@Sun.COM d->__nextchar += strlen (d->__nextchar); 625*9663SMark.Logan@Sun.COM 626*9663SMark.Logan@Sun.COM d->optopt = pfound->val; 627*9663SMark.Logan@Sun.COM return '?'; 628*9663SMark.Logan@Sun.COM } 629*9663SMark.Logan@Sun.COM } 630*9663SMark.Logan@Sun.COM else if (pfound->has_arg == 1) 631*9663SMark.Logan@Sun.COM { 632*9663SMark.Logan@Sun.COM if (d->optind < argc) 633*9663SMark.Logan@Sun.COM d->optarg = argv[d->optind++]; 634*9663SMark.Logan@Sun.COM else 635*9663SMark.Logan@Sun.COM { 636*9663SMark.Logan@Sun.COM if (print_errors) 637*9663SMark.Logan@Sun.COM { 638*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO 639*9663SMark.Logan@Sun.COM char *buf; 640*9663SMark.Logan@Sun.COM 641*9663SMark.Logan@Sun.COM if (__asprintf (&buf, _("\ 642*9663SMark.Logan@Sun.COM %s: option `%s' requires an argument\n"), 643*9663SMark.Logan@Sun.COM argv[0], argv[d->optind - 1]) >= 0) 644*9663SMark.Logan@Sun.COM { 645*9663SMark.Logan@Sun.COM _IO_flockfile (stderr); 646*9663SMark.Logan@Sun.COM 647*9663SMark.Logan@Sun.COM int old_flags2 = ((_IO_FILE *) stderr)->_flags2; 648*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 649*9663SMark.Logan@Sun.COM |= _IO_FLAGS2_NOTCANCEL; 650*9663SMark.Logan@Sun.COM 651*9663SMark.Logan@Sun.COM __fxprintf (NULL, "%s", buf); 652*9663SMark.Logan@Sun.COM 653*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 = old_flags2; 654*9663SMark.Logan@Sun.COM _IO_funlockfile (stderr); 655*9663SMark.Logan@Sun.COM 656*9663SMark.Logan@Sun.COM free (buf); 657*9663SMark.Logan@Sun.COM } 658*9663SMark.Logan@Sun.COM #else 659*9663SMark.Logan@Sun.COM fprintf (stderr, 660*9663SMark.Logan@Sun.COM _("%s: option `%s' requires an argument\n"), 661*9663SMark.Logan@Sun.COM argv[0], argv[d->optind - 1]); 662*9663SMark.Logan@Sun.COM #endif 663*9663SMark.Logan@Sun.COM } 664*9663SMark.Logan@Sun.COM d->__nextchar += strlen (d->__nextchar); 665*9663SMark.Logan@Sun.COM d->optopt = pfound->val; 666*9663SMark.Logan@Sun.COM return optstring[0] == ':' ? ':' : '?'; 667*9663SMark.Logan@Sun.COM } 668*9663SMark.Logan@Sun.COM } 669*9663SMark.Logan@Sun.COM d->__nextchar += strlen (d->__nextchar); 670*9663SMark.Logan@Sun.COM if (longind != NULL) 671*9663SMark.Logan@Sun.COM *longind = option_index; 672*9663SMark.Logan@Sun.COM if (pfound->flag) 673*9663SMark.Logan@Sun.COM { 674*9663SMark.Logan@Sun.COM *(pfound->flag) = pfound->val; 675*9663SMark.Logan@Sun.COM return 0; 676*9663SMark.Logan@Sun.COM } 677*9663SMark.Logan@Sun.COM return pfound->val; 678*9663SMark.Logan@Sun.COM } 679*9663SMark.Logan@Sun.COM 680*9663SMark.Logan@Sun.COM /* Can't find it as a long option. If this is not getopt_long_only, 681*9663SMark.Logan@Sun.COM or the option starts with '--' or is not a valid short 682*9663SMark.Logan@Sun.COM option, then it's an error. 683*9663SMark.Logan@Sun.COM Otherwise interpret it as a short option. */ 684*9663SMark.Logan@Sun.COM if (!long_only || argv[d->optind][1] == '-' 685*9663SMark.Logan@Sun.COM || strchr (optstring, *d->__nextchar) == NULL) 686*9663SMark.Logan@Sun.COM { 687*9663SMark.Logan@Sun.COM if (print_errors) 688*9663SMark.Logan@Sun.COM { 689*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO 690*9663SMark.Logan@Sun.COM char *buf; 691*9663SMark.Logan@Sun.COM int n; 692*9663SMark.Logan@Sun.COM #endif 693*9663SMark.Logan@Sun.COM 694*9663SMark.Logan@Sun.COM if (argv[d->optind][1] == '-') 695*9663SMark.Logan@Sun.COM { 696*9663SMark.Logan@Sun.COM /* --option */ 697*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO 698*9663SMark.Logan@Sun.COM n = __asprintf (&buf, _("%s: unrecognized option `--%s'\n"), 699*9663SMark.Logan@Sun.COM argv[0], d->__nextchar); 700*9663SMark.Logan@Sun.COM #else 701*9663SMark.Logan@Sun.COM fprintf (stderr, _("%s: unrecognized option `--%s'\n"), 702*9663SMark.Logan@Sun.COM argv[0], d->__nextchar); 703*9663SMark.Logan@Sun.COM #endif 704*9663SMark.Logan@Sun.COM } 705*9663SMark.Logan@Sun.COM else 706*9663SMark.Logan@Sun.COM { 707*9663SMark.Logan@Sun.COM /* +option or -option */ 708*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO 709*9663SMark.Logan@Sun.COM n = __asprintf (&buf, _("%s: unrecognized option `%c%s'\n"), 710*9663SMark.Logan@Sun.COM argv[0], argv[d->optind][0], d->__nextchar); 711*9663SMark.Logan@Sun.COM #else 712*9663SMark.Logan@Sun.COM fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), 713*9663SMark.Logan@Sun.COM argv[0], argv[d->optind][0], d->__nextchar); 714*9663SMark.Logan@Sun.COM #endif 715*9663SMark.Logan@Sun.COM } 716*9663SMark.Logan@Sun.COM 717*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO 718*9663SMark.Logan@Sun.COM if (n >= 0) 719*9663SMark.Logan@Sun.COM { 720*9663SMark.Logan@Sun.COM _IO_flockfile (stderr); 721*9663SMark.Logan@Sun.COM 722*9663SMark.Logan@Sun.COM int old_flags2 = ((_IO_FILE *) stderr)->_flags2; 723*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; 724*9663SMark.Logan@Sun.COM 725*9663SMark.Logan@Sun.COM __fxprintf (NULL, "%s", buf); 726*9663SMark.Logan@Sun.COM 727*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 = old_flags2; 728*9663SMark.Logan@Sun.COM _IO_funlockfile (stderr); 729*9663SMark.Logan@Sun.COM 730*9663SMark.Logan@Sun.COM free (buf); 731*9663SMark.Logan@Sun.COM } 732*9663SMark.Logan@Sun.COM #endif 733*9663SMark.Logan@Sun.COM } 734*9663SMark.Logan@Sun.COM d->__nextchar = (char *) ""; 735*9663SMark.Logan@Sun.COM d->optind++; 736*9663SMark.Logan@Sun.COM d->optopt = 0; 737*9663SMark.Logan@Sun.COM return '?'; 738*9663SMark.Logan@Sun.COM } 739*9663SMark.Logan@Sun.COM } 740*9663SMark.Logan@Sun.COM 741*9663SMark.Logan@Sun.COM /* Look at and handle the next short option-character. */ 742*9663SMark.Logan@Sun.COM 743*9663SMark.Logan@Sun.COM { 744*9663SMark.Logan@Sun.COM char c = *d->__nextchar++; 745*9663SMark.Logan@Sun.COM char *temp = strchr (optstring, c); 746*9663SMark.Logan@Sun.COM 747*9663SMark.Logan@Sun.COM /* Increment `optind' when we start to process its last character. */ 748*9663SMark.Logan@Sun.COM if (*d->__nextchar == '\0') 749*9663SMark.Logan@Sun.COM ++d->optind; 750*9663SMark.Logan@Sun.COM 751*9663SMark.Logan@Sun.COM if (temp == NULL || c == ':') 752*9663SMark.Logan@Sun.COM { 753*9663SMark.Logan@Sun.COM if (print_errors) 754*9663SMark.Logan@Sun.COM { 755*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO 756*9663SMark.Logan@Sun.COM char *buf; 757*9663SMark.Logan@Sun.COM int n; 758*9663SMark.Logan@Sun.COM #endif 759*9663SMark.Logan@Sun.COM 760*9663SMark.Logan@Sun.COM if (d->__posixly_correct) 761*9663SMark.Logan@Sun.COM { 762*9663SMark.Logan@Sun.COM /* 1003.2 specifies the format of this message. */ 763*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO 764*9663SMark.Logan@Sun.COM n = __asprintf (&buf, _("%s: illegal option -- %c\n"), 765*9663SMark.Logan@Sun.COM argv[0], c); 766*9663SMark.Logan@Sun.COM #else 767*9663SMark.Logan@Sun.COM fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c); 768*9663SMark.Logan@Sun.COM #endif 769*9663SMark.Logan@Sun.COM } 770*9663SMark.Logan@Sun.COM else 771*9663SMark.Logan@Sun.COM { 772*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO 773*9663SMark.Logan@Sun.COM n = __asprintf (&buf, _("%s: invalid option -- %c\n"), 774*9663SMark.Logan@Sun.COM argv[0], c); 775*9663SMark.Logan@Sun.COM #else 776*9663SMark.Logan@Sun.COM fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c); 777*9663SMark.Logan@Sun.COM #endif 778*9663SMark.Logan@Sun.COM } 779*9663SMark.Logan@Sun.COM 780*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO 781*9663SMark.Logan@Sun.COM if (n >= 0) 782*9663SMark.Logan@Sun.COM { 783*9663SMark.Logan@Sun.COM _IO_flockfile (stderr); 784*9663SMark.Logan@Sun.COM 785*9663SMark.Logan@Sun.COM int old_flags2 = ((_IO_FILE *) stderr)->_flags2; 786*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; 787*9663SMark.Logan@Sun.COM 788*9663SMark.Logan@Sun.COM __fxprintf (NULL, "%s", buf); 789*9663SMark.Logan@Sun.COM 790*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 = old_flags2; 791*9663SMark.Logan@Sun.COM _IO_funlockfile (stderr); 792*9663SMark.Logan@Sun.COM 793*9663SMark.Logan@Sun.COM free (buf); 794*9663SMark.Logan@Sun.COM } 795*9663SMark.Logan@Sun.COM #endif 796*9663SMark.Logan@Sun.COM } 797*9663SMark.Logan@Sun.COM d->optopt = c; 798*9663SMark.Logan@Sun.COM return '?'; 799*9663SMark.Logan@Sun.COM } 800*9663SMark.Logan@Sun.COM /* Convenience. Treat POSIX -W foo same as long option --foo */ 801*9663SMark.Logan@Sun.COM if (temp[0] == 'W' && temp[1] == ';') 802*9663SMark.Logan@Sun.COM { 803*9663SMark.Logan@Sun.COM char *nameend; 804*9663SMark.Logan@Sun.COM const struct option *p; 805*9663SMark.Logan@Sun.COM const struct option *pfound = NULL; 806*9663SMark.Logan@Sun.COM int exact = 0; 807*9663SMark.Logan@Sun.COM int ambig = 0; 808*9663SMark.Logan@Sun.COM int indfound = 0; 809*9663SMark.Logan@Sun.COM int option_index; 810*9663SMark.Logan@Sun.COM 811*9663SMark.Logan@Sun.COM /* This is an option that requires an argument. */ 812*9663SMark.Logan@Sun.COM if (*d->__nextchar != '\0') 813*9663SMark.Logan@Sun.COM { 814*9663SMark.Logan@Sun.COM d->optarg = d->__nextchar; 815*9663SMark.Logan@Sun.COM /* If we end this ARGV-element by taking the rest as an arg, 816*9663SMark.Logan@Sun.COM we must advance to the next element now. */ 817*9663SMark.Logan@Sun.COM d->optind++; 818*9663SMark.Logan@Sun.COM } 819*9663SMark.Logan@Sun.COM else if (d->optind == argc) 820*9663SMark.Logan@Sun.COM { 821*9663SMark.Logan@Sun.COM if (print_errors) 822*9663SMark.Logan@Sun.COM { 823*9663SMark.Logan@Sun.COM /* 1003.2 specifies the format of this message. */ 824*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO 825*9663SMark.Logan@Sun.COM char *buf; 826*9663SMark.Logan@Sun.COM 827*9663SMark.Logan@Sun.COM if (__asprintf (&buf, 828*9663SMark.Logan@Sun.COM _("%s: option requires an argument -- %c\n"), 829*9663SMark.Logan@Sun.COM argv[0], c) >= 0) 830*9663SMark.Logan@Sun.COM { 831*9663SMark.Logan@Sun.COM _IO_flockfile (stderr); 832*9663SMark.Logan@Sun.COM 833*9663SMark.Logan@Sun.COM int old_flags2 = ((_IO_FILE *) stderr)->_flags2; 834*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; 835*9663SMark.Logan@Sun.COM 836*9663SMark.Logan@Sun.COM __fxprintf (NULL, "%s", buf); 837*9663SMark.Logan@Sun.COM 838*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 = old_flags2; 839*9663SMark.Logan@Sun.COM _IO_funlockfile (stderr); 840*9663SMark.Logan@Sun.COM 841*9663SMark.Logan@Sun.COM free (buf); 842*9663SMark.Logan@Sun.COM } 843*9663SMark.Logan@Sun.COM #else 844*9663SMark.Logan@Sun.COM fprintf (stderr, _("%s: option requires an argument -- %c\n"), 845*9663SMark.Logan@Sun.COM argv[0], c); 846*9663SMark.Logan@Sun.COM #endif 847*9663SMark.Logan@Sun.COM } 848*9663SMark.Logan@Sun.COM d->optopt = c; 849*9663SMark.Logan@Sun.COM if (optstring[0] == ':') 850*9663SMark.Logan@Sun.COM c = ':'; 851*9663SMark.Logan@Sun.COM else 852*9663SMark.Logan@Sun.COM c = '?'; 853*9663SMark.Logan@Sun.COM return c; 854*9663SMark.Logan@Sun.COM } 855*9663SMark.Logan@Sun.COM else 856*9663SMark.Logan@Sun.COM /* We already incremented `d->optind' once; 857*9663SMark.Logan@Sun.COM increment it again when taking next ARGV-elt as argument. */ 858*9663SMark.Logan@Sun.COM d->optarg = argv[d->optind++]; 859*9663SMark.Logan@Sun.COM 860*9663SMark.Logan@Sun.COM /* optarg is now the argument, see if it's in the 861*9663SMark.Logan@Sun.COM table of longopts. */ 862*9663SMark.Logan@Sun.COM 863*9663SMark.Logan@Sun.COM for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '='; 864*9663SMark.Logan@Sun.COM nameend++) 865*9663SMark.Logan@Sun.COM /* Do nothing. */ ; 866*9663SMark.Logan@Sun.COM 867*9663SMark.Logan@Sun.COM /* Test all long options for either exact match 868*9663SMark.Logan@Sun.COM or abbreviated matches. */ 869*9663SMark.Logan@Sun.COM for (p = longopts, option_index = 0; p->name; p++, option_index++) 870*9663SMark.Logan@Sun.COM if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar)) 871*9663SMark.Logan@Sun.COM { 872*9663SMark.Logan@Sun.COM if ((unsigned int) (nameend - d->__nextchar) == strlen (p->name)) 873*9663SMark.Logan@Sun.COM { 874*9663SMark.Logan@Sun.COM /* Exact match found. */ 875*9663SMark.Logan@Sun.COM pfound = p; 876*9663SMark.Logan@Sun.COM indfound = option_index; 877*9663SMark.Logan@Sun.COM exact = 1; 878*9663SMark.Logan@Sun.COM break; 879*9663SMark.Logan@Sun.COM } 880*9663SMark.Logan@Sun.COM else if (pfound == NULL) 881*9663SMark.Logan@Sun.COM { 882*9663SMark.Logan@Sun.COM /* First nonexact match found. */ 883*9663SMark.Logan@Sun.COM pfound = p; 884*9663SMark.Logan@Sun.COM indfound = option_index; 885*9663SMark.Logan@Sun.COM } 886*9663SMark.Logan@Sun.COM else 887*9663SMark.Logan@Sun.COM /* Second or later nonexact match found. */ 888*9663SMark.Logan@Sun.COM ambig = 1; 889*9663SMark.Logan@Sun.COM } 890*9663SMark.Logan@Sun.COM if (ambig && !exact) 891*9663SMark.Logan@Sun.COM { 892*9663SMark.Logan@Sun.COM if (print_errors) 893*9663SMark.Logan@Sun.COM { 894*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO 895*9663SMark.Logan@Sun.COM char *buf; 896*9663SMark.Logan@Sun.COM 897*9663SMark.Logan@Sun.COM if (__asprintf (&buf, _("%s: option `-W %s' is ambiguous\n"), 898*9663SMark.Logan@Sun.COM argv[0], argv[d->optind]) >= 0) 899*9663SMark.Logan@Sun.COM { 900*9663SMark.Logan@Sun.COM _IO_flockfile (stderr); 901*9663SMark.Logan@Sun.COM 902*9663SMark.Logan@Sun.COM int old_flags2 = ((_IO_FILE *) stderr)->_flags2; 903*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; 904*9663SMark.Logan@Sun.COM 905*9663SMark.Logan@Sun.COM __fxprintf (NULL, "%s", buf); 906*9663SMark.Logan@Sun.COM 907*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 = old_flags2; 908*9663SMark.Logan@Sun.COM _IO_funlockfile (stderr); 909*9663SMark.Logan@Sun.COM 910*9663SMark.Logan@Sun.COM free (buf); 911*9663SMark.Logan@Sun.COM } 912*9663SMark.Logan@Sun.COM #else 913*9663SMark.Logan@Sun.COM fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), 914*9663SMark.Logan@Sun.COM argv[0], argv[d->optind]); 915*9663SMark.Logan@Sun.COM #endif 916*9663SMark.Logan@Sun.COM } 917*9663SMark.Logan@Sun.COM d->__nextchar += strlen (d->__nextchar); 918*9663SMark.Logan@Sun.COM d->optind++; 919*9663SMark.Logan@Sun.COM return '?'; 920*9663SMark.Logan@Sun.COM } 921*9663SMark.Logan@Sun.COM if (pfound != NULL) 922*9663SMark.Logan@Sun.COM { 923*9663SMark.Logan@Sun.COM option_index = indfound; 924*9663SMark.Logan@Sun.COM if (*nameend) 925*9663SMark.Logan@Sun.COM { 926*9663SMark.Logan@Sun.COM /* Don't test has_arg with >, because some C compilers don't 927*9663SMark.Logan@Sun.COM allow it to be used on enums. */ 928*9663SMark.Logan@Sun.COM if (pfound->has_arg) 929*9663SMark.Logan@Sun.COM d->optarg = nameend + 1; 930*9663SMark.Logan@Sun.COM else 931*9663SMark.Logan@Sun.COM { 932*9663SMark.Logan@Sun.COM if (print_errors) 933*9663SMark.Logan@Sun.COM { 934*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO 935*9663SMark.Logan@Sun.COM char *buf; 936*9663SMark.Logan@Sun.COM 937*9663SMark.Logan@Sun.COM if (__asprintf (&buf, _("\ 938*9663SMark.Logan@Sun.COM %s: option `-W %s' doesn't allow an argument\n"), 939*9663SMark.Logan@Sun.COM argv[0], pfound->name) >= 0) 940*9663SMark.Logan@Sun.COM { 941*9663SMark.Logan@Sun.COM _IO_flockfile (stderr); 942*9663SMark.Logan@Sun.COM 943*9663SMark.Logan@Sun.COM int old_flags2 = ((_IO_FILE *) stderr)->_flags2; 944*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 945*9663SMark.Logan@Sun.COM |= _IO_FLAGS2_NOTCANCEL; 946*9663SMark.Logan@Sun.COM 947*9663SMark.Logan@Sun.COM __fxprintf (NULL, "%s", buf); 948*9663SMark.Logan@Sun.COM 949*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 = old_flags2; 950*9663SMark.Logan@Sun.COM _IO_funlockfile (stderr); 951*9663SMark.Logan@Sun.COM 952*9663SMark.Logan@Sun.COM free (buf); 953*9663SMark.Logan@Sun.COM } 954*9663SMark.Logan@Sun.COM #else 955*9663SMark.Logan@Sun.COM fprintf (stderr, _("\ 956*9663SMark.Logan@Sun.COM %s: option `-W %s' doesn't allow an argument\n"), 957*9663SMark.Logan@Sun.COM argv[0], pfound->name); 958*9663SMark.Logan@Sun.COM #endif 959*9663SMark.Logan@Sun.COM } 960*9663SMark.Logan@Sun.COM 961*9663SMark.Logan@Sun.COM d->__nextchar += strlen (d->__nextchar); 962*9663SMark.Logan@Sun.COM return '?'; 963*9663SMark.Logan@Sun.COM } 964*9663SMark.Logan@Sun.COM } 965*9663SMark.Logan@Sun.COM else if (pfound->has_arg == 1) 966*9663SMark.Logan@Sun.COM { 967*9663SMark.Logan@Sun.COM if (d->optind < argc) 968*9663SMark.Logan@Sun.COM d->optarg = argv[d->optind++]; 969*9663SMark.Logan@Sun.COM else 970*9663SMark.Logan@Sun.COM { 971*9663SMark.Logan@Sun.COM if (print_errors) 972*9663SMark.Logan@Sun.COM { 973*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO 974*9663SMark.Logan@Sun.COM char *buf; 975*9663SMark.Logan@Sun.COM 976*9663SMark.Logan@Sun.COM if (__asprintf (&buf, _("\ 977*9663SMark.Logan@Sun.COM %s: option `%s' requires an argument\n"), 978*9663SMark.Logan@Sun.COM argv[0], argv[d->optind - 1]) >= 0) 979*9663SMark.Logan@Sun.COM { 980*9663SMark.Logan@Sun.COM _IO_flockfile (stderr); 981*9663SMark.Logan@Sun.COM 982*9663SMark.Logan@Sun.COM int old_flags2 = ((_IO_FILE *) stderr)->_flags2; 983*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 984*9663SMark.Logan@Sun.COM |= _IO_FLAGS2_NOTCANCEL; 985*9663SMark.Logan@Sun.COM 986*9663SMark.Logan@Sun.COM __fxprintf (NULL, "%s", buf); 987*9663SMark.Logan@Sun.COM 988*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 = old_flags2; 989*9663SMark.Logan@Sun.COM _IO_funlockfile (stderr); 990*9663SMark.Logan@Sun.COM 991*9663SMark.Logan@Sun.COM free (buf); 992*9663SMark.Logan@Sun.COM } 993*9663SMark.Logan@Sun.COM #else 994*9663SMark.Logan@Sun.COM fprintf (stderr, 995*9663SMark.Logan@Sun.COM _("%s: option `%s' requires an argument\n"), 996*9663SMark.Logan@Sun.COM argv[0], argv[d->optind - 1]); 997*9663SMark.Logan@Sun.COM #endif 998*9663SMark.Logan@Sun.COM } 999*9663SMark.Logan@Sun.COM d->__nextchar += strlen (d->__nextchar); 1000*9663SMark.Logan@Sun.COM return optstring[0] == ':' ? ':' : '?'; 1001*9663SMark.Logan@Sun.COM } 1002*9663SMark.Logan@Sun.COM } 1003*9663SMark.Logan@Sun.COM d->__nextchar += strlen (d->__nextchar); 1004*9663SMark.Logan@Sun.COM if (longind != NULL) 1005*9663SMark.Logan@Sun.COM *longind = option_index; 1006*9663SMark.Logan@Sun.COM if (pfound->flag) 1007*9663SMark.Logan@Sun.COM { 1008*9663SMark.Logan@Sun.COM *(pfound->flag) = pfound->val; 1009*9663SMark.Logan@Sun.COM return 0; 1010*9663SMark.Logan@Sun.COM } 1011*9663SMark.Logan@Sun.COM return pfound->val; 1012*9663SMark.Logan@Sun.COM } 1013*9663SMark.Logan@Sun.COM d->__nextchar = NULL; 1014*9663SMark.Logan@Sun.COM return 'W'; /* Let the application handle it. */ 1015*9663SMark.Logan@Sun.COM } 1016*9663SMark.Logan@Sun.COM if (temp[1] == ':') 1017*9663SMark.Logan@Sun.COM { 1018*9663SMark.Logan@Sun.COM if (temp[2] == ':') 1019*9663SMark.Logan@Sun.COM { 1020*9663SMark.Logan@Sun.COM /* This is an option that accepts an argument optionally. */ 1021*9663SMark.Logan@Sun.COM if (*d->__nextchar != '\0') 1022*9663SMark.Logan@Sun.COM { 1023*9663SMark.Logan@Sun.COM d->optarg = d->__nextchar; 1024*9663SMark.Logan@Sun.COM d->optind++; 1025*9663SMark.Logan@Sun.COM } 1026*9663SMark.Logan@Sun.COM else 1027*9663SMark.Logan@Sun.COM d->optarg = NULL; 1028*9663SMark.Logan@Sun.COM d->__nextchar = NULL; 1029*9663SMark.Logan@Sun.COM } 1030*9663SMark.Logan@Sun.COM else 1031*9663SMark.Logan@Sun.COM { 1032*9663SMark.Logan@Sun.COM /* This is an option that requires an argument. */ 1033*9663SMark.Logan@Sun.COM if (*d->__nextchar != '\0') 1034*9663SMark.Logan@Sun.COM { 1035*9663SMark.Logan@Sun.COM d->optarg = d->__nextchar; 1036*9663SMark.Logan@Sun.COM /* If we end this ARGV-element by taking the rest as an arg, 1037*9663SMark.Logan@Sun.COM we must advance to the next element now. */ 1038*9663SMark.Logan@Sun.COM d->optind++; 1039*9663SMark.Logan@Sun.COM } 1040*9663SMark.Logan@Sun.COM else if (d->optind == argc) 1041*9663SMark.Logan@Sun.COM { 1042*9663SMark.Logan@Sun.COM if (print_errors) 1043*9663SMark.Logan@Sun.COM { 1044*9663SMark.Logan@Sun.COM /* 1003.2 specifies the format of this message. */ 1045*9663SMark.Logan@Sun.COM #if defined _LIBC && defined USE_IN_LIBIO 1046*9663SMark.Logan@Sun.COM char *buf; 1047*9663SMark.Logan@Sun.COM 1048*9663SMark.Logan@Sun.COM if (__asprintf (&buf, _("\ 1049*9663SMark.Logan@Sun.COM %s: option requires an argument -- %c\n"), 1050*9663SMark.Logan@Sun.COM argv[0], c) >= 0) 1051*9663SMark.Logan@Sun.COM { 1052*9663SMark.Logan@Sun.COM _IO_flockfile (stderr); 1053*9663SMark.Logan@Sun.COM 1054*9663SMark.Logan@Sun.COM int old_flags2 = ((_IO_FILE *) stderr)->_flags2; 1055*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; 1056*9663SMark.Logan@Sun.COM 1057*9663SMark.Logan@Sun.COM __fxprintf (NULL, "%s", buf); 1058*9663SMark.Logan@Sun.COM 1059*9663SMark.Logan@Sun.COM ((_IO_FILE *) stderr)->_flags2 = old_flags2; 1060*9663SMark.Logan@Sun.COM _IO_funlockfile (stderr); 1061*9663SMark.Logan@Sun.COM 1062*9663SMark.Logan@Sun.COM free (buf); 1063*9663SMark.Logan@Sun.COM } 1064*9663SMark.Logan@Sun.COM #else 1065*9663SMark.Logan@Sun.COM fprintf (stderr, 1066*9663SMark.Logan@Sun.COM _("%s: option requires an argument -- %c\n"), 1067*9663SMark.Logan@Sun.COM argv[0], c); 1068*9663SMark.Logan@Sun.COM #endif 1069*9663SMark.Logan@Sun.COM } 1070*9663SMark.Logan@Sun.COM d->optopt = c; 1071*9663SMark.Logan@Sun.COM if (optstring[0] == ':') 1072*9663SMark.Logan@Sun.COM c = ':'; 1073*9663SMark.Logan@Sun.COM else 1074*9663SMark.Logan@Sun.COM c = '?'; 1075*9663SMark.Logan@Sun.COM } 1076*9663SMark.Logan@Sun.COM else 1077*9663SMark.Logan@Sun.COM /* We already incremented `optind' once; 1078*9663SMark.Logan@Sun.COM increment it again when taking next ARGV-elt as argument. */ 1079*9663SMark.Logan@Sun.COM d->optarg = argv[d->optind++]; 1080*9663SMark.Logan@Sun.COM d->__nextchar = NULL; 1081*9663SMark.Logan@Sun.COM } 1082*9663SMark.Logan@Sun.COM } 1083*9663SMark.Logan@Sun.COM return c; 1084*9663SMark.Logan@Sun.COM } 1085*9663SMark.Logan@Sun.COM } 1086*9663SMark.Logan@Sun.COM 1087*9663SMark.Logan@Sun.COM int 1088*9663SMark.Logan@Sun.COM _getopt_internal (int argc, char **argv, const char *optstring, 1089*9663SMark.Logan@Sun.COM const struct option *longopts, int *longind, 1090*9663SMark.Logan@Sun.COM int long_only, int posixly_correct) 1091*9663SMark.Logan@Sun.COM { 1092*9663SMark.Logan@Sun.COM int result; 1093*9663SMark.Logan@Sun.COM 1094*9663SMark.Logan@Sun.COM getopt_data.optind = optind; 1095*9663SMark.Logan@Sun.COM getopt_data.opterr = opterr; 1096*9663SMark.Logan@Sun.COM 1097*9663SMark.Logan@Sun.COM result = _getopt_internal_r (argc, argv, optstring, longopts, longind, 1098*9663SMark.Logan@Sun.COM long_only, posixly_correct, &getopt_data); 1099*9663SMark.Logan@Sun.COM 1100*9663SMark.Logan@Sun.COM optind = getopt_data.optind; 1101*9663SMark.Logan@Sun.COM optarg = getopt_data.optarg; 1102*9663SMark.Logan@Sun.COM optopt = getopt_data.optopt; 1103*9663SMark.Logan@Sun.COM 1104*9663SMark.Logan@Sun.COM return result; 1105*9663SMark.Logan@Sun.COM } 1106*9663SMark.Logan@Sun.COM 1107*9663SMark.Logan@Sun.COM /* glibc gets a LSB-compliant getopt. 1108*9663SMark.Logan@Sun.COM Standalone applications get a POSIX-compliant getopt. */ 1109*9663SMark.Logan@Sun.COM #if _LIBC 1110*9663SMark.Logan@Sun.COM enum { POSIXLY_CORRECT = 0 }; 1111*9663SMark.Logan@Sun.COM #else 1112*9663SMark.Logan@Sun.COM enum { POSIXLY_CORRECT = 1 }; 1113*9663SMark.Logan@Sun.COM #endif 1114*9663SMark.Logan@Sun.COM 1115*9663SMark.Logan@Sun.COM int 1116*9663SMark.Logan@Sun.COM getopt (int argc, char *const *argv, const char *optstring) 1117*9663SMark.Logan@Sun.COM { 1118*9663SMark.Logan@Sun.COM return _getopt_internal (argc, (char **) argv, optstring, NULL, NULL, 0, 1119*9663SMark.Logan@Sun.COM POSIXLY_CORRECT); 1120*9663SMark.Logan@Sun.COM } 1121*9663SMark.Logan@Sun.COM 1122*9663SMark.Logan@Sun.COM 1123*9663SMark.Logan@Sun.COM #ifdef TEST 1124*9663SMark.Logan@Sun.COM 1125*9663SMark.Logan@Sun.COM /* Compile with -DTEST to make an executable for use in testing 1126*9663SMark.Logan@Sun.COM the above definition of `getopt'. */ 1127*9663SMark.Logan@Sun.COM 1128*9663SMark.Logan@Sun.COM int 1129*9663SMark.Logan@Sun.COM main (int argc, char **argv) 1130*9663SMark.Logan@Sun.COM { 1131*9663SMark.Logan@Sun.COM int c; 1132*9663SMark.Logan@Sun.COM int digit_optind = 0; 1133*9663SMark.Logan@Sun.COM 1134*9663SMark.Logan@Sun.COM while (1) 1135*9663SMark.Logan@Sun.COM { 1136*9663SMark.Logan@Sun.COM int this_option_optind = optind ? optind : 1; 1137*9663SMark.Logan@Sun.COM 1138*9663SMark.Logan@Sun.COM c = getopt (argc, argv, "abc:d:0123456789"); 1139*9663SMark.Logan@Sun.COM if (c == -1) 1140*9663SMark.Logan@Sun.COM break; 1141*9663SMark.Logan@Sun.COM 1142*9663SMark.Logan@Sun.COM switch (c) 1143*9663SMark.Logan@Sun.COM { 1144*9663SMark.Logan@Sun.COM case '0': 1145*9663SMark.Logan@Sun.COM case '1': 1146*9663SMark.Logan@Sun.COM case '2': 1147*9663SMark.Logan@Sun.COM case '3': 1148*9663SMark.Logan@Sun.COM case '4': 1149*9663SMark.Logan@Sun.COM case '5': 1150*9663SMark.Logan@Sun.COM case '6': 1151*9663SMark.Logan@Sun.COM case '7': 1152*9663SMark.Logan@Sun.COM case '8': 1153*9663SMark.Logan@Sun.COM case '9': 1154*9663SMark.Logan@Sun.COM if (digit_optind != 0 && digit_optind != this_option_optind) 1155*9663SMark.Logan@Sun.COM printf ("digits occur in two different argv-elements.\n"); 1156*9663SMark.Logan@Sun.COM digit_optind = this_option_optind; 1157*9663SMark.Logan@Sun.COM printf ("option %c\n", c); 1158*9663SMark.Logan@Sun.COM break; 1159*9663SMark.Logan@Sun.COM 1160*9663SMark.Logan@Sun.COM case 'a': 1161*9663SMark.Logan@Sun.COM printf ("option a\n"); 1162*9663SMark.Logan@Sun.COM break; 1163*9663SMark.Logan@Sun.COM 1164*9663SMark.Logan@Sun.COM case 'b': 1165*9663SMark.Logan@Sun.COM printf ("option b\n"); 1166*9663SMark.Logan@Sun.COM break; 1167*9663SMark.Logan@Sun.COM 1168*9663SMark.Logan@Sun.COM case 'c': 1169*9663SMark.Logan@Sun.COM printf ("option c with value `%s'\n", optarg); 1170*9663SMark.Logan@Sun.COM break; 1171*9663SMark.Logan@Sun.COM 1172*9663SMark.Logan@Sun.COM case '?': 1173*9663SMark.Logan@Sun.COM break; 1174*9663SMark.Logan@Sun.COM 1175*9663SMark.Logan@Sun.COM default: 1176*9663SMark.Logan@Sun.COM printf ("?? getopt returned character code 0%o ??\n", c); 1177*9663SMark.Logan@Sun.COM } 1178*9663SMark.Logan@Sun.COM } 1179*9663SMark.Logan@Sun.COM 1180*9663SMark.Logan@Sun.COM if (optind < argc) 1181*9663SMark.Logan@Sun.COM { 1182*9663SMark.Logan@Sun.COM printf ("non-option ARGV-elements: "); 1183*9663SMark.Logan@Sun.COM while (optind < argc) 1184*9663SMark.Logan@Sun.COM printf ("%s ", argv[optind++]); 1185*9663SMark.Logan@Sun.COM printf ("\n"); 1186*9663SMark.Logan@Sun.COM } 1187*9663SMark.Logan@Sun.COM 1188*9663SMark.Logan@Sun.COM exit (0); 1189*9663SMark.Logan@Sun.COM } 1190*9663SMark.Logan@Sun.COM 1191*9663SMark.Logan@Sun.COM #endif /* TEST */ 1192