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