xref: /openbsd/games/trek/getpar.c (revision 17df1aa7)
1 /*	$OpenBSD: getpar.c,v 1.13 2009/10/27 23:59:27 deraadt Exp $	*/
2 /*	$NetBSD: getpar.c,v 1.4 1995/04/24 12:25:57 cgd Exp $	*/
3 
4 /*
5  * Copyright (c) 1980, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include "getpar.h"
37 #include "trek.h"
38 
39 static int testterm(void);
40 
41 /**
42  **	get integer parameter
43  **/
44 
45 int
46 getintpar(s)
47 	const char	*s;
48 {
49 	int	i, n;
50 
51 	while (1)
52 	{
53 		if (testnl() && s)
54 			printf("%s: ", s);
55 		i = scanf("%d", &n);
56 		if (i < 0)
57 			exit(1);
58 		if (i > 0 && testterm())
59 			return (n);
60 		printf("invalid input; please enter an integer\n");
61 		skiptonl(0);
62 	}
63 }
64 
65 /**
66  **	get floating parameter
67  **/
68 
69 double
70 getfltpar(s)
71 	const char	*s;
72 {
73 	int		i;
74 	double		d;
75 
76 	while (1)
77 	{
78 		if (testnl() && s)
79 			printf("%s: ", s);
80 		i = scanf("%lf", &d);
81 		if (i < 0)
82 			exit(1);
83 		if (i > 0 && testterm())
84 			return (d);
85 		printf("invalid input; please enter a double\n");
86 		skiptonl(0);
87 	}
88 }
89 
90 /**
91  **	get yes/no parameter
92  **/
93 
94 const struct cvntab	Yntab[] =
95 {
96 	{ "y",	"es",	(cmdfun)1,	1 },
97 	{ "n",	"o",	(cmdfun)0,	0 },
98 	{ NULL,	NULL,	NULL,		0 }
99 };
100 
101 int
102 getynpar(s)
103 	const char	*s;
104 {
105 	const struct cvntab	*r;
106 
107 	r = getcodpar(s, Yntab);
108 	return (r->value2);
109 }
110 
111 
112 /**
113  **	get coded parameter
114  **/
115 
116 const struct cvntab *
117 getcodpar(s, tab)
118 	const char		*s;
119 	const struct cvntab	tab[];
120 {
121 	char				input[100];
122 	const struct cvntab		*r;
123 	int				flag;
124 	const char			*p, *q;
125 	int				c;
126 	int				f;
127 
128 	flag = 0;
129 	while (1)
130 	{
131 		flag |= (f = testnl());
132 		if (flag)
133 			printf("%s: ", s);
134 		if (f)
135 			getchar();		/* throw out the newline */
136 		scanf("%*[ \t;]");
137 		if ((c = scanf("%99[^ \t;\n]", input)) < 0)
138 			exit(1);
139 		if (c == 0)
140 			continue;
141 		flag = 1;
142 
143 		/* if command list, print four per line */
144 		if (input[0] == '?' && input[1] == 0)
145 		{
146 			c = 4;
147 			for (r = tab; r->abrev; r++)
148 			{
149 				strlcpy(input, r->abrev, sizeof input);
150 				strlcat(input, r->full, sizeof input);
151 				printf("%14.14s", input);
152 				if (--c > 0)
153 					continue;
154 				c = 4;
155 				printf("\n");
156 			}
157 			if (c != 4)
158 				printf("\n");
159 			continue;
160 		}
161 
162 		/* search for in table */
163 		for (r = tab; r->abrev; r++)
164 		{
165 			p = input;
166 			for (q = r->abrev; *q; q++)
167 				if (*p++ != *q)
168 					break;
169 			if (!*q)
170 			{
171 				for (q = r->full; *p && *q; q++, p++)
172 					if (*p != *q)
173 						break;
174 				if (!*p || !*q)
175 					break;
176 			}
177 		}
178 
179 		/* check for not found */
180 		if (!r->abrev)
181 		{
182 			printf("invalid input; ? for valid inputs\n");
183 			skiptonl(0);
184 		}
185 		else
186 			return (r);
187 	}
188 }
189 
190 
191 /**
192  **	get string parameter
193  **/
194 
195 void
196 getstrpar(s, r, l, t)
197 	const char	*s;
198 	char		*r;
199 	int		l;
200 	const char	*t;
201 {
202 	int	i, f;
203 	char	format[20];
204 
205 	if (t == 0)
206 		t = " \t\n;";
207 	(void)snprintf(format, sizeof format, "%%%d[^%s]", l, t);
208 	while (1)
209 	{
210 		if ((f = testnl()) && s)
211 			printf("%s: ", s);
212 		if (f)
213 			getchar();
214 		scanf("%*[\t ;]");
215 		i = scanf(format, r);
216 		if (i < 0)
217 			exit(1);
218 		if (i != 0)
219 			return;
220 	}
221 }
222 
223 
224 /**
225  **	test if newline is next valid character
226  **/
227 
228 int
229 testnl()
230 {
231 	int	c;
232 
233 	while ((c = getchar()) != '\n')
234 		if ((c >= '0' && c <= '9') || c == '.' || c == '!' ||
235 				(c >= 'A' && c <= 'Z') ||
236 				(c >= 'a' && c <= 'z') || c == '-' || c == EOF)
237 		{
238 			ungetc(c, stdin);
239 			return(0);
240 		}
241 	ungetc(c, stdin);
242 	return (1);
243 }
244 
245 
246 /**
247  **	scan for newline
248  **/
249 
250 void
251 skiptonl(c)
252 	int	c;
253 {
254 	while (c != '\n')
255 		if (!(c = getchar()))
256 			return;
257 	ungetc('\n', stdin);
258 	return;
259 }
260 
261 
262 /**
263  **	test for valid terminator
264  **/
265 
266 static int
267 testterm()
268 {
269 	int	c;
270 
271 	if (!(c = getchar()))
272 		return (1);
273 	if (c == '.')
274 		return (0);
275 	if (c == '\n' || c == ';')
276 		ungetc(c, stdin);
277 	return (1);
278 }
279 
280 
281 /*
282 **  TEST FOR SPECIFIED DELIMETER
283 **
284 **	The standard input is scanned for the parameter.  If found,
285 **	it is thrown away and non-zero is returned.  If not found,
286 **	zero is returned.
287 */
288 
289 int
290 readdelim(d)
291 	int	d;
292 {
293 	int	c;
294 
295 	while ((c = getchar()))
296 	{
297 		if (c == d)
298 			return (1);
299 		if (c == ' ')
300 			continue;
301 		ungetc(c, stdin);
302 		break;
303 	}
304 	return (0);
305 }
306