]>
sourceware.org Git - newlib-cygwin.git/blob - winsup/cygwin/libc/getopt.c
1 /* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */
4 * Copyright (c) 2000 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Dieter Baron and Thomas Klausner.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
48 #define REPLACE_GETOPT
50 #define _DIAGASSERT(x) do {} while (0)
54 __weak_alias(getopt
,_getopt
)
56 int __declspec(dllexport
) opterr
; /* if error message should be printed */
57 int __declspec(dllexport
) optind
; /* index into parent argv vector */
58 int __declspec(dllexport
) optopt
; /* character checked for validity */
59 int __declspec(dllexport
) optreset
; /* reset getopt */
60 char __declspec(dllexport
) *optarg
; /* argument associated with option */
64 __weak_alias(getopt_long
,_getopt_long
)
68 #define __progname __argv[0]
70 extern char *__progname
;
73 #define IGNORE_FIRST (*options == '-' || *options == '+')
74 #define PRINT_ERROR ((opterr) && ((*options != ':') \
75 || (IGNORE_FIRST && options[1] != ':')))
77 #define IS_POSIXLY_CORRECT (getenv("POSIXLY_INCORRECT_GETOPT") == NULL)
79 #define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST)
80 /* XXX: GNU ignores PC if *options == '-' */
81 #define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-')
84 #define BADCH (int)'?'
85 #define BADARG ((IGNORE_FIRST && options[1] == ':') \
86 || (*options == ':') ? (int)':' : (int)'?')
87 #define INORDER (int)1
91 static int getopt_internal (int, char * const *, const char *);
92 static int gcd (int, int);
93 static void permute_args (int, int, int, char * const *);
95 static char *place
= EMSG
; /* option letter processing */
97 /* XXX: set optreset to 1 rather than these two */
98 static int nonopt_start
= -1; /* first non option argument (for permute) */
99 static int nonopt_end
= -1; /* first option after non options (for permute) */
102 static const char recargchar
[] = "option requires an argument -- %c";
103 static const char recargstring
[] = "option requires an argument -- %s";
104 static const char ambig
[] = "ambiguous option -- %.*s";
105 static const char noarg
[] = "option doesn't take an argument -- %.*s";
106 static const char illoptchar
[] = "unknown option -- %c";
107 static const char illoptstring
[] = "unknown option -- %s";
110 _vwarnx(const char *fmt
, va_list ap
)
112 (void)fprintf(stderr
, "%s: ", __progname
);
114 (void)vfprintf(stderr
, fmt
, ap
);
115 (void)fprintf(stderr
, "\n");
119 warnx(const char *fmt
, ...)
128 * Compute the greatest common divisor of a and b.
148 * Exchange the block from nonopt_start to nonopt_end with the block
149 * from nonopt_end to opt_end (keeping the same order of arguments
153 permute_args(panonopt_start
, panonopt_end
, opt_end
, nargv
)
159 int cstart
, cyclelen
, i
, j
, ncycle
, nnonopts
, nopts
, pos
;
162 _DIAGASSERT(nargv
!= NULL
);
165 * compute lengths of blocks and number and size of cycles
167 nnonopts
= panonopt_end
- panonopt_start
;
168 nopts
= opt_end
- panonopt_end
;
169 ncycle
= gcd(nnonopts
, nopts
);
170 cyclelen
= (opt_end
- panonopt_start
) / ncycle
;
172 for (i
= 0; i
< ncycle
; i
++) {
173 cstart
= panonopt_end
+i
;
175 for (j
= 0; j
< cyclelen
; j
++) {
176 if (pos
>= panonopt_end
)
181 /* LINTED const cast */
182 ((char **) nargv
)[pos
] = nargv
[cstart
];
183 /* LINTED const cast */
184 ((char **)nargv
)[cstart
] = swap
;
191 * Parse argc/argv argument vector. Called by user level routines.
192 * Returns -2 if -- is found (can be long option or end of options marker).
195 getopt_internal(nargc
, nargv
, options
)
200 char *oli
; /* option letter list index */
203 _DIAGASSERT(nargv
!= NULL
);
204 _DIAGASSERT(options
!= NULL
);
209 * XXX Some programs (like rsyncd) expect to be able to
210 * XXX re-initialize optind to 0 and have getopt_long(3)
211 * XXX properly function again. Work around this braindamage.
217 nonopt_start
= nonopt_end
= -1;
219 if (optreset
|| !*place
) { /* update scanning pointer */
221 if (optind
>= nargc
) { /* end of argument vector */
223 if (nonopt_end
!= -1) {
224 /* do permutation, if we have to */
225 permute_args(nonopt_start
, nonopt_end
,
227 optind
-= nonopt_end
- nonopt_start
;
229 else if (nonopt_start
!= -1) {
231 * If we skipped non-options, set optind
232 * to the first of them.
234 optind
= nonopt_start
;
236 nonopt_start
= nonopt_end
= -1;
239 if ((*(place
= nargv
[optind
]) != '-')
240 || (place
[1] == '\0')) { /* found non-option */
245 * return non-option as argument to option 1
247 optarg
= nargv
[optind
++];
252 * if no permutation wanted, stop parsing
253 * at first non-option
258 if (nonopt_start
== -1)
259 nonopt_start
= optind
;
260 else if (nonopt_end
!= -1) {
261 permute_args(nonopt_start
, nonopt_end
,
263 nonopt_start
= optind
-
264 (nonopt_end
- nonopt_start
);
268 /* process next argument */
271 if (nonopt_start
!= -1 && nonopt_end
== -1)
273 if (place
[1] && *++place
== '-') { /* found "--" */
278 if ((optchar
= (int)*place
++) == (int)':' ||
279 (oli
= strchr(options
+ (IGNORE_FIRST
? 1 : 0), optchar
)) == NULL
) {
280 /* option letter unknown or ':' */
284 warnx(illoptchar
, optchar
);
288 if (optchar
== 'W' && oli
[1] == ';') { /* -W long-option */
289 /* XXX: what if no long options provided (called by getopt)? */
293 if (++optind
>= nargc
) { /* no arg */
296 warnx(recargchar
, optchar
);
299 } else /* white space */
300 place
= nargv
[optind
];
302 * Handle -W arg the same as --arg (which causes getopt to
307 if (*++oli
!= ':') { /* doesn't take argument */
310 } else { /* takes (optional) argument */
312 if (*place
) /* no white space */
314 /* XXX: disable test for :: if PC? (GNU doesn't) */
315 else if (oli
[1] != ':') { /* arg not optional */
316 if (++optind
>= nargc
) { /* no arg */
319 warnx(recargchar
, optchar
);
323 optarg
= nargv
[optind
];
328 /* dump back option letter */
332 #ifdef REPLACE_GETOPT
335 * Parse argc/argv argument vector.
337 * [eventually this will replace the real getopt]
340 getopt(nargc
, nargv
, options
)
347 _DIAGASSERT(nargv
!= NULL
);
348 _DIAGASSERT(options
!= NULL
);
350 if ((retval
= getopt_internal(nargc
, nargv
, options
)) == -2) {
353 * We found an option (--), so if we skipped non-options,
354 * we have to permute.
356 if (nonopt_end
!= -1) {
357 permute_args(nonopt_start
, nonopt_end
, optind
,
359 optind
-= nonopt_end
- nonopt_start
;
361 nonopt_start
= nonopt_end
= -1;
370 * Parse argc/argv argument vector.
373 getopt_long(nargc
, nargv
, options
, long_options
, idx
)
377 const struct option
*long_options
;
382 _DIAGASSERT(nargv
!= NULL
);
383 _DIAGASSERT(options
!= NULL
);
384 _DIAGASSERT(long_options
!= NULL
);
385 /* idx may be NULL */
387 if ((retval
= getopt_internal(nargc
, nargv
, options
)) == -2) {
388 char *current_argv
, *has_equal
;
389 size_t current_argv_len
;
392 current_argv
= place
;
398 if (*current_argv
== '\0') { /* found "--" */
400 * We found an option (--), so if we skipped
401 * non-options, we have to permute.
403 if (nonopt_end
!= -1) {
404 permute_args(nonopt_start
, nonopt_end
,
406 optind
-= nonopt_end
- nonopt_start
;
408 nonopt_start
= nonopt_end
= -1;
411 if ((has_equal
= strchr(current_argv
, '=')) != NULL
) {
412 /* argument found (--option=arg) */
413 current_argv_len
= has_equal
- current_argv
;
416 current_argv_len
= strlen(current_argv
);
418 for (i
= 0; long_options
[i
].name
; i
++) {
419 /* find matching long option */
420 if (strncmp(current_argv
, long_options
[i
].name
,
424 if (strlen(long_options
[i
].name
) ==
425 (unsigned)current_argv_len
) {
430 if (match
== -1) /* partial match */
433 /* ambiguous abbreviation */
435 warnx(ambig
, (int)current_argv_len
,
441 if (match
!= -1) { /* option found */
442 if (long_options
[match
].has_arg
== no_argument
445 warnx(noarg
, (int)current_argv_len
,
448 * XXX: GNU sets optopt to val regardless of
451 if (long_options
[match
].flag
== NULL
)
452 optopt
= long_options
[match
].val
;
457 if (long_options
[match
].has_arg
== required_argument
||
458 long_options
[match
].has_arg
== optional_argument
) {
461 else if (long_options
[match
].has_arg
==
464 * optional argument doesn't use
467 optarg
= nargv
[optind
++];
470 if ((long_options
[match
].has_arg
== required_argument
)
471 && (optarg
== NULL
)) {
473 * Missing argument; leading ':'
474 * indicates no error should be generated
477 warnx(recargstring
, current_argv
);
479 * XXX: GNU sets optopt to val regardless
482 if (long_options
[match
].flag
== NULL
)
483 optopt
= long_options
[match
].val
;
489 } else { /* unknown option */
491 warnx(illoptstring
, current_argv
);
495 if (long_options
[match
].flag
) {
496 *long_options
[match
].flag
= long_options
[match
].val
;
499 retval
= long_options
[match
].val
;
This page took 0.06106 seconds and 5 git commands to generate.