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