1 /* $OpenBSD: getopt_long.c,v 1.21 2006/09/22 17:22:05 millert Exp $ */
2 /* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */
5 * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 * Sponsored in part by the Defense Advanced Research Projects
20 * Agency (DARPA) and Air Force Research Laboratory, Air Force
21 * Materiel Command, USAF, under agreement number F39502-99-1-0512.
24 * Copyright (c) 2000 The NetBSD Foundation, Inc.
25 * All rights reserved.
27 * This code is derived from software contributed to The NetBSD Foundation
28 * by Dieter Baron and Thomas Klausner.
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 * 3. All advertising materials mentioning features or use of this software
39 * must display the following acknowledgement:
40 * This product includes software developed by the NetBSD
41 * Foundation, Inc. and its contributors.
42 * 4. Neither the name of The NetBSD Foundation nor the names of its
43 * contributors may be used to endorse or promote products derived
44 * from this software without specific prior written permission.
46 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
47 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
48 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
49 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
50 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
51 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
52 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
53 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
54 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
55 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
56 * POSSIBILITY OF SUCH DAMAGE.
60 #if defined(LIBC_SCCS) && !defined(lint)
61 static char *rcsid
= "$OpenBSD: getopt_long.c,v 1.16 2004/02/04 18:17:25 millert Exp $";
62 #endif /* LIBC_SCCS and not lint */
66 void warnx(const char * s
, ...) {}
67 // FIXME: implement me
77 #define GNU_COMPATIBLE /* Be more compatible, configure's use us! */
79 #if 0 /* we prefer to keep our getopt(3) */
80 #define REPLACE_GETOPT /* use this getopt as the system getopt(3) */
84 int opterr
= 1; /* if error message should be printed */
85 int optind
= 1; /* index into parent argv vector */
86 int optopt
= '?'; /* character checked for validity */
87 int optreset
; /* reset getopt */
88 char *optarg
; /* argument associated with option */
91 #define PRINT_ERROR ((opterr) && (*options != ':'))
93 #define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
94 #define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
95 #define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
98 #define BADCH (int)'?'
99 #define BADARG ((*options == ':') ? (int)':' : (int)'?')
100 #define INORDER (int)1
104 #ifdef GNU_COMPATIBLE
105 #define NO_PREFIX (-1)
111 static int getopt_internal(int, char * const *, const char *,
112 const struct option
*, int *, int);
113 static int parse_long_options(char * const *, const char *,
114 const struct option
*, int *, int, int);
115 static int gcd(int, int);
116 static void permute_args(int, int, int, char * const *);
118 static char *place
= EMSG
; /* option letter processing */
120 /* XXX: set optreset to 1 rather than these two */
121 static int nonopt_start
= -1; /* first non option argument (for permute) */
122 static int nonopt_end
= -1; /* first option after non options (for permute) */
125 static const char recargchar
[] = "option requires an argument -- %c";
126 static const char illoptchar
[] = "illegal option -- %c"; /* From P1003.2 */
127 #ifdef GNU_COMPATIBLE
128 static int dash_prefix
= NO_PREFIX
;
129 static const char gnuoptchar
[] = "invalid option -- %c";
131 static const char recargstring
[] = "option `%s%s' requires an argument";
132 static const char ambig
[] = "option `%s%.*s' is ambiguous";
133 static const char noarg
[] = "option `%s%.*s' doesn't allow an argument";
134 static const char illoptstring
[] = "unrecognized option `%s%s'";
136 static const char recargstring
[] = "option requires an argument -- %s";
137 static const char ambig
[] = "ambiguous option -- %.*s";
138 static const char noarg
[] = "option doesn't take an argument -- %.*s";
139 static const char illoptstring
[] = "unknown option -- %s";
143 * Compute the greatest common divisor of a and b.
161 * Exchange the block from nonopt_start to nonopt_end with the block
162 * from nonopt_end to opt_end (keeping the same order of arguments
166 permute_args(int panonopt_start
, int panonopt_end
, int opt_end
,
169 int cstart
, cyclelen
, i
, j
, ncycle
, nnonopts
, nopts
, pos
;
173 * compute lengths of blocks and number and size of cycles
175 nnonopts
= panonopt_end
- panonopt_start
;
176 nopts
= opt_end
- panonopt_end
;
177 ncycle
= gcd(nnonopts
, nopts
);
178 cyclelen
= (opt_end
- panonopt_start
) / ncycle
;
180 for (i
= 0; i
< ncycle
; i
++) {
181 cstart
= panonopt_end
+i
;
183 for (j
= 0; j
< cyclelen
; j
++) {
184 if (pos
>= panonopt_end
)
189 /* LINTED const cast */
190 ((char **) nargv
)[pos
] = nargv
[cstart
];
191 /* LINTED const cast */
192 ((char **)nargv
)[cstart
] = swap
;
198 * parse_long_options --
199 * Parse long options in argc/argv argument vector.
200 * Returns -1 if short_too is set and the option does not match long_options.
203 parse_long_options(char * const *nargv
, const char *options
,
204 const struct option
*long_options
, int *idx
, int short_too
, int flags
)
206 char *current_argv
, *has_equal
;
207 #ifdef GNU_COMPATIBLE
210 size_t current_argv_len
;
211 int i
, match
, exact_match
, second_partial_match
;
213 current_argv
= place
;
214 #ifdef GNU_COMPATIBLE
215 switch (dash_prefix
) {
223 current_dash
= "-W ";
232 second_partial_match
= 0;
236 if ((has_equal
= strchr(current_argv
, '=')) != NULL
) {
237 /* argument found (--option=arg) */
238 current_argv_len
= has_equal
- current_argv
;
241 current_argv_len
= strlen(current_argv
);
243 for (i
= 0; long_options
[i
].name
; i
++) {
244 /* find matching long option */
245 if (strncmp(current_argv
, long_options
[i
].name
,
249 if (strlen(long_options
[i
].name
) == current_argv_len
) {
256 * If this is a known short option, don't allow
257 * a partial match of a single character.
259 if (short_too
&& current_argv_len
== 1)
262 if (match
== -1) /* first partial match */
264 else if ((flags
& FLAG_LONGONLY
) ||
265 long_options
[i
].has_arg
!=
266 long_options
[match
].has_arg
||
267 long_options
[i
].flag
!= long_options
[match
].flag
||
268 long_options
[i
].val
!= long_options
[match
].val
)
269 second_partial_match
= 1;
271 if (!exact_match
&& second_partial_match
) {
272 /* ambiguous abbreviation */
275 #ifdef GNU_COMPATIBLE
278 (int)current_argv_len
,
283 if (match
!= -1) { /* option found */
284 if (long_options
[match
].has_arg
== no_argument
288 #ifdef GNU_COMPATIBLE
291 (int)current_argv_len
,
294 * XXX: GNU sets optopt to val regardless of flag
296 if (long_options
[match
].flag
== NULL
)
297 optopt
= long_options
[match
].val
;
300 #ifdef GNU_COMPATIBLE
306 if (long_options
[match
].has_arg
== required_argument
||
307 long_options
[match
].has_arg
== optional_argument
) {
310 else if (long_options
[match
].has_arg
==
313 * optional argument doesn't use next nargv
315 optarg
= nargv
[optind
++];
318 if ((long_options
[match
].has_arg
== required_argument
)
319 && (optarg
== NULL
)) {
321 * Missing argument; leading ':' indicates no error
322 * should be generated.
326 #ifdef GNU_COMPATIBLE
331 * XXX: GNU sets optopt to val regardless of flag
333 if (long_options
[match
].flag
== NULL
)
334 optopt
= long_options
[match
].val
;
340 } else { /* unknown option */
347 #ifdef GNU_COMPATIBLE
356 if (long_options
[match
].flag
) {
357 *long_options
[match
].flag
= long_options
[match
].val
;
360 return (long_options
[match
].val
);
365 * Parse argc/argv argument vector. Called by user level routines.
368 getopt_internal(int nargc
, char * const *nargv
, const char *options
,
369 const struct option
*long_options
, int *idx
, int flags
)
371 char *oli
; /* option letter list index */
372 int optchar
, short_too
;
373 int posixly_correct
; /* no static, can be changed on the fly */
379 * Disable GNU extensions if POSIXLY_CORRECT is set or options
380 * string begins with a '+'.
382 posixly_correct
= (getenv("POSIXLY_CORRECT") != NULL
);
383 #ifdef GNU_COMPATIBLE
385 flags
|= FLAG_ALLARGS
;
386 else if (posixly_correct
|| *options
== '+')
387 flags
&= ~FLAG_PERMUTE
;
389 if (posixly_correct
|| *options
== '+')
390 flags
&= ~FLAG_PERMUTE
;
391 else if (*options
== '-')
392 flags
|= FLAG_ALLARGS
;
394 if (*options
== '+' || *options
== '-')
398 * XXX Some GNU programs (like cvs) set optind to 0 instead of
399 * XXX using optreset. Work around this braindamage.
402 optind
= optreset
= 1;
406 nonopt_start
= nonopt_end
= -1;
408 if (optreset
|| !*place
) { /* update scanning pointer */
410 if (optind
>= nargc
) { /* end of argument vector */
412 if (nonopt_end
!= -1) {
413 /* do permutation, if we have to */
414 permute_args(nonopt_start
, nonopt_end
,
416 optind
-= nonopt_end
- nonopt_start
;
418 else if (nonopt_start
!= -1) {
420 * If we skipped non-options, set optind
421 * to the first of them.
423 optind
= nonopt_start
;
425 nonopt_start
= nonopt_end
= -1;
428 if (*(place
= nargv
[optind
]) != '-' ||
429 #ifdef GNU_COMPATIBLE
432 (place
[1] == '\0' && strchr(options
, '-') == NULL
)) {
434 place
= EMSG
; /* found non-option */
435 if (flags
& FLAG_ALLARGS
) {
438 * return non-option as argument to option 1
440 optarg
= nargv
[optind
++];
443 if (!(flags
& FLAG_PERMUTE
)) {
445 * If no permutation wanted, stop parsing
446 * at first non-option.
451 if (nonopt_start
== -1)
452 nonopt_start
= optind
;
453 else if (nonopt_end
!= -1) {
454 permute_args(nonopt_start
, nonopt_end
,
456 nonopt_start
= optind
-
457 (nonopt_end
- nonopt_start
);
461 /* process next argument */
464 if (nonopt_start
!= -1 && nonopt_end
== -1)
468 * If we have "-" do nothing, if "--" we are done.
470 if (place
[1] != '\0' && *++place
== '-' && place
[1] == '\0') {
474 * We found an option (--), so if we skipped
475 * non-options, we have to permute.
477 if (nonopt_end
!= -1) {
478 permute_args(nonopt_start
, nonopt_end
,
480 optind
-= nonopt_end
- nonopt_start
;
482 nonopt_start
= nonopt_end
= -1;
488 * Check long options if:
489 * 1) we were passed some
490 * 2) the arg is not just "-"
491 * 3) either the arg starts with -- we are getopt_long_only()
493 if (long_options
!= NULL
&& place
!= nargv
[optind
] &&
494 (*place
== '-' || (flags
& FLAG_LONGONLY
))) {
496 #ifdef GNU_COMPATIBLE
497 dash_prefix
= D_PREFIX
;
500 place
++; /* --foo long option */
501 #ifdef GNU_COMPATIBLE
502 dash_prefix
= DD_PREFIX
;
504 } else if (*place
!= ':' && strchr(options
, *place
) != NULL
)
505 short_too
= 1; /* could be short option too */
507 optchar
= parse_long_options(nargv
, options
, long_options
,
508 idx
, short_too
, flags
);
515 if ((optchar
= (int)*place
++) == (int)':' ||
516 (optchar
== (int)'-' && *place
!= '\0') ||
517 (oli
= strchr(options
, optchar
)) == NULL
) {
519 * If the user specified "-" and '-' isn't listed in
520 * options, return -1 (non-option) as per POSIX.
521 * Otherwise, it is an unknown option character (or ':').
523 if (optchar
== (int)'-' && *place
== '\0')
527 #ifdef GNU_COMPATIBLE
529 warnx(posixly_correct
? illoptchar
: gnuoptchar
,
533 warnx(illoptchar
, optchar
);
538 if (long_options
!= NULL
&& optchar
== 'W' && oli
[1] == ';') {
540 if (*place
) /* no space */
542 else if (++optind
>= nargc
) { /* no arg */
545 warnx(recargchar
, optchar
);
548 } else /* white space */
549 place
= nargv
[optind
];
550 #ifdef GNU_COMPATIBLE
551 dash_prefix
= W_PREFIX
;
553 optchar
= parse_long_options(nargv
, options
, long_options
,
558 if (*++oli
!= ':') { /* doesn't take argument */
561 } else { /* takes (optional) argument */
563 if (*place
) /* no white space */
565 else if (oli
[1] != ':') { /* arg not optional */
566 if (++optind
>= nargc
) { /* no arg */
569 warnx(recargchar
, optchar
);
573 optarg
= nargv
[optind
];
578 /* dump back option letter */
582 #ifdef REPLACE_GETOPT
585 * Parse argc/argv argument vector.
587 * [eventually this will replace the BSD getopt]
590 getopt(int nargc
, char * const *nargv
, const char *options
)
594 * We don't pass FLAG_PERMUTE to getopt_internal() since
595 * the BSD getopt(3) (unlike GNU) has never done this.
597 * Furthermore, since many privileged programs call getopt()
598 * before dropping privileges it makes sense to keep things
599 * as simple (and bug-free) as possible.
601 return (getopt_internal(nargc
, nargv
, options
, NULL
, NULL
, 0));
603 #endif /* REPLACE_GETOPT */
606 /*****************************************************************************
615 const struct option
*long_options
,
619 The getopt_long() function is similar to getopt() but it accepts options
620 in two forms: words and characters. The getopt_long() function provides
621 a superset of the functionality of getopt(3). The getopt_long() function
622 can be used in two ways. In the first way, every long option understood
623 by the program has a corresponding short option, and the option structure
624 is only used to translate from long options to short options. When used
625 in this fashion, getopt_long() behaves identically to getopt(3). This is
626 a good way to add long option processing to an existing program with the
627 minimum of rewriting.
629 In the second mechanism, a long option sets a flag in the option struc-
630 ture passed, or will store a pointer to the command line argument in the
631 option structure passed to it for options that take arguments. Addition-
632 ally, the long option's argument may be specified as a single argument
633 with an equal sign, e.g.,
635 myprogram --myoption=somevalue
637 When a long option is processed, the call to getopt_long() will return 0.
638 For this reason, long option processing without shortcuts is not back-
639 wards compatible with getopt(3).
641 It is possible to combine these methods, providing for long options pro-
642 cessing with short option equivalents for some options. Less frequently
643 used options would be processed as long options only.
645 The getopt_long() call requires a structure to be initialized describing
646 the long options. The structure is:
655 The name field should contain the option name without the leading double
658 The has_arg field should be one of:
660 no_argument no argument to the option is expect
661 required_argument an argument to the option is required
662 optional_argument an argument to the option may be presented.
664 If flag is not NULL, then the integer pointed to by it will be set to the
665 value in the val field. If the flag field is NULL, then the val field
666 will be returned. Setting flag to NULL and setting val to the corre-
667 sponding short option will make this function act just like getopt(3).
669 If the longindex field is not NULL, then the integer pointed to by it
670 will be set to the index of the long option relative to longopts.
672 The last element of the longopts array has to be filled with zeroes.
678 If the flag field in struct option is NULL, getopt_long() and
679 getopt_long_only() return the value specified in the val field, which is
680 usually just the corresponding short option. If flag is not NULL, these
681 functions return 0 and store val in the location pointed to by flag.
682 These functions return `:' if there was a missing option argument, `?' if
683 the user specified an unknown or ambiguous option, and -1 when the argu-
684 ment list has been exhausted.
687 Due to the usage of global variables this function is now put in
688 the static link library. This means each compilation unit using
689 getopt_long has its own getopt_long state tracking.
700 ******************************************************************************/
703 return (getopt_internal(nargc
, nargv
, options
, long_options
, idx
,
708 /*****************************************************************************
711 int getopt_long_only(
717 const struct option
*long_options
,
721 The getopt_long_only() function behaves identically to getopt_long() with
722 the exception that long options may start with `-' in addition to `--'.
723 If an option starting with `-' does not match a long option but does
724 match a single-character option, the single-character option is returned.
737 getopt(), getopt_long()
741 ******************************************************************************/
744 return (getopt_internal(nargc
, nargv
, options
, long_options
, idx
,
745 FLAG_PERMUTE
|FLAG_LONGONLY
));