egetopt.c revision 1.1 1 /*-
2 * Copyright (c) 1991 Keith Muller.
3 * Copyright (c) 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Keith Muller of the University of California, San Diego.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the University of
20 * California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 */
37
38 #ifndef lint
39 /* from: static char sccsid[] = "@(#)egetopt.c 8.1 (Berkeley) 6/6/93"; */
40 static char *rcsid = "$Id: egetopt.c,v 1.1 1994/01/06 15:57:18 cgd Exp $";
41 #endif /* not lint */
42
43 #include <ctype.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47
48 #include "extern.h"
49
50 /*
51 * egetopt: get option letter from argument vector (an extended
52 * version of getopt).
53 *
54 * Non standard additions to the ostr specs are:
55 * 1) '?': immediate value following arg is optional (no white space
56 * between the arg and the value)
57 * 2) '#': +/- followed by a number (with an optional sign but
58 * no white space between the arg and the number). The - may be
59 * combined with other options, but the + cannot.
60 */
61
62 int eopterr = 1; /* if error message should be printed */
63 int eoptind = 1; /* index into parent argv vector */
64 int eoptopt; /* character checked for validity */
65 char *eoptarg; /* argument associated with option */
66
67 #define BADCH (int)'?'
68 #define EMSG ""
69
70 int
71 egetopt(nargc, nargv, ostr)
72 int nargc;
73 char * const *nargv;
74 const char *ostr;
75 {
76 static char *place = EMSG; /* option letter processing */
77 register char *oli; /* option letter list index */
78 static int delim; /* which option delimeter */
79 register char *p;
80 static char savec = '\0';
81
82 if (savec != '\0') {
83 *place = savec;
84 savec = '\0';
85 }
86
87 if (!*place) {
88 /*
89 * update scanning pointer
90 */
91 if ((eoptind >= nargc) ||
92 ((*(place = nargv[eoptind]) != '-') && (*place != '+'))) {
93 place = EMSG;
94 return (EOF);
95 }
96
97 delim = (int)*place;
98 if (place[1] && *++place == '-' && !place[1]) {
99 /*
100 * found "--"
101 */
102 ++eoptind;
103 place = EMSG;
104 return (EOF);
105 }
106 }
107
108 /*
109 * check option letter
110 */
111 if ((eoptopt = (int)*place++) == (int)':' || (eoptopt == (int)'?') ||
112 !(oli = strchr(ostr, eoptopt))) {
113 /*
114 * if the user didn't specify '-' as an option,
115 * assume it means EOF when by itself.
116 */
117 if ((eoptopt == (int)'-') && !*place)
118 return (EOF);
119 if (strchr(ostr, '#') && (isdigit(eoptopt) ||
120 (((eoptopt == (int)'-') || (eoptopt == (int)'+')) &&
121 isdigit(*place)))) {
122 /*
123 * # option: +/- with a number is ok
124 */
125 for (p = place; *p != '\0'; ++p) {
126 if (!isdigit(*p))
127 break;
128 }
129 eoptarg = place-1;
130
131 if (*p == '\0') {
132 place = EMSG;
133 ++eoptind;
134 } else {
135 place = p;
136 savec = *p;
137 *place = '\0';
138 }
139 return (delim);
140 }
141
142 if (!*place)
143 ++eoptind;
144 if (eopterr) {
145 if (!(p = strrchr(*nargv, '/')))
146 p = *nargv;
147 else
148 ++p;
149 (void)fprintf(stderr, "%s: illegal option -- %c\n",
150 p, eoptopt);
151 }
152 return (BADCH);
153 }
154 if (delim == (int)'+') {
155 /*
156 * '+' is only allowed with numbers
157 */
158 if (!*place)
159 ++eoptind;
160 if (eopterr) {
161 if (!(p = strrchr(*nargv, '/')))
162 p = *nargv;
163 else
164 ++p;
165 (void)fprintf(stderr,
166 "%s: illegal '+' delimiter with option -- %c\n",
167 p, eoptopt);
168 }
169 return (BADCH);
170 }
171 ++oli;
172 if ((*oli != ':') && (*oli != '?')) {
173 /*
174 * don't need argument
175 */
176 eoptarg = NULL;
177 if (!*place)
178 ++eoptind;
179 return (eoptopt);
180 }
181
182 if (*place) {
183 /*
184 * no white space
185 */
186 eoptarg = place;
187 } else if (*oli == '?') {
188 /*
189 * no arg, but NOT required
190 */
191 eoptarg = NULL;
192 } else if (nargc <= ++eoptind) {
193 /*
194 * no arg, but IS required
195 */
196 place = EMSG;
197 if (eopterr) {
198 if (!(p = strrchr(*nargv, '/')))
199 p = *nargv;
200 else
201 ++p;
202 (void)fprintf(stderr,
203 "%s: option requires an argument -- %c\n", p,
204 eoptopt);
205 }
206 return (BADCH);
207 } else {
208 /*
209 * arg has white space
210 */
211 eoptarg = nargv[eoptind];
212 }
213 place = EMSG;
214 ++eoptind;
215 return (eoptopt);
216 }
217