]>
git.ipfire.org Git - thirdparty/bash.git/blob - builtins/bashgetopt.c
1 /* bashgetopt.c -- `getopt' for use by the builtins. */
3 /* Copyright (C) 1992-2021 Free Software Foundation, Inc.
5 This file is part of GNU Bash, the Bourne Again SHell.
7 Bash is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 Bash is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Bash. If not, see <http://www.gnu.org/licenses/>.
23 #if defined (HAVE_UNISTD_H)
27 #include "../bashansi.h"
28 #include <chartypes.h>
34 #include "bashgetopt.h"
36 #define ISOPT(s) (((*(s) == '-') || (plus && *(s) == '+')) && (s)[1])
37 #define NOTOPT(s) (((*(s) != '-') && (!plus || *(s) != '+')) || (s)[1] == '\0')
46 static WORD_LIST
*lhead
= (WORD_LIST
*)NULL
;
47 WORD_LIST
*lcurrent
= (WORD_LIST
*)NULL
;
48 WORD_LIST
*loptend
; /* Points to the first non-option argument in the list */
51 internal_getopt(list
, opts
)
57 int plus
; /* nonzero means to handle +option */
58 static char errstr
[3] = { '-', '\0', '\0' };
65 list_optarg
= (char *)NULL
;
67 loptend
= (WORD_LIST
*)NULL
; /* No non-option arguments */
71 if (list
!= lhead
|| lhead
== 0) {
72 /* Hmmm.... called with a different word list. Reset. */
74 lcurrent
= lhead
= list
;
75 loptend
= (WORD_LIST
*)NULL
;
79 if (lcurrent
== 0 || NOTOPT(lcurrent
->word
->word
)) {
80 lhead
= (WORD_LIST
*)NULL
;
83 } else if (ISHELP (lcurrent
->word
->word
)) {
84 lhead
= (WORD_LIST
*)NULL
;
87 } else if (lcurrent
->word
->word
[0] == '-' &&
88 lcurrent
->word
->word
[1] == '-' &&
89 lcurrent
->word
->word
[2] == 0) {
90 lhead
= (WORD_LIST
*)NULL
;
91 loptend
= lcurrent
->next
;
94 errstr
[0] = list_opttype
= lcurrent
->word
->word
[0];
97 list_optopt
= c
= lcurrent
->word
->word
[sp
];
99 if (c
== ':' || (cp
= strchr(opts
, c
)) == NULL
) {
101 sh_invalidopt (errstr
);
102 if (lcurrent
->word
->word
[++sp
] == '\0') {
103 lcurrent
= lcurrent
->next
;
109 loptend
= lcurrent
->next
;
113 if (*++cp
== ':' || *cp
== ';') {
114 /* `:': Option requires an argument. */
115 /* `;': option argument may be missing */
116 /* We allow -l2 as equivalent to -l 2 */
117 if (lcurrent
->word
->word
[sp
+1]) {
118 list_optarg
= lcurrent
->word
->word
+ sp
+ 1;
120 lcurrent
= lcurrent
->next
;
121 /* If the specifier is `;', don't set optarg if the next
122 argument looks like another option. */
124 } else if (lcurrent
->next
&& (*cp
== ':' || lcurrent
->next
->word
->word
[0] != '-')) {
126 } else if (lcurrent
->next
&& (*cp
== ':' || NOTOPT(lcurrent
->next
->word
->word
))) {
128 lcurrent
= lcurrent
->next
;
129 list_optarg
= lcurrent
->word
->word
;
130 list_optflags
= lcurrent
->word
->flags
;
131 lcurrent
= lcurrent
->next
;
132 } else if (*cp
== ';') {
133 list_optarg
= (char *)NULL
;
135 lcurrent
= lcurrent
->next
;
136 } else { /* lcurrent->next == NULL */
140 list_optarg
= (char *)NULL
;
145 } else if (*cp
== '#') {
146 /* option requires a numeric argument */
147 if (lcurrent
->word
->word
[sp
+1]) {
148 if (DIGIT(lcurrent
->word
->word
[sp
+1])) {
149 list_optarg
= lcurrent
->word
->word
+ sp
+ 1;
151 lcurrent
= lcurrent
->next
;
153 list_optarg
= (char *)NULL
;
157 if (lcurrent
->next
&& legal_number(lcurrent
->next
->word
->word
, (intmax_t *)0)) {
158 lcurrent
= lcurrent
->next
;
159 list_optarg
= lcurrent
->word
->word
;
160 list_optflags
= lcurrent
->word
->flags
;
161 lcurrent
= lcurrent
->next
;
164 sh_neednumarg (errstr
);
166 list_optarg
= (char *)NULL
;
173 /* No argument, just return the option. */
174 if (lcurrent
->word
->word
[++sp
] == '\0') {
176 lcurrent
= lcurrent
->next
;
178 list_optarg
= (char *)NULL
;
186 * reset_internal_getopt -- force the in[ft]ernal getopt to reset
190 reset_internal_getopt ()
192 lhead
= lcurrent
= loptend
= (WORD_LIST
*)NULL
;