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 39from: 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 64int eopterr = 1; /* if error message should be printed */ 65int eoptind = 1; /* index into parent argv vector */ 66int eoptopt; /* character checked for validity */ 67char *eoptarg; /* argument associated with option */ 68 69#define BADCH (int)'?' 70static char EMSG[1] = { '\0' }; 71 72int 73egetopt(int nargc, char * const *nargv, const char *ostr) 74{ 75 static char *place = EMSG; /* option letter processing */ 76 char *oli; /* option letter list index */ 77 static int delim; /* which option delimiter */ 78 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 (-1); 94 } 95 96 delim = (int)*place; 97 if (place[1] && *++place == '-' && !place[1]) { 98 /* 99 * found "--" 100 */ 101 ++eoptind; 102 place = EMSG; 103 return (-1); 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 -1 when by itself. 115 */ 116 if ((eoptopt == (int)'-') && !*place) 117 return (-1); 118 if (strchr(ostr, '#') && (isdigit(eoptopt) || 119 (((eoptopt == (int)'-') || (eoptopt == (int)'+')) && 120 isdigit((unsigned char)*place)))) { 121 /* 122 * # option: +/- with a number is ok 123 */ 124 for (p = place; *p != '\0'; ++p) { 125 if (!isdigit((unsigned char)*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