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