2 * my_getopt.c - my re-implementation of getopt.
3 * Copyright 1997, 2000, 2001, 2002, Benjamin Sittler
5 * Permission is hereby granted, free of charge, to any person
6 * obtaining a copy of this software and associated documentation
7 * files (the "Software"), to deal in the Software without
8 * restriction, including without limitation the rights to use, copy,
9 * modify, merge, publish, distribute, sublicense, and/or sell copies
10 * of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
26 #include <sys/types.h>
30 #include "my_getopt.h"
32 int my_optind
=1, my_opterr
=1, my_optopt
=0;
35 /* this is the plain old UNIX getopt, with GNU-style extensions. */
36 /* if you're porting some piece of UNIX software, this is all you need. */
37 /* this supports GNU-style permution and optional arguments */
39 int my_getopt(int argc
, char * argv
[], const char *opts
)
43 char mode
, colon_mode
;
44 int off
= 0, opt
= -1;
46 if(getenv("POSIXLY_CORRECT")) colon_mode
= mode
= '+';
48 if((colon_mode
= *opts
) == ':') off
++;
49 if(((mode
= opts
[off
]) == '+') || (mode
== '-')) {
51 if((colon_mode
!= ':') && ((colon_mode
= opts
[off
]) == ':'))
57 my_optopt
= argv
[my_optind
][charind
];
58 for(s
=opts
+off
; *s
; s
++) if(my_optopt
== *s
) {
60 if((*(++s
) == ':') || ((my_optopt
== 'W') && (*s
== ';'))) {
61 if(argv
[my_optind
][charind
]) {
62 my_optarg
= &(argv
[my_optind
++][charind
]);
64 } else if(*(++s
) != ':') {
66 if(++my_optind
>= argc
) {
67 if(my_opterr
) fprintf(stderr
,
68 "%s: option requires an argument -- %c\n",
70 opt
= (colon_mode
== ':') ? ':' : '?';
73 my_optarg
= argv
[my_optind
++];
79 if(my_opterr
) fprintf(stderr
,
80 "%s: illegal option -- %c\n",
83 if(argv
[my_optind
][++charind
] == '\0') {
88 if(charind
&& ! argv
[my_optind
][charind
]) {
92 } else if((my_optind
>= argc
) ||
93 ((argv
[my_optind
][0] == '-') &&
94 (argv
[my_optind
][1] == '-') &&
95 (argv
[my_optind
][2] == '\0'))) {
98 } else if((argv
[my_optind
][0] != '-') ||
99 (argv
[my_optind
][1] == '\0')) {
103 if(mode
== '+') opt
= -1;
104 else if(mode
== '-') {
105 my_optarg
= argv
[my_optind
++];
109 for(i
=j
=my_optind
; i
<argc
; i
++) if((argv
[i
][0] == '-') &&
110 (argv
[i
][1] != '\0')) {
112 opt
=my_getopt(argc
, argv
, opts
);
115 for(k
=i
; k
+1<my_optind
; k
++) argv
[k
]=argv
[k
+1];
116 argv
[--my_optind
]=tmp
;
120 if(i
== argc
) opt
= -1;
124 opt
= my_getopt(argc
, argv
, opts
);
126 if (my_optind
> argc
) my_optind
= argc
;
130 /* this is the extended getopt_long{,_only}, with some GNU-like
131 * extensions. Implements _getopt_internal in case any programs
132 * expecting GNU libc getopt call it.
135 int _my_getopt_internal(int argc
, char * argv
[], const char *shortopts
,
136 const struct option
*longopts
, int *longind
,
139 char mode
, colon_mode
= *shortopts
;
140 int shortoff
= 0, opt
= -1;
142 if(getenv("POSIXLY_CORRECT")) colon_mode
= mode
= '+';
144 if((colon_mode
= *shortopts
) == ':') shortoff
++;
145 if(((mode
= shortopts
[shortoff
]) == '+') || (mode
== '-')) {
147 if((colon_mode
!= ':') && ((colon_mode
= shortopts
[shortoff
]) == ':'))
152 if((my_optind
>= argc
) ||
153 ((argv
[my_optind
][0] == '-') &&
154 (argv
[my_optind
][1] == '-') &&
155 (argv
[my_optind
][2] == '\0'))) {
158 } else if((argv
[my_optind
][0] != '-') ||
159 (argv
[my_optind
][1] == '\0')) {
164 if(mode
== '+') return -1;
165 else if(mode
== '-') {
166 my_optarg
= argv
[my_optind
++];
169 for(i
=j
=my_optind
; i
<argc
; i
++) if((argv
[i
][0] == '-') &&
170 (argv
[i
][1] != '\0')) {
172 opt
=_my_getopt_internal(argc
, argv
, shortopts
,
177 for(k
=i
; k
+1<my_optind
; k
++)
179 argv
[--my_optind
]=tmp
;
183 } else if((!long_only
) && (argv
[my_optind
][1] != '-'))
184 opt
= my_getopt(argc
, argv
, shortopts
);
187 int found
= 0, ind
, hits
= 0;
189 if(((my_optopt
= argv
[my_optind
][1]) != '-') && ! argv
[my_optind
][2]) {
193 while((c
= shortopts
[ind
++])) {
194 if(((shortopts
[ind
] == ':') ||
195 ((c
== 'W') && (shortopts
[ind
] == ';'))) &&
196 (shortopts
[++ind
] == ':'))
198 if(my_optopt
== c
) return my_getopt(argc
, argv
, shortopts
);
201 offset
= 2 - (argv
[my_optind
][1] != '-');
202 for(charind
= offset
;
203 (argv
[my_optind
][charind
] != '\0') &&
204 (argv
[my_optind
][charind
] != '=');
206 for(ind
= 0; longopts
[ind
].name
&& !hits
; ind
++)
207 if((strlen(longopts
[ind
].name
) == (size_t) (charind
- offset
)) &&
208 (strncmp(longopts
[ind
].name
,
209 argv
[my_optind
] + offset
, charind
- offset
) == 0))
211 if(!hits
) for(ind
= 0; longopts
[ind
].name
; ind
++)
212 if(strncmp(longopts
[ind
].name
,
213 argv
[my_optind
] + offset
, charind
- offset
) == 0)
218 if(argv
[my_optind
][charind
] == '=') {
219 if(longopts
[found
].has_arg
== 0) {
221 if(my_opterr
) fprintf(stderr
,
222 "%s: option `--%s' doesn't allow an argument\n",
223 argv
[0], longopts
[found
].name
);
225 my_optarg
= argv
[my_optind
] + ++charind
;
228 } else if(longopts
[found
].has_arg
== 1) {
229 if(++my_optind
>= argc
) {
230 opt
= (colon_mode
== ':') ? ':' : '?';
231 if(my_opterr
) fprintf(stderr
,
232 "%s: option `--%s' requires an argument\n",
233 argv
[0], longopts
[found
].name
);
234 } else my_optarg
= argv
[my_optind
];
237 if (longind
) *longind
= found
;
238 if(!longopts
[found
].flag
) opt
= longopts
[found
].val
;
239 else *(longopts
[found
].flag
) = longopts
[found
].val
;
243 if(offset
== 1) opt
= my_getopt(argc
, argv
, shortopts
);
246 if(my_opterr
) fprintf(stderr
,
247 "%s: unrecognized option `%s'\n",
248 argv
[0], argv
[my_optind
++]);
252 if(my_opterr
) fprintf(stderr
,
253 "%s: option `%s' is ambiguous\n",
254 argv
[0], argv
[my_optind
++]);
257 if (my_optind
> argc
) my_optind
= argc
;
261 int my_getopt_long(int argc
, char * argv
[], const char *shortopts
,
262 const struct option
*longopts
, int *longind
)
264 return _my_getopt_internal(argc
, argv
, shortopts
, longopts
, longind
, 0);
267 int my_getopt_long_only(int argc
, char * argv
[], const char *shortopts
,
268 const struct option
*longopts
, int *longind
)
270 return _my_getopt_internal(argc
, argv
, shortopts
, longopts
, longind
, 1);