11590Srgrimes/*- 21590Srgrimes * Copyright (c) 1991 Keith Muller. 31590Srgrimes * Copyright (c) 1993 41590Srgrimes * The Regents of the University of California. All rights reserved. 51590Srgrimes * 61590Srgrimes * This code is derived from software contributed to Berkeley by 71590Srgrimes * Keith Muller of the University of California, San Diego. 81590Srgrimes * 91590Srgrimes * Redistribution and use in source and binary forms, with or without 101590Srgrimes * modification, are permitted provided that the following conditions 111590Srgrimes * are met: 121590Srgrimes * 1. Redistributions of source code must retain the above copyright 131590Srgrimes * notice, this list of conditions and the following disclaimer. 141590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 151590Srgrimes * notice, this list of conditions and the following disclaimer in the 161590Srgrimes * documentation and/or other materials provided with the distribution. 171590Srgrimes * 3. All advertising materials mentioning features or use of this software 181590Srgrimes * must display the following acknowledgement: 191590Srgrimes * This product includes software developed by the University of 201590Srgrimes * California, Berkeley and its contributors. 211590Srgrimes * 4. Neither the name of the University nor the names of its contributors 221590Srgrimes * may be used to endorse or promote products derived from this software 231590Srgrimes * without specific prior written permission. 241590Srgrimes * 251590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 261590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 271590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 281590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 291590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 301590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 311590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 321590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 331590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 341590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 351590Srgrimes * SUCH DAMAGE. 361590Srgrimes */ 371590Srgrimes 3898552Smarkm#if 0 391590Srgrimes#ifndef lint 401590Srgrimesstatic char sccsid[] = "@(#)egetopt.c 8.1 (Berkeley) 6/6/93"; 411590Srgrimes#endif /* not lint */ 4298552Smarkm#endif 431590Srgrimes 4498552Smarkm#include <sys/cdefs.h> 4598552Smarkm__FBSDID("$FreeBSD$"); 4698552Smarkm 471590Srgrimes#include <ctype.h> 481590Srgrimes#include <stdio.h> 491590Srgrimes#include <string.h> 501590Srgrimes 51204359Sed#include "extern.h" 52204359Sed 531590Srgrimes/* 541590Srgrimes * egetopt: get option letter from argument vector (an extended 551590Srgrimes * version of getopt). 561590Srgrimes * 571590Srgrimes * Non standard additions to the ostr specs are: 581590Srgrimes * 1) '?': immediate value following arg is optional (no white space 591590Srgrimes * between the arg and the value) 601590Srgrimes * 2) '#': +/- followed by a number (with an optional sign but 611590Srgrimes * no white space between the arg and the number). The - may be 621590Srgrimes * combined with other options, but the + cannot. 631590Srgrimes */ 641590Srgrimes 651590Srgrimesint eopterr = 1; /* if error message should be printed */ 661590Srgrimesint eoptind = 1; /* index into parent argv vector */ 671590Srgrimesint eoptopt; /* character checked for validity */ 681590Srgrimeschar *eoptarg; /* argument associated with option */ 691590Srgrimes 701590Srgrimes#define BADCH (int)'?' 711590Srgrimes 7298552Smarkmstatic char emsg[] = ""; 7398552Smarkm 741590Srgrimesint 7598552Smarkmegetopt(int nargc, char * const *nargv, const char *ostr) 761590Srgrimes{ 7798552Smarkm static char *place = emsg; /* option letter processing */ 7898552Smarkm char *oli; /* option letter list index */ 79289677Seadler static int delim; /* which option delimiter */ 8098552Smarkm char *p; 811590Srgrimes static char savec = '\0'; 821590Srgrimes 831590Srgrimes if (savec != '\0') { 841590Srgrimes *place = savec; 851590Srgrimes savec = '\0'; 861590Srgrimes } 871590Srgrimes 881590Srgrimes if (!*place) { 891590Srgrimes /* 901590Srgrimes * update scanning pointer 911590Srgrimes */ 921590Srgrimes if ((eoptind >= nargc) || 931590Srgrimes ((*(place = nargv[eoptind]) != '-') && (*place != '+'))) { 9498552Smarkm place = emsg; 9598698Scharnier return (-1); 961590Srgrimes } 971590Srgrimes 981590Srgrimes delim = (int)*place; 991590Srgrimes if (place[1] && *++place == '-' && !place[1]) { 1001590Srgrimes /* 1011590Srgrimes * found "--" 1021590Srgrimes */ 1031590Srgrimes ++eoptind; 10498552Smarkm place = emsg; 10598698Scharnier return (-1); 1061590Srgrimes } 1071590Srgrimes } 1081590Srgrimes 1091590Srgrimes /* 1101590Srgrimes * check option letter 1111590Srgrimes */ 1121590Srgrimes if ((eoptopt = (int)*place++) == (int)':' || (eoptopt == (int)'?') || 1131590Srgrimes !(oli = strchr(ostr, eoptopt))) { 1141590Srgrimes /* 1151590Srgrimes * if the user didn't specify '-' as an option, 11698698Scharnier * assume it means -1 when by itself. 1171590Srgrimes */ 1181590Srgrimes if ((eoptopt == (int)'-') && !*place) 11998698Scharnier return (-1); 1201590Srgrimes if (strchr(ostr, '#') && (isdigit(eoptopt) || 1211590Srgrimes (((eoptopt == (int)'-') || (eoptopt == (int)'+')) && 1221590Srgrimes isdigit(*place)))) { 1231590Srgrimes /* 1241590Srgrimes * # option: +/- with a number is ok 1251590Srgrimes */ 1261590Srgrimes for (p = place; *p != '\0'; ++p) { 1271590Srgrimes if (!isdigit(*p)) 1281590Srgrimes break; 1291590Srgrimes } 1301590Srgrimes eoptarg = place-1; 1311590Srgrimes 1321590Srgrimes if (*p == '\0') { 13398552Smarkm place = emsg; 1341590Srgrimes ++eoptind; 1351590Srgrimes } else { 1361590Srgrimes place = p; 1371590Srgrimes savec = *p; 1381590Srgrimes *place = '\0'; 1391590Srgrimes } 1401590Srgrimes return (delim); 1411590Srgrimes } 1421590Srgrimes 1431590Srgrimes if (!*place) 1441590Srgrimes ++eoptind; 1451590Srgrimes if (eopterr) { 1461590Srgrimes if (!(p = strrchr(*nargv, '/'))) 1471590Srgrimes p = *nargv; 1481590Srgrimes else 1491590Srgrimes ++p; 1501590Srgrimes (void)fprintf(stderr, "%s: illegal option -- %c\n", 1511590Srgrimes p, eoptopt); 1521590Srgrimes } 1531590Srgrimes return (BADCH); 1541590Srgrimes } 1551590Srgrimes if (delim == (int)'+') { 1561590Srgrimes /* 1571590Srgrimes * '+' is only allowed with numbers 1581590Srgrimes */ 1591590Srgrimes if (!*place) 1601590Srgrimes ++eoptind; 1611590Srgrimes if (eopterr) { 1621590Srgrimes if (!(p = strrchr(*nargv, '/'))) 1631590Srgrimes p = *nargv; 1641590Srgrimes else 1651590Srgrimes ++p; 1661590Srgrimes (void)fprintf(stderr, 1671590Srgrimes "%s: illegal '+' delimiter with option -- %c\n", 1681590Srgrimes p, eoptopt); 1691590Srgrimes } 1701590Srgrimes return (BADCH); 1711590Srgrimes } 1721590Srgrimes ++oli; 1731590Srgrimes if ((*oli != ':') && (*oli != '?')) { 1741590Srgrimes /* 1751590Srgrimes * don't need argument 1761590Srgrimes */ 1771590Srgrimes eoptarg = NULL; 1781590Srgrimes if (!*place) 1791590Srgrimes ++eoptind; 1801590Srgrimes return (eoptopt); 1811590Srgrimes } 1821590Srgrimes 1831590Srgrimes if (*place) { 1841590Srgrimes /* 1851590Srgrimes * no white space 1861590Srgrimes */ 1871590Srgrimes eoptarg = place; 1881590Srgrimes } else if (*oli == '?') { 1891590Srgrimes /* 1901590Srgrimes * no arg, but NOT required 1911590Srgrimes */ 1921590Srgrimes eoptarg = NULL; 1931590Srgrimes } else if (nargc <= ++eoptind) { 1941590Srgrimes /* 1951590Srgrimes * no arg, but IS required 1961590Srgrimes */ 19798552Smarkm place = emsg; 1981590Srgrimes if (eopterr) { 1991590Srgrimes if (!(p = strrchr(*nargv, '/'))) 2001590Srgrimes p = *nargv; 2011590Srgrimes else 2021590Srgrimes ++p; 2031590Srgrimes (void)fprintf(stderr, 2041590Srgrimes "%s: option requires an argument -- %c\n", p, 2051590Srgrimes eoptopt); 2061590Srgrimes } 2071590Srgrimes return (BADCH); 2081590Srgrimes } else { 2091590Srgrimes /* 2101590Srgrimes * arg has white space 2111590Srgrimes */ 2121590Srgrimes eoptarg = nargv[eoptind]; 2131590Srgrimes } 21498552Smarkm place = emsg; 2151590Srgrimes ++eoptind; 2161590Srgrimes return (eoptopt); 2171590Srgrimes} 218