import less(1)
[unleashed/tickless.git] / usr / src / lib / libc / port / gen / getopt_long.c
blob68cc6c3a8266ff023616fe045e0b6dd22708d23b
1 /*
2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
6 /*
7 * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
8 * All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
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. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
22 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
23 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
24 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * Copyright (c) 2000 The NetBSD Foundation, Inc.
34 * All rights reserved.
36 * This code is derived from software contributed to The NetBSD Foundation
37 * by Dieter Baron and Thomas Klausner.
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
41 * are met:
42 * 1. Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution.
47 * 3. All advertising materials mentioning features or use of this software
48 * must display the following acknowledgement:
49 * This product includes software developed by the NetBSD
50 * Foundation, Inc. and its contributors.
51 * 4. Neither the name of The NetBSD Foundation nor the names of its
52 * contributors may be used to endorse or promote products derived
53 * from this software without specific prior written permission.
55 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
56 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
57 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
58 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
59 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
60 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
61 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
62 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
63 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
64 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
65 * POSSIBILITY OF SUCH DAMAGE.
68 #pragma weak _getopt_clip = getopt_clip
69 #pragma weak _getopt_long = getopt_long
70 #pragma weak _getopt_long_only = getopt_long_only
72 #include "lint.h"
73 #include <getopt.h>
74 #include <stdio.h>
75 #include <errno.h>
76 #include <unistd.h>
77 #include <stdlib.h>
78 #include <string.h>
79 #include "_libc_gettext.h"
81 static int optreset = 0; /* keep track of first entry to getopt() */
82 #define PRINT_ERROR ((opterr) && (*options != ':'))
83 #define FLAG_IS_SET(flag) ((flags & flag) != 0) /* is flag turned on? */
85 /* Determine if an argument is required for this long option */
86 #define LONGOPT_REQUIRES_ARG(longopt) \
87 ((((longopt).has_arg == optional_argument) && \
88 (!FLAG_IS_SET(FLAG_OPTIONAL_ARGS))) || \
89 ((longopt).has_arg == required_argument))
91 #define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
92 #define FLAG_ALLARGS 0x02 /* treat non-options as args to option "1" */
93 #define FLAG_LONGONLY 0x04 /* operate as getopt_long_only() */
94 #define FLAG_OPTIONAL_ARGS 0x08 /* allow optional arguments to options */
95 #define FLAG_REQUIRE_EQUIVALENTS 0x10 /* require short<->long equivalents */
96 #define FLAG_ABBREV 0x20 /* long option abbreviation allowed. */
97 #define FLAG_W_SEMICOLON 0x40 /* Support for W; in optstring */
98 #define FLAG_PLUS_DASH_START 0x80 /* leading '+' or '-' in optstring */
100 /* return values */
101 #define BADCH (int)'?'
102 #define BADARG ((*options == ':') ? (int)':' : (int)'?')
103 #define INORDER (int)1
105 #define EMSG ""
107 static int getopt_internal(int, char * const *, const char *,
108 const struct option *, int *, uint_t);
109 static int parse_long_options(int nargc, char * const *nargv, const char *,
110 const struct option *, int *, int,
111 uint_t flags);
112 static int gcd(int, int);
113 static void permute_args(int, int, int, char * const *);
115 static char *place = EMSG; /* option letter processing */
117 /* XXX: set optreset to 1 rather than these two */
118 static int nonopt_start = -1; /* first non option argument (for permute) */
119 static int nonopt_end = -1; /* first option after non options (for permute) */
122 * Generalized error message output.
124 * NOTE ON ERROR MESSAGES: All the error messages in this file
125 * use %s (not %c) because they are all routed through warnx_getopt(),
126 * which takes a string argument. Character arguments passed
127 * to warnxchar() are converted to strings automatically before
128 * being passed to warnx_getopt().
130 static void
131 warnx_getopt(const char *argv0, const char *msg, const char *arg) {
132 char errbuf[256];
133 (void) snprintf(errbuf, sizeof (errbuf), msg, argv0, arg);
134 (void) write(2, errbuf, strlen(errbuf));
135 (void) write(2, "\n", 1);
139 * Generalized error message output.
141 static void
142 warnxchar(const char *argv0, const char *msg, const char c) {
143 char charbuf[2];
144 charbuf[0] = c;
145 charbuf[1] = '\0';
146 warnx_getopt(argv0, msg, charbuf);
150 * Generalized error message output.
152 static void
153 warnxlen(const char *argv0, const char *msg, int argLen, const char *arg) {
154 char argbuf[256];
155 (void) strncpy(argbuf, arg, argLen);
156 argbuf[argLen < (sizeof (argbuf)-1)? argLen:(sizeof (argbuf)-1)] = '\0';
157 warnx_getopt(argv0, msg, argbuf);
161 * Compute the greatest common divisor of a and b.
163 static int
164 gcd(int a, int b)
166 int c;
168 c = a % b;
169 while (c != 0) {
170 a = b;
171 b = c;
172 c = a % b;
175 return (b);
179 * Exchange the block from nonopt_start to nonopt_end with the block
180 * from nonopt_end to opt_end (keeping the same order of arguments
181 * in each block).
183 static void
184 permute_args(int panonopt_start, int panonopt_end, int opt_end,
185 char * const *nargv)
187 int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
188 char *swap;
191 * compute lengths of blocks and number and size of cycles
193 nnonopts = panonopt_end - panonopt_start;
194 nopts = opt_end - panonopt_end;
195 ncycle = gcd(nnonopts, nopts);
196 cyclelen = (opt_end - panonopt_start) / ncycle;
198 for (i = 0; i < ncycle; i++) {
199 cstart = panonopt_end+i;
200 pos = cstart;
201 for (j = 0; j < cyclelen; j++) {
202 if (pos >= panonopt_end)
203 pos -= nnonopts;
204 else
205 pos += nopts;
206 swap = nargv[pos];
207 ((char **)nargv)[pos] = nargv[cstart];
208 ((char **)nargv)[cstart] = swap;
211 } /* permute_args() */
214 * Verify that each short option (character flag) has a long equivalent,
215 * and that each long option has a short option equivalent. Note that
216 * multiple long options can map to the same character.
218 * This behavior is defined by Sun's CLIP specification (11/12/02),
219 * and currently getopt_clip() is the only getopt variant that
220 * requires it.
222 * If error output is enabled and an error is found, this function
223 * prints ONE error message (the first error found) and returns an
224 * error value.
226 * ASSUMES: options != NULL
227 * ASSUMES: long_options may be NULL
229 * Returns < 0 if an error is found
230 * Returns >= 0 on success
232 static int
233 /* LINTED: argument unused in function: nargc */
234 verify_short_long_equivalents(int nargc,
235 char *const *nargv,
236 const char *options,
237 const struct option *long_options,
238 uint_t flags) {
239 int short_i = 0;
240 int long_i = 0;
241 int equivFound = 0;
242 int ch = 0;
245 * Find a long option for each short option
247 equivFound = 1;
248 for (short_i = 0; equivFound && (options[short_i] != 0); ++short_i) {
249 ch = options[short_i];
251 if (ch == ':') {
252 continue;
254 if (FLAG_IS_SET(FLAG_W_SEMICOLON) &&
255 (ch == 'W') && (options[short_i+1] == ';')) {
256 /* W; is a special case */
257 ++short_i;
258 continue;
261 equivFound = 0;
262 if (long_options != NULL) {
263 for (long_i = 0; ((!equivFound) &&
264 (long_options[long_i].name != NULL));
265 ++long_i) {
266 equivFound = (ch == long_options[long_i].val);
269 if ((!equivFound) && (PRINT_ERROR)) {
270 warnxchar(nargv[0],
271 _libc_gettext(
272 "%s: equivalent long option required -- %s"),
273 ch);
275 } /* short_i */
278 * Find a short option for each long option. Note that if we came
279 * out of the above loop with equivFound==0, we are already done.
281 if (equivFound && (long_options != NULL)) {
282 for (long_i = 0; (equivFound &&
283 (long_options[long_i].name != NULL));
284 ++long_i) {
285 equivFound = ((long_options[long_i].val != 0) &&
286 (strchr(options, long_options[long_i].val)
287 != NULL));
289 if ((!equivFound) && (PRINT_ERROR)) {
290 warnx_getopt(nargv[0],
291 _libc_gettext(
292 "%s: equivalent short option required -- %s"),
293 long_options[long_i].name);
295 } /* for long_i */
298 return (equivFound? 0:-1);
299 } /* verify_short_long_equivalents() */
302 * parse_long_options --
303 * Parse long options in argc/argv argument vector.
304 * Returns -1 if short_too is set and the option does not match long_options.
306 static int
307 parse_long_options(int nargc, char * const *nargv, const char *options,
308 const struct option *long_options, int *idx, int short_too,
309 uint_t flags)
311 char *current_argv = NULL;
312 char *argv_equal_ptr = NULL;
313 size_t current_argv_len = 0;
314 size_t long_option_len = 0;
315 int i = 0;
316 int match = 0;
318 current_argv = place;
319 match = -1;
321 optind++;
323 if ((argv_equal_ptr = strchr(current_argv, '=')) != NULL) {
324 /* argument found (--option=arg) */
325 current_argv_len = (argv_equal_ptr - current_argv);
326 argv_equal_ptr++;
327 } else {
328 current_argv_len = strlen(current_argv);
331 for (i = 0; (long_options[i].name != NULL); i++) {
333 /* find matching long option */
334 if (strncmp(current_argv, long_options[i].name,
335 current_argv_len) != 0) {
336 continue; /* no match */
338 long_option_len = strlen(long_options[i].name);
339 if ((!FLAG_IS_SET(FLAG_ABBREV)) &&
340 (long_option_len > current_argv_len)) {
341 continue; /* Abbreviations are disabled */
344 if (long_option_len == current_argv_len) {
345 /* exact match */
346 match = i;
347 break;
350 * If this is a known short option, don't allow
351 * a partial match of a single character.
353 if (short_too && current_argv_len == 1)
354 continue;
356 if (match == -1) /* partial match */
357 match = i;
358 else {
359 /* ambiguous abbreviation */
360 if (PRINT_ERROR) {
361 warnxlen(nargv[0],
362 _libc_gettext(
363 "%s: ambiguous option -- %s"),
364 (int)current_argv_len,
365 current_argv);
367 optopt = 0;
368 return (BADCH);
370 } /* for i */
371 if (match != -1) { /* option found */
372 if ((long_options[match].has_arg == no_argument) &&
373 (argv_equal_ptr != NULL)) {
374 if (PRINT_ERROR) {
375 warnxlen(nargv[0],
376 _libc_gettext(
377 "%s: option doesn't take an argument -- %s"),
378 (int)current_argv_len,
379 current_argv);
382 * XXX: GNU sets optopt to val regardless of flag
384 if (long_options[match].flag == NULL)
385 optopt = long_options[match].val;
386 else
387 optopt = 0;
388 return (BADARG);
390 if (long_options[match].has_arg == required_argument ||
391 long_options[match].has_arg == optional_argument) {
392 if (argv_equal_ptr != NULL) {
393 optarg = argv_equal_ptr;
394 } else if (LONGOPT_REQUIRES_ARG(long_options[match])) {
395 /* The next argv must be the option argument */
396 if (optind < nargc) {
397 optarg = nargv[optind];
399 ++optind; /* code below depends on this */
402 if (LONGOPT_REQUIRES_ARG(long_options[match]) &&
403 (optarg == NULL)) {
405 * Missing argument; leading ':' indicates no error
406 * should be generated.
408 if (PRINT_ERROR) {
409 warnx_getopt(nargv[0],
410 _libc_gettext(
411 "%s: option requires an argument -- %s"),
412 current_argv);
415 * XXX: GNU sets optopt to val regardless of flag
417 if (long_options[match].flag == NULL)
418 optopt = long_options[match].val;
419 else
420 optopt = 0;
421 --optind;
422 return (BADARG);
424 } else { /* unknown option */
425 if (short_too) {
426 --optind;
427 return (-1);
429 if (PRINT_ERROR) {
430 warnx_getopt(nargv[0],
431 _libc_gettext("%s: illegal option -- %s"),
432 current_argv);
434 optopt = 0;
435 return (BADCH);
437 if (idx)
438 *idx = match;
439 if (long_options[match].flag != NULL) {
440 *long_options[match].flag = long_options[match].val;
441 return (0);
442 } else {
443 optopt = long_options[match].val;
444 return (optopt);
446 } /* parse_long_options() */
449 * getopt_internal() --
450 * Parse argc/argv argument vector. Called by user level routines.
452 * This implements all of the getopt_long(), getopt_long_only(),
453 * getopt_clip() variants.
455 static int
456 getopt_internal(int nargc, char * const *nargv, const char *options,
457 const struct option *long_options, int *idx, uint_t flags)
459 char *oli; /* option letter list index */
460 int optchar, short_too;
461 static int posixly_correct = -1;
463 if (options == NULL)
464 return (-1);
467 * Disable GNU extensions if POSIXLY_CORRECT is set or options
468 * string begins with a '+'.
470 if (posixly_correct == -1) {
471 posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
473 if (FLAG_IS_SET(FLAG_PLUS_DASH_START)) {
475 * + or - at start of optstring takes precedence
476 * over POSIXLY_CORRECT.
478 if (*options == '+') {
480 * leading + means POSIX-compliant; first non-option
481 * ends option list. Therefore, don't permute args.
483 posixly_correct = 1;
484 } else if (*options == '-') {
485 posixly_correct = 0;
486 flags |= FLAG_ALLARGS;
488 if ((*options == '+') || (*options == '-')) {
489 options++;
491 } /* if FLAG_PLUS_DASH_START */
493 if (posixly_correct) {
494 flags &= ~FLAG_PERMUTE;
495 flags &= ~FLAG_ALLARGS;
499 * Some programs (like GNU cvs) set optind to 0 to restart
500 * option processing. Work around this braindamage.
502 * The above problem comes from using global variables. We
503 * should avoid their use in the future.
505 if (optind == 0) {
506 optind = optreset = 1;
509 optarg = NULL;
510 optopt = 0;
512 if (optreset) {
513 nonopt_start = nonopt_end = -1;
517 * On the first call, make sure that there is a short equivalent
518 * for each long option, and vice versa. This is required by
519 * Sun's CLIP specification (11/12/02).
521 if ((optind == 1) && FLAG_IS_SET(FLAG_REQUIRE_EQUIVALENTS)) {
522 if (verify_short_long_equivalents(
523 nargc, nargv, options, long_options, flags) < 0) {
524 /* function printed any necessary messages */
525 errno = EINVAL; /* invalid argument */
526 return (-1);
530 start:
531 if (optreset || !*place) { /* update scanning pointer */
532 optreset = 0;
533 if (optind >= nargc) { /* end of argument vector */
534 place = EMSG;
535 if (nonopt_end != -1) {
536 /* do permutation, if we have to */
537 permute_args(nonopt_start, nonopt_end,
538 optind, nargv);
539 optind -= nonopt_end - nonopt_start;
541 } else if (nonopt_start != -1) {
543 * If we skipped non-options, set optind
544 * to the first of them.
546 optind = nonopt_start;
548 nonopt_start = nonopt_end = -1;
549 return (-1);
551 if ((*(place = nargv[optind]) != '-') || (place[1] == '\0')) {
552 place = EMSG; /* found non-option */
553 if (flags & FLAG_ALLARGS) {
555 * GNU extension:
556 * return non-option as argument to option '\1'
558 optarg = nargv[optind++];
559 return (INORDER);
561 if (!(flags & FLAG_PERMUTE)) {
563 * If no permutation wanted, stop parsing
564 * at first non-option.
566 return (-1);
568 /* do permutation */
569 if (nonopt_start == -1)
570 nonopt_start = optind;
571 else if (nonopt_end != -1) {
572 permute_args(nonopt_start, nonopt_end,
573 optind, nargv);
574 nonopt_start = optind -
575 (nonopt_end - nonopt_start);
576 nonopt_end = -1;
578 optind++;
579 /* process next argument */
580 goto start;
582 if (nonopt_start != -1 && nonopt_end == -1)
583 nonopt_end = optind;
586 * Check for "--" or "--foo" with no long options
587 * but if place is simply "-" leave it unmolested.
589 if (place[1] != '\0' && *++place == '-' &&
590 (place[1] == '\0' || long_options == NULL)) {
591 optind++;
592 place = EMSG;
594 * We found an option (--), so if we skipped
595 * non-options, we have to permute.
597 if (nonopt_end != -1) {
598 permute_args(nonopt_start, nonopt_end,
599 optind, nargv);
600 optind -= nonopt_end - nonopt_start;
602 nonopt_start = nonopt_end = -1;
603 return (-1);
608 * Check long options if:
609 * 1) we were passed some
610 * 2) the arg is not just "-"
611 * 3) either the arg starts with -- or we are getopt_long_only()
613 if (long_options != NULL && place != nargv[optind] &&
614 (*place == '-' || (FLAG_IS_SET(FLAG_LONGONLY)))) {
615 short_too = 0;
616 if (*place == '-')
617 place++; /* --foo long option */
618 else if (*place != ':' && strchr(options, *place) != NULL)
619 short_too = 1; /* could be short option too */
621 optchar = parse_long_options(nargc, nargv, options,
622 long_options, idx, short_too, flags);
623 if (optchar != -1) {
624 place = EMSG;
625 return (optchar);
629 if ((optchar = (int)*place++) == (int)':' ||
630 (oli = strchr(options, optchar)) == NULL) {
632 * If the user didn't specify '-' as an option,
633 * assume it means -1 as POSIX specifies.
635 if (optchar == (int)'-')
636 return (-1);
637 /* option letter unknown or ':' */
638 if (!*place)
639 ++optind;
640 if (PRINT_ERROR)
641 warnxchar(nargv[0],
642 _libc_gettext("%s: illegal option -- %s"),
643 optchar);
644 optopt = optchar;
645 return (BADCH);
647 if (FLAG_IS_SET(FLAG_W_SEMICOLON) &&
648 (long_options != NULL) && (optchar == 'W') && (oli[1] == ';')) {
649 /* -W long-option */
650 /* LINTED: statement has no consequent: if */
651 if (*place) { /* no space */
652 /* NOTHING */;
653 } else if (++optind >= nargc) { /* no long-option after -W */
654 place = EMSG;
655 if (PRINT_ERROR)
656 warnxchar(nargv[0],
657 _libc_gettext(
658 "%s: option requires an argument -- %s"),
659 optchar);
660 optopt = optchar;
661 return (BADARG);
662 } else { /* white space */
663 place = nargv[optind];
665 optchar = parse_long_options(
666 nargc, nargv, options, long_options,
667 idx, 0, flags);
670 * PSARC 2003/645 - Match GNU behavior, set optarg to
671 * the long-option.
673 if (optarg == NULL) {
674 optarg = nargv[optind-1];
676 place = EMSG;
677 return (optchar);
679 if (*++oli != ':') { /* doesn't take argument */
680 if (!*place)
681 ++optind;
682 } else { /* takes (optional) argument */
683 optarg = NULL;
684 if (*place) { /* no white space */
685 optarg = place;
686 /* XXX: disable test for :: if PC? (GNU doesn't) */
687 } else if (!(FLAG_IS_SET(FLAG_OPTIONAL_ARGS) &&
688 (oli[1] == ':'))) {
689 /* arg is required (not optional) */
691 if (++optind >= nargc) { /* no arg */
692 place = EMSG;
693 if (PRINT_ERROR) {
694 warnxchar(nargv[0],
695 _libc_gettext(
696 "%s: option requires an argument -- %s"),
697 optchar);
699 optopt = optchar;
700 return (BADARG);
701 } else
702 optarg = nargv[optind];
704 place = EMSG;
705 ++optind;
707 /* return valid option letter */
708 optopt = optchar; /* preserve getopt() behavior */
709 return (optchar);
710 } /* getopt_internal() */
713 * getopt_long() --
714 * Parse argc/argv argument vector.
716 * Requires that long options be preceded with a two dashes
717 * (e.g., --longoption).
720 getopt_long(int nargc, char *const *nargv,
721 const char *optstring,
722 const struct option *long_options, int *long_index)
725 return (getopt_internal(
726 nargc, nargv, optstring, long_options, long_index,
727 FLAG_PERMUTE
728 | FLAG_OPTIONAL_ARGS
729 | FLAG_ABBREV
730 | FLAG_W_SEMICOLON
731 | FLAG_PLUS_DASH_START));
732 } /* getopt_long() */
735 * getopt_long_only() --
736 * Parse argc/argv argument vector.
738 * Long options may be preceded with a single dash (e.g., -longoption)
741 getopt_long_only(int nargc, char *const *nargv,
742 const char *optstring,
743 const struct option *long_options, int *long_index)
746 return (getopt_internal(
747 nargc, nargv, optstring, long_options, long_index,
748 FLAG_PERMUTE
749 | FLAG_OPTIONAL_ARGS
750 | FLAG_ABBREV
751 | FLAG_W_SEMICOLON
752 | FLAG_PLUS_DASH_START
753 | FLAG_LONGONLY));
754 } /* getopt_long_only() */
757 * getopt_clip() --
758 * Parse argc/argv argument vector, requiring compliance with
759 * Sun's CLIP specification (11/12/02)
761 * o Does not allow arguments to be optional (optional_argument is
762 * treated as required_argument).
764 * o Does not allow long options to be abbreviated on the command line
766 * o Does not allow long argument to be preceded by a single dash
767 * (Double-dash '--' is required)
769 * o Stops option processing at the first non-option
771 * o Requires that every long option have a short-option (single
772 * character) equivalent and vice-versa. If a short option or
773 * long option without an equivalent is found, an error message
774 * is printed and -1 is returned on the first call, and errno
775 * is set to EINVAL.
777 * o Leading + or - in optstring is ignored, and opstring is
778 * treated as if it began after the + or - .
781 getopt_clip(int nargc, char *const *nargv,
782 const char *optstring,
783 const struct option *long_options, int *long_index)
785 return getopt_internal(
786 nargc, nargv, optstring, long_options, long_index,
788 * no permutation,
789 * no optional args,
790 * no long-only,
791 * no abbreviations
792 * no support for +- at start of optstring
793 * yes support for "W;" in optstring
795 FLAG_W_SEMICOLON
796 | FLAG_REQUIRE_EQUIVALENTS);
797 } /* getopt_clip() */