show PC of labels
[xorcyst.git] / RCS / my_getopt.c,v
blob5af8e0332c6965c61ef833868c891bac9b988943
1 head    1.1;
2 access;
3 symbols;
4 locks; strict;
5 comment @ * @;
8 1.1
9 date    2004.12.06.04.53.28;    author kenth;   state Exp;
10 branches;
11 next    ;
14 desc
18 1.1
19 log
20 @Initial revision
22 text
23 @/*
24  *  my_getopt.c - my re-implementation of getopt.
25  *  Copyright 1997, 2000, 2001, 2002, Benjamin Sittler
26  *
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:
34  *  
35  *  The above copyright notice and this permission notice shall be
36  *  included in all copies or substantial portions of the Software.
37  *  
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.
46  */
48 #include <sys/types.h>
49 #include <stdlib.h>
50 #include <stdio.h>
51 #include <string.h>
52 #include "my_getopt.h"
54 int my_optind=1, my_opterr=1, my_optopt=0;
55 char *my_optarg=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)
63   static int charind=0;
64   const char *s;
65   char mode, colon_mode;
66   int off = 0, opt = -1;
68   if(getenv("POSIXLY_CORRECT")) colon_mode = mode = '+';
69   else {
70     if((colon_mode = *opts) == ':') off ++;
71     if(((mode = opts[off]) == '+') || (mode == '-')) {
72       off++;
73       if((colon_mode != ':') && ((colon_mode = opts[off]) == ':'))
74         off ++;
75     }
76   }
77   my_optarg = 0;
78   if(charind) {
79     my_optopt = argv[my_optind][charind];
80     for(s=opts+off; *s; s++) if(my_optopt == *s) {
81       charind++;
82       if((*(++s) == ':') || ((my_optopt == 'W') && (*s == ';'))) {
83         if(argv[my_optind][charind]) {
84           my_optarg = &(argv[my_optind++][charind]);
85           charind = 0;
86         } else if(*(++s) != ':') {
87           charind = 0;
88           if(++my_optind >= argc) {
89             if(my_opterr) fprintf(stderr,
90                                 "%s: option requires an argument -- %c\n",
91                                 argv[0], my_optopt);
92             opt = (colon_mode == ':') ? ':' : '?';
93             goto my_getopt_ok;
94           }
95           my_optarg = argv[my_optind++];
96         }
97       }
98       opt = my_optopt;
99       goto my_getopt_ok;
100     }
101     if(my_opterr) fprintf(stderr,
102                         "%s: illegal option -- %c\n",
103                         argv[0], my_optopt);
104     opt = '?';
105     if(argv[my_optind][++charind] == '\0') {
106       my_optind++;
107       charind = 0;
108     }
109   my_getopt_ok:
110     if(charind && ! argv[my_optind][charind]) {
111       my_optind++;
112       charind = 0;
113     }
114   } else if((my_optind >= argc) ||
115              ((argv[my_optind][0] == '-') &&
116               (argv[my_optind][1] == '-') &&
117               (argv[my_optind][2] == '\0'))) {
118     my_optind++;
119     opt = -1;
120   } else if((argv[my_optind][0] != '-') ||
121              (argv[my_optind][1] == '\0')) {
122     char *tmp;
123     int i, j, k;
125     if(mode == '+') opt = -1;
126     else if(mode == '-') {
127       my_optarg = argv[my_optind++];
128       charind = 0;
129       opt = 1;
130     } else {
131       for(i=j=my_optind; i<argc; i++) if((argv[i][0] == '-') &&
132                                         (argv[i][1] != '\0')) {
133         my_optind=i;
134         opt=my_getopt(argc, argv, opts);
135         while(i > j) {
136           tmp=argv[--i];
137           for(k=i; k+1<my_optind; k++) argv[k]=argv[k+1];
138           argv[--my_optind]=tmp;
139         }
140         break;
141       }
142       if(i == argc) opt = -1;
143     }
144   } else {
145     charind++;
146     opt = my_getopt(argc, argv, opts);
147   }
148   if (my_optind > argc) my_optind = argc;
149   return opt;
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.
155  */
157 int _my_getopt_internal(int argc, char * argv[], const char *shortopts,
158                      const struct option *longopts, int *longind,
159                      int long_only)
161   char mode, colon_mode = *shortopts;
162   int shortoff = 0, opt = -1;
164   if(getenv("POSIXLY_CORRECT")) colon_mode = mode = '+';
165   else {
166     if((colon_mode = *shortopts) == ':') shortoff ++;
167     if(((mode = shortopts[shortoff]) == '+') || (mode == '-')) {
168       shortoff++;
169       if((colon_mode != ':') && ((colon_mode = shortopts[shortoff]) == ':'))
170         shortoff ++;
171     }
172   }
173   my_optarg = 0;
174   if((my_optind >= argc) ||
175       ((argv[my_optind][0] == '-') &&
176        (argv[my_optind][1] == '-') &&
177        (argv[my_optind][2] == '\0'))) {
178     my_optind++;
179     opt = -1;
180   } else if((argv[my_optind][0] != '-') ||
181             (argv[my_optind][1] == '\0')) {
182     char *tmp;
183     int i, j, k;
185     opt = -1;
186     if(mode == '+') return -1;
187     else if(mode == '-') {
188       my_optarg = argv[my_optind++];
189       return 1;
190     }
191     for(i=j=my_optind; i<argc; i++) if((argv[i][0] == '-') &&
192                                     (argv[i][1] != '\0')) {
193       my_optind=i;
194       opt=_my_getopt_internal(argc, argv, shortopts,
195                               longopts, longind,
196                               long_only);
197       while(i > j) {
198         tmp=argv[--i];
199         for(k=i; k+1<my_optind; k++)
200           argv[k]=argv[k+1];
201         argv[--my_optind]=tmp;
202       }
203       break;
204     }
205   } else if((!long_only) && (argv[my_optind][1] != '-'))
206     opt = my_getopt(argc, argv, shortopts);
207   else {
208     int charind, offset;
209     int found = 0, ind, hits = 0;
211     if(((my_optopt = argv[my_optind][1]) != '-') && ! argv[my_optind][2]) {
212       int c;
213       
214       ind = shortoff;
215       while((c = shortopts[ind++])) {
216         if(((shortopts[ind] == ':') ||
217             ((c == 'W') && (shortopts[ind] == ';'))) &&
218            (shortopts[++ind] == ':'))
219           ind ++;
220         if(my_optopt == c) return my_getopt(argc, argv, shortopts);
221       }
222     }
223     offset = 2 - (argv[my_optind][1] != '-');
224     for(charind = offset;
225         (argv[my_optind][charind] != '\0') &&
226           (argv[my_optind][charind] != '=');
227         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))
232         found = ind, hits++;
233     if(!hits) for(ind = 0; longopts[ind].name; ind++)
234       if(strncmp(longopts[ind].name,
235                  argv[my_optind] + offset, charind - offset) == 0)
236         found = ind, hits++;
237     if(hits == 1) {
238       opt = 0;
240       if(argv[my_optind][charind] == '=') {
241         if(longopts[found].has_arg == 0) {
242           opt = '?';
243           if(my_opterr) fprintf(stderr,
244                              "%s: option `--%s' doesn't allow an argument\n",
245                              argv[0], longopts[found].name);
246         } else {
247           my_optarg = argv[my_optind] + ++charind;
248           charind = 0;
249         }
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];
257       }
258       if(!opt) {
259         if (longind) *longind = found;
260         if(!longopts[found].flag) opt = longopts[found].val;
261         else *(longopts[found].flag) = longopts[found].val;
262       }
263       my_optind++;
264     } else if(!hits) {
265       if(offset == 1) opt = my_getopt(argc, argv, shortopts);
266       else {
267         opt = '?';
268         if(my_opterr) fprintf(stderr,
269                            "%s: unrecognized option `%s'\n",
270                            argv[0], argv[my_optind++]);
271       }
272     } else {
273       opt = '?';
274       if(my_opterr) fprintf(stderr,
275                          "%s: option `%s' is ambiguous\n",
276                          argv[0], argv[my_optind++]);
277     }
278   }
279   if (my_optind > argc) my_optind = argc;
280   return opt;
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);