egetopt.c revision 98552
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: head/usr.bin/pr/egetopt.c 98552 2002-06-21 10:14:57Z markm $"); 4698552Smarkm 471590Srgrimes#include <ctype.h> 481590Srgrimes#include <stdio.h> 491590Srgrimes#include <stdlib.h> 501590Srgrimes#include <string.h> 511590Srgrimes 521590Srgrimes#include "extern.h" 531590Srgrimes 541590Srgrimes/* 551590Srgrimes * egetopt: get option letter from argument vector (an extended 561590Srgrimes * version of getopt). 571590Srgrimes * 581590Srgrimes * Non standard additions to the ostr specs are: 591590Srgrimes * 1) '?': immediate value following arg is optional (no white space 601590Srgrimes * between the arg and the value) 611590Srgrimes * 2) '#': +/- followed by a number (with an optional sign but 621590Srgrimes * no white space between the arg and the number). The - may be 631590Srgrimes * combined with other options, but the + cannot. 641590Srgrimes */ 651590Srgrimes 661590Srgrimesint eopterr = 1; /* if error message should be printed */ 671590Srgrimesint eoptind = 1; /* index into parent argv vector */ 681590Srgrimesint eoptopt; /* character checked for validity */ 691590Srgrimeschar *eoptarg; /* argument associated with option */ 701590Srgrimes 711590Srgrimes#define BADCH (int)'?' 721590Srgrimes 7398552Smarkmstatic char emsg[] = ""; 7498552Smarkm 751590Srgrimesint 7698552Smarkmegetopt(int nargc, char * const *nargv, const char *ostr) 771590Srgrimes{ 7898552Smarkm static char *place = emsg; /* option letter processing */ 7998552Smarkm char *oli; /* option letter list index */ 801590Srgrimes static int delim; /* which option delimeter */ 8198552Smarkm char *p; 821590Srgrimes static char savec = '\0'; 831590Srgrimes 841590Srgrimes if (savec != '\0') { 851590Srgrimes *place = savec; 861590Srgrimes savec = '\0'; 871590Srgrimes } 881590Srgrimes 891590Srgrimes if (!*place) { 901590Srgrimes /* 911590Srgrimes * update scanning pointer 921590Srgrimes */ 931590Srgrimes if ((eoptind >= nargc) || 941590Srgrimes ((*(place = nargv[eoptind]) != '-') && (*place != '+'))) { 9598552Smarkm place = emsg; 961590Srgrimes return (EOF); 971590Srgrimes } 981590Srgrimes 991590Srgrimes delim = (int)*place; 1001590Srgrimes if (place[1] && *++place == '-' && !place[1]) { 1011590Srgrimes /* 1021590Srgrimes * found "--" 1031590Srgrimes */ 1041590Srgrimes ++eoptind; 10598552Smarkm place = emsg; 1061590Srgrimes return (EOF); 1071590Srgrimes } 1081590Srgrimes } 1091590Srgrimes 1101590Srgrimes /* 1111590Srgrimes * check option letter 1121590Srgrimes */ 1131590Srgrimes if ((eoptopt = (int)*place++) == (int)':' || (eoptopt == (int)'?') || 1141590Srgrimes !(oli = strchr(ostr, eoptopt))) { 1151590Srgrimes /* 1161590Srgrimes * if the user didn't specify '-' as an option, 1171590Srgrimes * assume it means EOF when by itself. 1181590Srgrimes */ 1191590Srgrimes if ((eoptopt == (int)'-') && !*place) 1201590Srgrimes return (EOF); 1211590Srgrimes if (strchr(ostr, '#') && (isdigit(eoptopt) || 1221590Srgrimes (((eoptopt == (int)'-') || (eoptopt == (int)'+')) && 1231590Srgrimes isdigit(*place)))) { 1241590Srgrimes /* 1251590Srgrimes * # option: +/- with a number is ok 1261590Srgrimes */ 1271590Srgrimes for (p = place; *p != '\0'; ++p) { 1281590Srgrimes if (!isdigit(*p)) 1291590Srgrimes break; 1301590Srgrimes } 1311590Srgrimes eoptarg = place-1; 1321590Srgrimes 1331590Srgrimes if (*p == '\0') { 13498552Smarkm place = emsg; 1351590Srgrimes ++eoptind; 1361590Srgrimes } else { 1371590Srgrimes place = p; 1381590Srgrimes savec = *p; 1391590Srgrimes *place = '\0'; 1401590Srgrimes } 1411590Srgrimes return (delim); 1421590Srgrimes } 1431590Srgrimes 1441590Srgrimes if (!*place) 1451590Srgrimes ++eoptind; 1461590Srgrimes if (eopterr) { 1471590Srgrimes if (!(p = strrchr(*nargv, '/'))) 1481590Srgrimes p = *nargv; 1491590Srgrimes else 1501590Srgrimes ++p; 1511590Srgrimes (void)fprintf(stderr, "%s: illegal option -- %c\n", 1521590Srgrimes p, eoptopt); 1531590Srgrimes } 1541590Srgrimes return (BADCH); 1551590Srgrimes } 1561590Srgrimes if (delim == (int)'+') { 1571590Srgrimes /* 1581590Srgrimes * '+' is only allowed with numbers 1591590Srgrimes */ 1601590Srgrimes if (!*place) 1611590Srgrimes ++eoptind; 1621590Srgrimes if (eopterr) { 1631590Srgrimes if (!(p = strrchr(*nargv, '/'))) 1641590Srgrimes p = *nargv; 1651590Srgrimes else 1661590Srgrimes ++p; 1671590Srgrimes (void)fprintf(stderr, 1681590Srgrimes "%s: illegal '+' delimiter with option -- %c\n", 1691590Srgrimes p, eoptopt); 1701590Srgrimes } 1711590Srgrimes return (BADCH); 1721590Srgrimes } 1731590Srgrimes ++oli; 1741590Srgrimes if ((*oli != ':') && (*oli != '?')) { 1751590Srgrimes /* 1761590Srgrimes * don't need argument 1771590Srgrimes */ 1781590Srgrimes eoptarg = NULL; 1791590Srgrimes if (!*place) 1801590Srgrimes ++eoptind; 1811590Srgrimes return (eoptopt); 1821590Srgrimes } 1831590Srgrimes 1841590Srgrimes if (*place) { 1851590Srgrimes /* 1861590Srgrimes * no white space 1871590Srgrimes */ 1881590Srgrimes eoptarg = place; 1891590Srgrimes } else if (*oli == '?') { 1901590Srgrimes /* 1911590Srgrimes * no arg, but NOT required 1921590Srgrimes */ 1931590Srgrimes eoptarg = NULL; 1941590Srgrimes } else if (nargc <= ++eoptind) { 1951590Srgrimes /* 1961590Srgrimes * no arg, but IS required 1971590Srgrimes */ 19898552Smarkm place = emsg; 1991590Srgrimes if (eopterr) { 2001590Srgrimes if (!(p = strrchr(*nargv, '/'))) 2011590Srgrimes p = *nargv; 2021590Srgrimes else 2031590Srgrimes ++p; 2041590Srgrimes (void)fprintf(stderr, 2051590Srgrimes "%s: option requires an argument -- %c\n", p, 2061590Srgrimes eoptopt); 2071590Srgrimes } 2081590Srgrimes return (BADCH); 2091590Srgrimes } else { 2101590Srgrimes /* 2111590Srgrimes * arg has white space 2121590Srgrimes */ 2131590Srgrimes eoptarg = nargv[eoptind]; 2141590Srgrimes } 21598552Smarkm place = emsg; 2161590Srgrimes ++eoptind; 2171590Srgrimes return (eoptopt); 2181590Srgrimes} 219