xref: /csrg-svn/usr.bin/pr/egetopt.c (revision 62178)
159583Smuller /*-
259599Sbostic  * Copyright (c) 1991 Keith Muller.
3*62178Sbostic  * Copyright (c) 1993
4*62178Sbostic  *	The Regents of the University of California.  All rights reserved.
559583Smuller  *
659599Sbostic  * This code is derived from software contributed to Berkeley by
759599Sbostic  * Keith Muller of the University of California, San Diego.
859599Sbostic  *
959583Smuller  * %sccs.include.redist.c%
1059583Smuller  */
1159583Smuller 
1259583Smuller #ifndef lint
13*62178Sbostic static char sccsid[] = "@(#)egetopt.c	8.1 (Berkeley) 06/06/93";
1459583Smuller #endif /* not lint */
1559583Smuller 
1659599Sbostic #include <ctype.h>
1759583Smuller #include <stdio.h>
1859583Smuller #include <stdlib.h>
1959583Smuller #include <string.h>
2059599Sbostic 
2159583Smuller #include "extern.h"
2259583Smuller 
2359583Smuller /*
2459583Smuller  * egetopt:	get option letter from argument vector (an extended
2559583Smuller  *		version of getopt).
2659583Smuller  *
2759583Smuller  * Non standard additions to the ostr specs are:
2859583Smuller  * 1) '?': immediate value following arg is optional (no white space
2959583Smuller  *    between the arg and the value)
3059583Smuller  * 2) '#': +/- followed by a number (with an optional sign but
3159583Smuller  *    no white space between the arg and the number). The - may be
3259583Smuller  *    combined with other options, but the + cannot.
3359583Smuller  */
3459583Smuller 
3559583Smuller int	eopterr = 1;		/* if error message should be printed */
3659583Smuller int	eoptind = 1;		/* index into parent argv vector */
3759583Smuller int	eoptopt;		/* character checked for validity */
3859583Smuller char	*eoptarg;		/* argument associated with option */
3959583Smuller 
4059583Smuller #define	BADCH	(int)'?'
4159583Smuller #define	EMSG	""
4259583Smuller 
4359583Smuller int
egetopt(nargc,nargv,ostr)4459583Smuller egetopt(nargc, nargv, ostr)
4559583Smuller 	int nargc;
4659599Sbostic 	char * const *nargv;
4759599Sbostic 	const char *ostr;
4859583Smuller {
4959583Smuller 	static char *place = EMSG;	/* option letter processing */
5059583Smuller 	register char *oli;		/* option letter list index */
5159583Smuller 	static int delim;		/* which option delimeter */
5259583Smuller 	register char *p;
5359583Smuller 	static char savec = '\0';
5459583Smuller 
5559583Smuller 	if (savec != '\0') {
5659583Smuller 		*place = savec;
5759583Smuller 		savec = '\0';
5859583Smuller 	}
5959583Smuller 
6059583Smuller 	if (!*place) {
6159583Smuller 		/*
6259583Smuller 		 * update scanning pointer
6359583Smuller 		 */
6459583Smuller 		if ((eoptind >= nargc) ||
6559583Smuller 		    ((*(place = nargv[eoptind]) != '-') && (*place != '+'))) {
6659583Smuller 			place = EMSG;
6759599Sbostic 			return (EOF);
6859583Smuller 		}
6959583Smuller 
7059583Smuller 		delim = (int)*place;
7159583Smuller 		if (place[1] && *++place == '-' && !place[1]) {
7259583Smuller 			/*
7359583Smuller 			 * found "--"
7459583Smuller 			 */
7559583Smuller 			++eoptind;
7659583Smuller 			place = EMSG;
7759599Sbostic 			return (EOF);
7859583Smuller 		}
7959583Smuller 	}
8059583Smuller 
8159583Smuller 	/*
8259583Smuller 	 * check option letter
8359583Smuller 	 */
8459583Smuller 	if ((eoptopt = (int)*place++) == (int)':' || (eoptopt == (int)'?') ||
8559599Sbostic 	    !(oli = strchr(ostr, eoptopt))) {
8659583Smuller 		/*
8759583Smuller 		 * if the user didn't specify '-' as an option,
8859583Smuller 		 * assume it means EOF when by itself.
8959583Smuller 		 */
9059583Smuller 		if ((eoptopt == (int)'-') && !*place)
9159599Sbostic 			return (EOF);
9259599Sbostic 		if (strchr(ostr, '#') && (isdigit(eoptopt) ||
9359583Smuller 		    (((eoptopt == (int)'-') || (eoptopt == (int)'+')) &&
9459583Smuller 		      isdigit(*place)))) {
9559583Smuller 			/*
9659583Smuller 			 * # option: +/- with a number is ok
9759583Smuller 			 */
9859583Smuller 			for (p = place; *p != '\0'; ++p) {
9959583Smuller 				if (!isdigit(*p))
10059583Smuller 					break;
10159583Smuller 			}
10259583Smuller 			eoptarg = place-1;
10359583Smuller 
10459583Smuller 			if (*p == '\0') {
10559583Smuller 				place = EMSG;
10659583Smuller 				++eoptind;
10759583Smuller 			} else {
10859583Smuller 				place = p;
10959583Smuller 				savec = *p;
11059583Smuller 				*place = '\0';
11159583Smuller 			}
11259599Sbostic 			return (delim);
11359583Smuller 		}
11459583Smuller 
11559583Smuller 		if (!*place)
11659583Smuller 			++eoptind;
11759583Smuller 		if (eopterr) {
11859599Sbostic 			if (!(p = strrchr(*nargv, '/')))
11959583Smuller 				p = *nargv;
12059583Smuller 			else
12159583Smuller 				++p;
12259583Smuller 			(void)fprintf(stderr, "%s: illegal option -- %c\n",
12359583Smuller 			    p, eoptopt);
12459583Smuller 		}
12559599Sbostic 		return (BADCH);
12659583Smuller 	}
12759583Smuller 	if (delim == (int)'+') {
12859583Smuller 		/*
12959583Smuller 		 * '+' is only allowed with numbers
13059583Smuller 		 */
13159583Smuller 		if (!*place)
13259583Smuller 			++eoptind;
13359583Smuller 		if (eopterr) {
13459599Sbostic 			if (!(p = strrchr(*nargv, '/')))
13559583Smuller 				p = *nargv;
13659583Smuller 			else
13759583Smuller 				++p;
13859583Smuller 			(void)fprintf(stderr,
13959583Smuller 				"%s: illegal '+' delimiter with option -- %c\n",
14059583Smuller 				p, eoptopt);
14159583Smuller 		}
14259599Sbostic 		return (BADCH);
14359583Smuller 	}
14459583Smuller 	++oli;
14559583Smuller 	if ((*oli != ':') && (*oli != '?')) {
14659583Smuller 		/*
14759583Smuller 		 * don't need argument
14859583Smuller 		 */
14959583Smuller 		eoptarg = NULL;
15059583Smuller 		if (!*place)
15159583Smuller 			++eoptind;
15259599Sbostic 		return (eoptopt);
15359583Smuller 	}
15459583Smuller 
15559583Smuller 	if (*place) {
15659583Smuller 		/*
15759583Smuller 		 * no white space
15859583Smuller 		 */
15959583Smuller 		eoptarg = place;
16059583Smuller 	} else if (*oli == '?') {
16159583Smuller 		/*
16259583Smuller 		 * no arg, but NOT required
16359583Smuller 		 */
16459583Smuller 		eoptarg = NULL;
16559583Smuller 	} else if (nargc <= ++eoptind) {
16659583Smuller 		/*
16759583Smuller 		 * no arg, but IS required
16859583Smuller 		 */
16959583Smuller 		place = EMSG;
17059583Smuller 		if (eopterr) {
17159599Sbostic 			if (!(p = strrchr(*nargv, '/')))
17259583Smuller 				p = *nargv;
17359583Smuller 			else
17459583Smuller 				++p;
17559583Smuller 			(void)fprintf(stderr,
17659583Smuller 			    "%s: option requires an argument -- %c\n", p,
17759583Smuller 			    eoptopt);
17859583Smuller 		}
17959599Sbostic 		return (BADCH);
18059583Smuller 	} else {
18159583Smuller 		/*
18259583Smuller 		 * arg has white space
18359583Smuller 		 */
18459583Smuller 		eoptarg = nargv[eoptind];
18559583Smuller 	}
18659583Smuller 	place = EMSG;
18759583Smuller 	++eoptind;
18859599Sbostic 	return (eoptopt);
18959583Smuller }
190