xref: /openbsd/games/trek/getpar.c (revision db3296cf)
1 /*	$OpenBSD: getpar.c,v 1.12 2003/07/10 00:03:01 david 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 #ifndef lint
34 #if 0
35 static char sccsid[] = "@(#)getpar.c	8.1 (Berkeley) 5/31/93";
36 #else
37 static char rcsid[] = "$OpenBSD: getpar.c,v 1.12 2003/07/10 00:03:01 david Exp $";
38 #endif
39 #endif /* not lint */
40 
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include "getpar.h"
45 #include "trek.h"
46 
47 static int testterm(void);
48 
49 /**
50  **	get integer parameter
51  **/
52 
53 int
54 getintpar(s)
55 	const char	*s;
56 {
57 	int	i, n;
58 
59 	while (1)
60 	{
61 		if (testnl() && s)
62 			printf("%s: ", s);
63 		i = scanf("%d", &n);
64 		if (i < 0)
65 			exit(1);
66 		if (i > 0 && testterm())
67 			return (n);
68 		printf("invalid input; please enter an integer\n");
69 		skiptonl(0);
70 	}
71 }
72 
73 /**
74  **	get floating parameter
75  **/
76 
77 double
78 getfltpar(s)
79 	const char	*s;
80 {
81 	int		i;
82 	double		d;
83 
84 	while (1)
85 	{
86 		if (testnl() && s)
87 			printf("%s: ", s);
88 		i = scanf("%lf", &d);
89 		if (i < 0)
90 			exit(1);
91 		if (i > 0 && testterm())
92 			return (d);
93 		printf("invalid input; please enter a double\n");
94 		skiptonl(0);
95 	}
96 }
97 
98 /**
99  **	get yes/no parameter
100  **/
101 
102 const struct cvntab	Yntab[] =
103 {
104 	{ "y",	"es",	(cmdfun)1,	1 },
105 	{ "n",	"o",	(cmdfun)0,	0 },
106 	{ NULL,	NULL,	NULL,		0 }
107 };
108 
109 int
110 getynpar(s)
111 	const char	*s;
112 {
113 	const struct cvntab	*r;
114 
115 	r = getcodpar(s, Yntab);
116 	return (r->value2);
117 }
118 
119 
120 /**
121  **	get coded parameter
122  **/
123 
124 const struct cvntab *
125 getcodpar(s, tab)
126 	const char		*s;
127 	const struct cvntab	tab[];
128 {
129 	char				input[100];
130 	const struct cvntab		*r;
131 	int				flag;
132 	const char			*p, *q;
133 	int				c;
134 	int				f;
135 
136 	flag = 0;
137 	while (1)
138 	{
139 		flag |= (f = testnl());
140 		if (flag)
141 			printf("%s: ", s);
142 		if (f)
143 			getchar();		/* throw out the newline */
144 		scanf("%*[ \t;]");
145 		if ((c = scanf("%99[^ \t;\n]", input)) < 0)
146 			exit(1);
147 		if (c == 0)
148 			continue;
149 		flag = 1;
150 
151 		/* if command list, print four per line */
152 		if (input[0] == '?' && input[1] == 0)
153 		{
154 			c = 4;
155 			for (r = tab; r->abrev; r++)
156 			{
157 				strlcpy(input, r->abrev, sizeof input);
158 				strlcat(input, r->full, sizeof input);
159 				printf("%14.14s", input);
160 				if (--c > 0)
161 					continue;
162 				c = 4;
163 				printf("\n");
164 			}
165 			if (c != 4)
166 				printf("\n");
167 			continue;
168 		}
169 
170 		/* search for in table */
171 		for (r = tab; r->abrev; r++)
172 		{
173 			p = input;
174 			for (q = r->abrev; *q; q++)
175 				if (*p++ != *q)
176 					break;
177 			if (!*q)
178 			{
179 				for (q = r->full; *p && *q; q++, p++)
180 					if (*p != *q)
181 						break;
182 				if (!*p || !*q)
183 					break;
184 			}
185 		}
186 
187 		/* check for not found */
188 		if (!r->abrev)
189 		{
190 			printf("invalid input; ? for valid inputs\n");
191 			skiptonl(0);
192 		}
193 		else
194 			return (r);
195 	}
196 }
197 
198 
199 /**
200  **	get string parameter
201  **/
202 
203 void
204 getstrpar(s, r, l, t)
205 	const char	*s;
206 	char		*r;
207 	int		l;
208 	const char	*t;
209 {
210 	int	i, f;
211 	char	format[20];
212 
213 	if (t == 0)
214 		t = " \t\n;";
215 	(void)snprintf(format, sizeof format, "%%%d[^%s]", l, t);
216 	while (1)
217 	{
218 		if ((f = testnl()) && s)
219 			printf("%s: ", s);
220 		if (f)
221 			getchar();
222 		scanf("%*[\t ;]");
223 		i = scanf(format, r);
224 		if (i < 0)
225 			exit(1);
226 		if (i != 0)
227 			return;
228 	}
229 }
230 
231 
232 /**
233  **	test if newline is next valid character
234  **/
235 
236 int
237 testnl()
238 {
239 	int	c;
240 
241 	while ((c = getchar()) != '\n')
242 		if ((c >= '0' && c <= '9') || c == '.' || c == '!' ||
243 				(c >= 'A' && c <= 'Z') ||
244 				(c >= 'a' && c <= 'z') || c == '-' || c == EOF)
245 		{
246 			ungetc(c, stdin);
247 			return(0);
248 		}
249 	ungetc(c, stdin);
250 	return (1);
251 }
252 
253 
254 /**
255  **	scan for newline
256  **/
257 
258 void
259 skiptonl(c)
260 	int	c;
261 {
262 	while (c != '\n')
263 		if (!(c = getchar()))
264 			return;
265 	ungetc('\n', stdin);
266 	return;
267 }
268 
269 
270 /**
271  **	test for valid terminator
272  **/
273 
274 static int
275 testterm()
276 {
277 	int	c;
278 
279 	if (!(c = getchar()))
280 		return (1);
281 	if (c == '.')
282 		return (0);
283 	if (c == '\n' || c == ';')
284 		ungetc(c, stdin);
285 	return (1);
286 }
287 
288 
289 /*
290 **  TEST FOR SPECIFIED DELIMETER
291 **
292 **	The standard input is scanned for the parameter.  If found,
293 **	it is thrown away and non-zero is returned.  If not found,
294 **	zero is returned.
295 */
296 
297 int
298 readdelim(d)
299 	int	d;
300 {
301 	int	c;
302 
303 	while ((c = getchar()))
304 	{
305 		if (c == d)
306 			return (1);
307 		if (c == ' ')
308 			continue;
309 		ungetc(c, stdin);
310 		break;
311 	}
312 	return (0);
313 }
314