GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/pr/egetopt.c Lines: 0 66 0.0 %
Date: 2016-12-06 Branches: 0 68 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: egetopt.c,v 1.9 2013/11/26 13:19:07 deraadt 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 <ctype.h>
37
#include <stdio.h>
38
#include <stdlib.h>
39
#include <string.h>
40
41
#include "extern.h"
42
43
/*
44
 * egetopt:	get option letter from argument vector (an extended
45
 *		version of getopt).
46
 *
47
 * Non standard additions to the ostr specs are:
48
 * 1) '?': immediate value following arg is optional (no white space
49
 *    between the arg and the value)
50
 * 2) '#': +/- followed by a number (with an optional sign but
51
 *    no white space between the arg and the number). The - may be
52
 *    combined with other options, but the + cannot.
53
 */
54
55
int	eopterr = 1;		/* if error message should be printed */
56
int	eoptind = 1;		/* index into parent argv vector */
57
int	eoptopt;		/* character checked for validity */
58
char	*eoptarg;		/* argument associated with option */
59
60
#define	BADCH	(int)'?'
61
#define	EMSG	""
62
63
int
64
egetopt(int nargc, char * const *nargv, const char *ostr)
65
{
66
	static char *place = EMSG;	/* option letter processing */
67
	char *oli;			/* option letter list index */
68
	static int delim;		/* which option delimiter */
69
	char *p;
70
	static char savec = '\0';
71
72
	if (savec != '\0') {
73
		*place = savec;
74
		savec = '\0';
75
	}
76
77
	if (!*place) {
78
		/*
79
		 * update scanning pointer
80
		 */
81
		if ((eoptind >= nargc) ||
82
		    ((*(place = nargv[eoptind]) != '-') && (*place != '+'))) {
83
			place = EMSG;
84
			return (-1);
85
		}
86
87
		delim = (int)*place;
88
		if (place[1] && *++place == '-' && !place[1]) {
89
			/*
90
			 * found "--"
91
			 */
92
			++eoptind;
93
			place = EMSG;
94
			return (-1);
95
		}
96
	}
97
98
	/*
99
	 * check option letter
100
	 */
101
	if ((eoptopt = (int)*place++) == (int)':' || (eoptopt == (int)'?') ||
102
	    !(oli = strchr(ostr, eoptopt))) {
103
		/*
104
		 * if the user didn't specify '-' as an option,
105
		 * assume it means EOF when by itself.
106
		 */
107
		if ((eoptopt == (int)'-') && !*place)
108
			return (-1);
109
		if (strchr(ostr, '#') && (isdigit((unsigned char)eoptopt) ||
110
		    (((eoptopt == (int)'-') || (eoptopt == (int)'+')) &&
111
		      isdigit((unsigned char)*place)))) {
112
			/*
113
			 * # option: +/- with a number is ok
114
			 */
115
			for (p = place; *p != '\0'; ++p) {
116
				if (!isdigit((unsigned char)*p))
117
					break;
118
			}
119
			eoptarg = place-1;
120
121
			if (*p == '\0') {
122
				place = EMSG;
123
				++eoptind;
124
			} else {
125
				place = p;
126
				savec = *p;
127
				*place = '\0';
128
			}
129
			return (delim);
130
		}
131
132
		if (!*place)
133
			++eoptind;
134
		if (eopterr) {
135
			if (!(p = strrchr(*nargv, '/')))
136
				p = *nargv;
137
			else
138
				++p;
139
			(void)fprintf(stderr, "%s: illegal option -- %c\n",
140
			    p, eoptopt);
141
		}
142
		return (BADCH);
143
	}
144
	if (delim == (int)'+') {
145
		/*
146
		 * '+' is only allowed with numbers
147
		 */
148
		if (!*place)
149
			++eoptind;
150
		if (eopterr) {
151
			if (!(p = strrchr(*nargv, '/')))
152
				p = *nargv;
153
			else
154
				++p;
155
			(void)fprintf(stderr,
156
				"%s: illegal '+' delimiter with option -- %c\n",
157
				p, eoptopt);
158
		}
159
		return (BADCH);
160
	}
161
	++oli;
162
	if ((*oli != ':') && (*oli != '?')) {
163
		/*
164
		 * don't need argument
165
		 */
166
		eoptarg = NULL;
167
		if (!*place)
168
			++eoptind;
169
		return (eoptopt);
170
	}
171
172
	if (*place) {
173
		/*
174
		 * no white space
175
		 */
176
		eoptarg = place;
177
	} else if (*oli == '?') {
178
		/*
179
		 * no arg, but NOT required
180
		 */
181
		eoptarg = NULL;
182
	} else if (nargc <= ++eoptind) {
183
		/*
184
		 * no arg, but IS required
185
		 */
186
		place = EMSG;
187
		if (eopterr) {
188
			if (!(p = strrchr(*nargv, '/')))
189
				p = *nargv;
190
			else
191
				++p;
192
			(void)fprintf(stderr,
193
			    "%s: option requires an argument -- %c\n", p,
194
			    eoptopt);
195
		}
196
		return (BADCH);
197
	} else {
198
		/*
199
		 * arg has white space
200
		 */
201
		eoptarg = nargv[eoptind];
202
	}
203
	place = EMSG;
204
	++eoptind;
205
	return (eoptopt);
206
}