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