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