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 * %sccs.include.redist.c%
10 */
11
12 #ifndef lint
13 static char sccsid[] = "@(#)egetopt.c 8.1 (Berkeley) 06/06/93";
14 #endif /* not lint */
15
16 #include <ctype.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20
21 #include "extern.h"
22
23 /*
24 * egetopt: get option letter from argument vector (an extended
25 * version of getopt).
26 *
27 * Non standard additions to the ostr specs are:
28 * 1) '?': immediate value following arg is optional (no white space
29 * between the arg and the value)
30 * 2) '#': +/- followed by a number (with an optional sign but
31 * no white space between the arg and the number). The - may be
32 * combined with other options, but the + cannot.
33 */
34
35 int eopterr = 1; /* if error message should be printed */
36 int eoptind = 1; /* index into parent argv vector */
37 int eoptopt; /* character checked for validity */
38 char *eoptarg; /* argument associated with option */
39
40 #define BADCH (int)'?'
41 #define EMSG ""
42
43 int
egetopt(nargc,nargv,ostr)44 egetopt(nargc, nargv, ostr)
45 int nargc;
46 char * const *nargv;
47 const char *ostr;
48 {
49 static char *place = EMSG; /* option letter processing */
50 register char *oli; /* option letter list index */
51 static int delim; /* which option delimeter */
52 register char *p;
53 static char savec = '\0';
54
55 if (savec != '\0') {
56 *place = savec;
57 savec = '\0';
58 }
59
60 if (!*place) {
61 /*
62 * update scanning pointer
63 */
64 if ((eoptind >= nargc) ||
65 ((*(place = nargv[eoptind]) != '-') && (*place != '+'))) {
66 place = EMSG;
67 return (EOF);
68 }
69
70 delim = (int)*place;
71 if (place[1] && *++place == '-' && !place[1]) {
72 /*
73 * found "--"
74 */
75 ++eoptind;
76 place = EMSG;
77 return (EOF);
78 }
79 }
80
81 /*
82 * check option letter
83 */
84 if ((eoptopt = (int)*place++) == (int)':' || (eoptopt == (int)'?') ||
85 !(oli = strchr(ostr, eoptopt))) {
86 /*
87 * if the user didn't specify '-' as an option,
88 * assume it means EOF when by itself.
89 */
90 if ((eoptopt == (int)'-') && !*place)
91 return (EOF);
92 if (strchr(ostr, '#') && (isdigit(eoptopt) ||
93 (((eoptopt == (int)'-') || (eoptopt == (int)'+')) &&
94 isdigit(*place)))) {
95 /*
96 * # option: +/- with a number is ok
97 */
98 for (p = place; *p != '\0'; ++p) {
99 if (!isdigit(*p))
100 break;
101 }
102 eoptarg = place-1;
103
104 if (*p == '\0') {
105 place = EMSG;
106 ++eoptind;
107 } else {
108 place = p;
109 savec = *p;
110 *place = '\0';
111 }
112 return (delim);
113 }
114
115 if (!*place)
116 ++eoptind;
117 if (eopterr) {
118 if (!(p = strrchr(*nargv, '/')))
119 p = *nargv;
120 else
121 ++p;
122 (void)fprintf(stderr, "%s: illegal option -- %c\n",
123 p, eoptopt);
124 }
125 return (BADCH);
126 }
127 if (delim == (int)'+') {
128 /*
129 * '+' is only allowed with numbers
130 */
131 if (!*place)
132 ++eoptind;
133 if (eopterr) {
134 if (!(p = strrchr(*nargv, '/')))
135 p = *nargv;
136 else
137 ++p;
138 (void)fprintf(stderr,
139 "%s: illegal '+' delimiter with option -- %c\n",
140 p, eoptopt);
141 }
142 return (BADCH);
143 }
144 ++oli;
145 if ((*oli != ':') && (*oli != '?')) {
146 /*
147 * don't need argument
148 */
149 eoptarg = NULL;
150 if (!*place)
151 ++eoptind;
152 return (eoptopt);
153 }
154
155 if (*place) {
156 /*
157 * no white space
158 */
159 eoptarg = place;
160 } else if (*oli == '?') {
161 /*
162 * no arg, but NOT required
163 */
164 eoptarg = NULL;
165 } else if (nargc <= ++eoptind) {
166 /*
167 * no arg, but IS required
168 */
169 place = EMSG;
170 if (eopterr) {
171 if (!(p = strrchr(*nargv, '/')))
172 p = *nargv;
173 else
174 ++p;
175 (void)fprintf(stderr,
176 "%s: option requires an argument -- %c\n", p,
177 eoptopt);
178 }
179 return (BADCH);
180 } else {
181 /*
182 * arg has white space
183 */
184 eoptarg = nargv[eoptind];
185 }
186 place = EMSG;
187 ++eoptind;
188 return (eoptopt);
189 }
190