9 date 2004.12.06.04.53.28; author kenth; state Exp;
24 * my_getopt.c - my re-implementation of getopt.
25 * Copyright 1997, 2000, 2001, 2002, Benjamin Sittler
27 * Permission is hereby granted, free of charge, to any person
28 * obtaining a copy of this software and associated documentation
29 * files (the "Software"), to deal in the Software without
30 * restriction, including without limitation the rights to use, copy,
31 * modify, merge, publish, distribute, sublicense, and/or sell copies
32 * of the Software, and to permit persons to whom the Software is
33 * furnished to do so, subject to the following conditions:
35 * The above copyright notice and this permission notice shall be
36 * included in all copies or substantial portions of the Software.
38 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
39 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
40 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
41 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
42 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
43 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
44 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
45 * DEALINGS IN THE SOFTWARE.
48 #include <sys/types.h>
52 #include "my_getopt.h"
54 int my_optind=1, my_opterr=1, my_optopt=0;
57 /* this is the plain old UNIX getopt, with GNU-style extensions. */
58 /* if you're porting some piece of UNIX software, this is all you need. */
59 /* this supports GNU-style permution and optional arguments */
61 int my_getopt(int argc, char * argv[], const char *opts)
65 char mode, colon_mode;
66 int off = 0, opt = -1;
68 if(getenv("POSIXLY_CORRECT")) colon_mode = mode = '+';
70 if((colon_mode = *opts) == ':') off ++;
71 if(((mode = opts[off]) == '+') || (mode == '-')) {
73 if((colon_mode != ':') && ((colon_mode = opts[off]) == ':'))
79 my_optopt = argv[my_optind][charind];
80 for(s=opts+off; *s; s++) if(my_optopt == *s) {
82 if((*(++s) == ':') || ((my_optopt == 'W') && (*s == ';'))) {
83 if(argv[my_optind][charind]) {
84 my_optarg = &(argv[my_optind++][charind]);
86 } else if(*(++s) != ':') {
88 if(++my_optind >= argc) {
89 if(my_opterr) fprintf(stderr,
90 "%s: option requires an argument -- %c\n",
92 opt = (colon_mode == ':') ? ':' : '?';
95 my_optarg = argv[my_optind++];
101 if(my_opterr) fprintf(stderr,
102 "%s: illegal option -- %c\n",
105 if(argv[my_optind][++charind] == '\0') {
110 if(charind && ! argv[my_optind][charind]) {
114 } else if((my_optind >= argc) ||
115 ((argv[my_optind][0] == '-') &&
116 (argv[my_optind][1] == '-') &&
117 (argv[my_optind][2] == '\0'))) {
120 } else if((argv[my_optind][0] != '-') ||
121 (argv[my_optind][1] == '\0')) {
125 if(mode == '+') opt = -1;
126 else if(mode == '-') {
127 my_optarg = argv[my_optind++];
131 for(i=j=my_optind; i<argc; i++) if((argv[i][0] == '-') &&
132 (argv[i][1] != '\0')) {
134 opt=my_getopt(argc, argv, opts);
137 for(k=i; k+1<my_optind; k++) argv[k]=argv[k+1];
138 argv[--my_optind]=tmp;
142 if(i == argc) opt = -1;
146 opt = my_getopt(argc, argv, opts);
148 if (my_optind > argc) my_optind = argc;
152 /* this is the extended getopt_long{,_only}, with some GNU-like
153 * extensions. Implements _getopt_internal in case any programs
154 * expecting GNU libc getopt call it.
157 int _my_getopt_internal(int argc, char * argv[], const char *shortopts,
158 const struct option *longopts, int *longind,
161 char mode, colon_mode = *shortopts;
162 int shortoff = 0, opt = -1;
164 if(getenv("POSIXLY_CORRECT")) colon_mode = mode = '+';
166 if((colon_mode = *shortopts) == ':') shortoff ++;
167 if(((mode = shortopts[shortoff]) == '+') || (mode == '-')) {
169 if((colon_mode != ':') && ((colon_mode = shortopts[shortoff]) == ':'))
174 if((my_optind >= argc) ||
175 ((argv[my_optind][0] == '-') &&
176 (argv[my_optind][1] == '-') &&
177 (argv[my_optind][2] == '\0'))) {
180 } else if((argv[my_optind][0] != '-') ||
181 (argv[my_optind][1] == '\0')) {
186 if(mode == '+') return -1;
187 else if(mode == '-') {
188 my_optarg = argv[my_optind++];
191 for(i=j=my_optind; i<argc; i++) if((argv[i][0] == '-') &&
192 (argv[i][1] != '\0')) {
194 opt=_my_getopt_internal(argc, argv, shortopts,
199 for(k=i; k+1<my_optind; k++)
201 argv[--my_optind]=tmp;
205 } else if((!long_only) && (argv[my_optind][1] != '-'))
206 opt = my_getopt(argc, argv, shortopts);
209 int found = 0, ind, hits = 0;
211 if(((my_optopt = argv[my_optind][1]) != '-') && ! argv[my_optind][2]) {
215 while((c = shortopts[ind++])) {
216 if(((shortopts[ind] == ':') ||
217 ((c == 'W') && (shortopts[ind] == ';'))) &&
218 (shortopts[++ind] == ':'))
220 if(my_optopt == c) return my_getopt(argc, argv, shortopts);
223 offset = 2 - (argv[my_optind][1] != '-');
224 for(charind = offset;
225 (argv[my_optind][charind] != '\0') &&
226 (argv[my_optind][charind] != '=');
228 for(ind = 0; longopts[ind].name && !hits; ind++)
229 if((strlen(longopts[ind].name) == (size_t) (charind - offset)) &&
230 (strncmp(longopts[ind].name,
231 argv[my_optind] + offset, charind - offset) == 0))
233 if(!hits) for(ind = 0; longopts[ind].name; ind++)
234 if(strncmp(longopts[ind].name,
235 argv[my_optind] + offset, charind - offset) == 0)
240 if(argv[my_optind][charind] == '=') {
241 if(longopts[found].has_arg == 0) {
243 if(my_opterr) fprintf(stderr,
244 "%s: option `--%s' doesn't allow an argument\n",
245 argv[0], longopts[found].name);
247 my_optarg = argv[my_optind] + ++charind;
250 } else if(longopts[found].has_arg == 1) {
251 if(++my_optind >= argc) {
252 opt = (colon_mode == ':') ? ':' : '?';
253 if(my_opterr) fprintf(stderr,
254 "%s: option `--%s' requires an argument\n",
255 argv[0], longopts[found].name);
256 } else my_optarg = argv[my_optind];
259 if (longind) *longind = found;
260 if(!longopts[found].flag) opt = longopts[found].val;
261 else *(longopts[found].flag) = longopts[found].val;
265 if(offset == 1) opt = my_getopt(argc, argv, shortopts);
268 if(my_opterr) fprintf(stderr,
269 "%s: unrecognized option `%s'\n",
270 argv[0], argv[my_optind++]);
274 if(my_opterr) fprintf(stderr,
275 "%s: option `%s' is ambiguous\n",
276 argv[0], argv[my_optind++]);
279 if (my_optind > argc) my_optind = argc;
283 int my_getopt_long(int argc, char * argv[], const char *shortopts,
284 const struct option *longopts, int *longind)
286 return _my_getopt_internal(argc, argv, shortopts, longopts, longind, 0);
289 int my_getopt_long_only(int argc, char * argv[], const char *shortopts,
290 const struct option *longopts, int *longind)
292 return _my_getopt_internal(argc, argv, shortopts, longopts, longind, 1);