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