xref: /dflybsd-src/contrib/bmake/getopt.c (revision f445c8974931e0ddbeb96b2514f9cb61aee7e659)
1*f445c897SJohn Marino /*	$NetBSD: getopt.c,v 1.29 2014/06/05 22:00:22 christos Exp $	*/
2*f445c897SJohn Marino 
301e196c8SJohn Marino /*
401e196c8SJohn Marino  * Copyright (c) 1987, 1993, 1994
501e196c8SJohn Marino  *	The Regents of the University of California.  All rights reserved.
601e196c8SJohn Marino  *
701e196c8SJohn Marino  * Redistribution and use in source and binary forms, with or without
801e196c8SJohn Marino  * modification, are permitted provided that the following conditions
901e196c8SJohn Marino  * are met:
1001e196c8SJohn Marino  * 1. Redistributions of source code must retain the above copyright
1101e196c8SJohn Marino  *    notice, this list of conditions and the following disclaimer.
1201e196c8SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
1301e196c8SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
1401e196c8SJohn Marino  *    documentation and/or other materials provided with the distribution.
15*f445c897SJohn Marino  * 3. Neither the name of the University nor the names of its contributors
1601e196c8SJohn Marino  *    may be used to endorse or promote products derived from this software
1701e196c8SJohn Marino  *    without specific prior written permission.
1801e196c8SJohn Marino  *
1901e196c8SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2001e196c8SJohn Marino  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2101e196c8SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2201e196c8SJohn Marino  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2301e196c8SJohn Marino  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2401e196c8SJohn Marino  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2501e196c8SJohn Marino  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2601e196c8SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2701e196c8SJohn Marino  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2801e196c8SJohn Marino  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2901e196c8SJohn Marino  * SUCH DAMAGE.
3001e196c8SJohn Marino  */
3101e196c8SJohn Marino 
3201e196c8SJohn Marino #ifdef HAVE_CONFIG_H
3301e196c8SJohn Marino # include "config.h"
3401e196c8SJohn Marino #endif
3501e196c8SJohn Marino #if !defined(HAVE_GETOPT) || defined(WANT_GETOPT_LONG) || defined(BROKEN_GETOPT)
36*f445c897SJohn Marino #include <sys/cdefs.h>
3701e196c8SJohn Marino 
3801e196c8SJohn Marino #include <stdio.h>
3901e196c8SJohn Marino #include <stdlib.h>
4001e196c8SJohn Marino #include <string.h>
4101e196c8SJohn Marino 
4201e196c8SJohn Marino 
4301e196c8SJohn Marino #define	BADCH	(int)'?'
4401e196c8SJohn Marino #define	BADARG	(int)':'
4501e196c8SJohn Marino #define	EMSG	""
4601e196c8SJohn Marino 
4701e196c8SJohn Marino int	opterr = 1,		/* if error message should be printed */
4801e196c8SJohn Marino 	optind = 1,		/* index into parent argv vector */
4901e196c8SJohn Marino 	optopt = BADCH,		/* character checked for validity */
5001e196c8SJohn Marino 	optreset;		/* reset getopt */
5101e196c8SJohn Marino char	*optarg;		/* argument associated with option */
5201e196c8SJohn Marino 
5301e196c8SJohn Marino /*
5401e196c8SJohn Marino  * getopt --
5501e196c8SJohn Marino  *	Parse argc/argv argument vector.
5601e196c8SJohn Marino  */
5701e196c8SJohn Marino int
getopt(int nargc,char * const nargv[],const char * ostr)58*f445c897SJohn Marino getopt(int nargc, char * const nargv[], const char *ostr)
5901e196c8SJohn Marino {
6001e196c8SJohn Marino 	extern char *__progname;
61*f445c897SJohn Marino 	static const char *place = EMSG; 	/* option letter processing */
6201e196c8SJohn Marino 	char *oli;				/* option letter list index */
6301e196c8SJohn Marino 
6401e196c8SJohn Marino #ifndef BSD4_4
6501e196c8SJohn Marino 	if (!__progname) {
6601e196c8SJohn Marino 		if (__progname = strrchr(nargv[0], '/'))
6701e196c8SJohn Marino 			++__progname;
6801e196c8SJohn Marino 		else
6901e196c8SJohn Marino 			__progname = nargv[0];
7001e196c8SJohn Marino 	}
7101e196c8SJohn Marino #endif
7201e196c8SJohn Marino 
73*f445c897SJohn Marino 	if (optreset || *place == 0) {		/* update scanning pointer */
7401e196c8SJohn Marino 		optreset = 0;
75*f445c897SJohn Marino 		place = nargv[optind];
76*f445c897SJohn Marino 		if (optind >= nargc || *place++ != '-') {
77*f445c897SJohn Marino 			/* Argument is absent or is not an option */
7801e196c8SJohn Marino 			place = EMSG;
7901e196c8SJohn Marino 			return (-1);
8001e196c8SJohn Marino 		}
81*f445c897SJohn Marino 		optopt = *place++;
82*f445c897SJohn Marino 		if (optopt == '-' && *place == 0) {
83*f445c897SJohn Marino 			/* "--" => end of options */
8401e196c8SJohn Marino 			++optind;
8501e196c8SJohn Marino 			place = EMSG;
8601e196c8SJohn Marino 			return (-1);
8701e196c8SJohn Marino 		}
88*f445c897SJohn Marino 		if (optopt == 0) {
89*f445c897SJohn Marino 			/* Solitary '-', treat as a '-' option
90*f445c897SJohn Marino 			   if the program (eg su) is looking for it. */
91*f445c897SJohn Marino 			place = EMSG;
92*f445c897SJohn Marino 			if (strchr(ostr, '-') == NULL)
93*f445c897SJohn Marino 				return -1;
94*f445c897SJohn Marino 			optopt = '-';
95*f445c897SJohn Marino 		}
96*f445c897SJohn Marino 	} else
97*f445c897SJohn Marino 		optopt = *place++;
98*f445c897SJohn Marino 
99*f445c897SJohn Marino 	/* See if option letter is one the caller wanted... */
100*f445c897SJohn Marino 	if (optopt == ':' || (oli = strchr(ostr, optopt)) == NULL) {
101*f445c897SJohn Marino 		if (*place == 0)
10201e196c8SJohn Marino 			++optind;
10301e196c8SJohn Marino 		if (opterr && *ostr != ':')
10401e196c8SJohn Marino 			(void)fprintf(stderr,
105*f445c897SJohn Marino 			    "%s: unknown option -- %c\n", __progname, optopt);
10601e196c8SJohn Marino 		return (BADCH);
10701e196c8SJohn Marino 	}
108*f445c897SJohn Marino 
109*f445c897SJohn Marino 	/* Does this option need an argument? */
110*f445c897SJohn Marino 	if (oli[1] != ':') {
111*f445c897SJohn Marino 		/* don't need argument */
11201e196c8SJohn Marino 		optarg = NULL;
113*f445c897SJohn Marino 		if (*place == 0)
11401e196c8SJohn Marino 			++optind;
115*f445c897SJohn Marino 	} else {
116*f445c897SJohn Marino 		/* Option-argument is either the rest of this argument or the
117*f445c897SJohn Marino 		   entire next argument. */
118*f445c897SJohn Marino 		if (*place)
119*f445c897SJohn Marino 			optarg = __UNCONST(place);
120*f445c897SJohn Marino 		else if (oli[2] == ':')
121*f445c897SJohn Marino 			/*
122*f445c897SJohn Marino 			 * GNU Extension, for optional arguments if the rest of
123*f445c897SJohn Marino 			 * the argument is empty, we return NULL
124*f445c897SJohn Marino 			 */
125*f445c897SJohn Marino 			optarg = NULL;
126*f445c897SJohn Marino 		else if (nargc > ++optind)
127*f445c897SJohn Marino 			optarg = nargv[optind];
128*f445c897SJohn Marino 		else {
129*f445c897SJohn Marino 			/* option-argument absent */
13001e196c8SJohn Marino 			place = EMSG;
13101e196c8SJohn Marino 			if (*ostr == ':')
13201e196c8SJohn Marino 				return (BADARG);
13301e196c8SJohn Marino 			if (opterr)
13401e196c8SJohn Marino 				(void)fprintf(stderr,
13501e196c8SJohn Marino 				    "%s: option requires an argument -- %c\n",
13601e196c8SJohn Marino 				    __progname, optopt);
13701e196c8SJohn Marino 			return (BADCH);
13801e196c8SJohn Marino 		}
13901e196c8SJohn Marino 		place = EMSG;
14001e196c8SJohn Marino 		++optind;
14101e196c8SJohn Marino 	}
142*f445c897SJohn Marino 	return (optopt);			/* return option letter */
14301e196c8SJohn Marino }
14401e196c8SJohn Marino #endif
14501e196c8SJohn Marino #ifdef MAIN
14601e196c8SJohn Marino #ifndef BSD4_4
14701e196c8SJohn Marino char *__progname;
14801e196c8SJohn Marino #endif
14901e196c8SJohn Marino 
15001e196c8SJohn Marino int
main(argc,argv)15101e196c8SJohn Marino main(argc, argv)
15201e196c8SJohn Marino 	int argc;
15301e196c8SJohn Marino 	char *argv[];
15401e196c8SJohn Marino {
15501e196c8SJohn Marino 	int c;
15601e196c8SJohn Marino 	char *opts = argv[1];
15701e196c8SJohn Marino 
15801e196c8SJohn Marino 	--argc;
15901e196c8SJohn Marino 	++argv;
16001e196c8SJohn Marino 
16101e196c8SJohn Marino 	while ((c = getopt(argc, argv, opts)) != EOF) {
16201e196c8SJohn Marino 		switch (c) {
16301e196c8SJohn Marino 		case '-':
16401e196c8SJohn Marino 			if (optarg)
16501e196c8SJohn Marino 				printf("--%s ", optarg);
16601e196c8SJohn Marino 			break;
16701e196c8SJohn Marino 		case '?':
16801e196c8SJohn Marino 			exit(1);
16901e196c8SJohn Marino 			break;
17001e196c8SJohn Marino 		default:
17101e196c8SJohn Marino 			if (optarg)
17201e196c8SJohn Marino 				printf("-%c %s ", c, optarg);
17301e196c8SJohn Marino 			else
17401e196c8SJohn Marino 				printf("-%c ", c);
17501e196c8SJohn Marino 			break;
17601e196c8SJohn Marino 		}
17701e196c8SJohn Marino 	}
17801e196c8SJohn Marino 
17901e196c8SJohn Marino 	if (optind < argc) {
18001e196c8SJohn Marino 		printf("-- ");
18101e196c8SJohn Marino 		for (; optind < argc; ++optind) {
18201e196c8SJohn Marino 			printf("%s ", argv[optind]);
18301e196c8SJohn Marino 		}
18401e196c8SJohn Marino 	}
18501e196c8SJohn Marino 	printf("\n");
18601e196c8SJohn Marino 	exit(0);
18701e196c8SJohn Marino }
18801e196c8SJohn Marino #endif
189