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