mkoptions.c revision 50479
1/*
2 * Copyright (c) 1995  Peter Wemm
3 * Copyright (c) 1980, 1993
4 *	The Regents of the University of California.  All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 *    must display the following acknowledgement:
16 *	This product includes software developed by the University of
17 *	California, Berkeley and its contributors.
18 * 4. Neither the name of the University nor the names of its contributors
19 *    may be used to endorse or promote products derived from this software
20 *    without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#ifndef lint
36#if 0
37static char sccsid[] = "@(#)mkheaders.c	8.1 (Berkeley) 6/6/93";
38#endif
39static const char rcsid[] =
40  "$FreeBSD: head/usr.sbin/config/mkoptions.c 50479 1999-08-28 01:35:59Z peter $";
41#endif /* not lint */
42
43/*
44 * Make all the .h files for the optional entries
45 */
46
47#include <ctype.h>
48#include <err.h>
49#include <stdio.h>
50#include <string.h>
51#include "config.h"
52#include "y.tab.h"
53
54#define ns(s) strdup(s)
55
56static	struct users {
57	int	u_default;
58	int	u_min;
59	int	u_max;
60} users[] = {
61	{ 8, 2, 512 },			/* MACHINE_I386 */
62	{ 8, 2, 512 },			/* MACHINE_PC98 */
63	{ 8, 2, 512 },			/* MACHINE_ALPHA */
64};
65#define	NUSERS	(sizeof (users) / sizeof (users[0]))
66
67static char *lower __P((char *));
68static void read_options __P((void));
69static void do_option __P((char *));
70static char *tooption __P((char *));
71
72void
73options()
74{
75	char buf[40];
76	struct cputype *cp;
77	struct opt_list *ol;
78	struct opt *op;
79	struct users *up;
80
81	/* Fake the cpu types as options. */
82	for (cp = cputype; cp != NULL; cp = cp->cpu_next) {
83		op = (struct opt *)malloc(sizeof(*op));
84		memset(op, 0, sizeof(*op));
85		op->op_name = ns(cp->cpu_name);
86		op->op_next = opt;
87		opt = op;
88	}
89
90	/* Initialize `maxusers'. */
91	if ((unsigned)machine > NUSERS) {
92		printf("maxusers config info isn't present, using i386\n");
93		up = &users[MACHINE_I386 - 1];
94	} else
95		up = &users[machine - 1];
96	if (maxusers == 0) {
97		printf("maxusers not specified; %d assumed\n", up->u_default);
98		maxusers = up->u_default;
99	} else if (maxusers < up->u_min) {
100		printf("minimum of %d maxusers assumed\n", up->u_min);
101		maxusers = up->u_min;
102	} else if (maxusers > up->u_max)
103		printf("warning: maxusers > %d (%d)\n", up->u_max, maxusers);
104
105	/* Fake MAXUSERS as an option. */
106	op = (struct opt *)malloc(sizeof(*op));
107	memset(op, 0, sizeof(*op));
108	op->op_name = "MAXUSERS";
109	snprintf(buf, sizeof(buf), "%d", maxusers);
110	op->op_value = ns(buf);
111	op->op_next = opt;
112	opt = op;
113
114	read_options();
115	for (ol = otab; ol != 0; ol = ol->o_next)
116		do_option(ol->o_name);
117}
118
119/*
120 * Generate an <options>.h file
121 */
122
123static void
124do_option(name)
125	char *name;
126{
127	char *file, *inw;
128	struct opt_list *ol;
129	struct opt *op, *op_head, *topp;
130	FILE *inf, *outf;
131	char *value;
132	char *oldvalue;
133	int seen;
134	int tidy;
135
136	file = tooption(name);
137
138	/*
139	 * Check to see if the option was specified..
140	 */
141	value = NULL;
142	for (op = opt; op; op = op->op_next) {
143		if (eq(name, op->op_name)) {
144			oldvalue = value;
145			value = op->op_value;
146			if (value == NULL)
147				value = ns("1");
148			if (oldvalue != NULL && !eq(value, oldvalue))
149				printf(
150			    "%s:%d: option \"%s\" redefined from %s to %s\n",
151				   PREFIX, op->op_line, op->op_name, oldvalue,
152				   value);
153			op->op_ownfile++;
154		}
155	}
156
157	inf = fopen(file, "r");
158	if (inf == 0) {
159		outf = fopen(file, "w");
160		if (outf == 0)
161			err(1, "%s", file);
162
163		/* was the option in the config file? */
164		if (value) {
165			fprintf(outf, "#define %s %s\n", name, value);
166		} /* else empty file */
167
168		(void) fclose(outf);
169		return;
170	}
171	oldvalue = NULL;
172	op_head = NULL;
173	seen = 0;
174	tidy = 0;
175	for (;;) {
176		char *cp;
177		char *invalue;
178
179		/* get the #define */
180		if ((inw = get_word(inf)) == 0 || inw == (char *)EOF)
181			break;
182		/* get the option name */
183		if ((inw = get_word(inf)) == 0 || inw == (char *)EOF)
184			break;
185		inw = ns(inw);
186		/* get the option value */
187		if ((cp = get_word(inf)) == 0 || cp == (char *)EOF)
188			break;
189		/* option value */
190		invalue = ns(cp); /* malloced */
191		if (eq(inw, name)) {
192			oldvalue = invalue;
193			invalue = value;
194			seen++;
195		}
196		for (ol = otab; ol != 0; ol = ol->o_next)
197			if (eq(inw, ol->o_name))
198				break;
199		if (!seen && !ol) {
200			printf("WARNING: unknown option `%s' removed from %s\n",
201				inw, file);
202			tidy++;
203		} else {
204			op = (struct opt *) malloc(sizeof *op);
205			bzero(op, sizeof(*op));
206			op->op_name = inw;
207			op->op_value = invalue;
208			op->op_next = op_head;
209			op_head = op;
210		}
211
212		/* EOL? */
213		cp = get_word(inf);
214		if (cp == (char *)EOF)
215			break;
216	}
217	(void) fclose(inf);
218	if (!tidy && ((value == NULL && oldvalue == NULL) ||
219	    (value && oldvalue && eq(value, oldvalue)))) {
220		for (op = op_head; op != NULL; op = topp) {
221			topp = op->op_next;
222			free(op->op_name);
223			free(op->op_value);
224			free(op);
225		}
226		return;
227	}
228
229	if (value && !seen) {
230		/* New option appears */
231		op = (struct opt *) malloc(sizeof *op);
232		bzero(op, sizeof(*op));
233		op->op_name = ns(name);
234		op->op_value = value ? ns(value) : NULL;
235		op->op_next = op_head;
236		op_head = op;
237	}
238
239	outf = fopen(file, "w");
240	if (outf == 0)
241		err(1, "%s", file);
242	for (op = op_head; op != NULL; op = topp) {
243		/* was the option in the config file? */
244		if (op->op_value) {
245			fprintf(outf, "#define %s %s\n",
246				op->op_name, op->op_value);
247		}
248		topp = op->op_next;
249		free(op->op_name);
250		free(op->op_value);
251		free(op);
252	}
253	(void) fclose(outf);
254}
255
256/*
257 * Find the filename to store the option spec into.
258 */
259static char *
260tooption(name)
261	char *name;
262{
263	static char hbuf[80];
264	char nbuf[80];
265	struct opt_list *po;
266
267	/* "cannot happen"?  the otab list should be complete.. */
268	(void) strcpy(nbuf, "options.h");
269
270	for (po = otab ; po != 0; po = po->o_next) {
271		if (eq(po->o_name, name)) {
272			strcpy(nbuf, po->o_file);
273			break;
274		}
275	}
276
277	(void) strcpy(hbuf, path(nbuf));
278	return (hbuf);
279}
280
281/*
282 * read the options and options.<machine> files
283 */
284static void
285read_options()
286{
287	FILE *fp;
288	char fname[80];
289	char *wd, *this, *val;
290	struct opt_list *po;
291	int first = 1;
292	char genopt[80];
293
294	otab = 0;
295	(void) snprintf(fname, sizeof fname, "../../conf/options");
296openit:
297	fp = fopen(fname, "r");
298	if (fp == 0) {
299		return;
300	}
301	if(ident == NULL) {
302		printf("no ident line specified\n");
303		exit(1);
304	}
305next:
306	wd = get_word(fp);
307	if (wd == (char *)EOF) {
308		(void) fclose(fp);
309		if (first == 1) {
310			(void) snprintf(fname, sizeof fname, "options.%s", machinename);
311			first++;
312			goto openit;
313		}
314		if (first == 2) {
315			(void) snprintf(fname, sizeof fname, "options.%s", raisestr(ident));
316			first++;
317			fp = fopen(fname, "r");
318			if (fp != 0)
319				goto next;
320		}
321		return;
322	}
323	if (wd == 0)
324		goto next;
325	/*************************************************\
326	* If it's a comment ignore to the end of the line *
327	\*************************************************/
328	if(wd[0] == '#')
329	{
330		while( ((wd = get_word(fp)) != (char *)EOF) && wd)
331		;
332		goto next;
333	}
334	this = ns(wd);
335	val = get_word(fp);
336	if (val == (char *)EOF)
337		return;
338	if (val == 0) {
339		char *s = ns(this);
340		(void) snprintf(genopt, sizeof genopt, "opt_%s.h", lower(s));
341		val = genopt;
342		free(s);
343	}
344	val = ns(val);
345
346	for (po = otab ; po != 0; po = po->o_next) {
347		if (eq(po->o_name, this)) {
348			printf("%s: Duplicate option %s.\n",
349			       fname, this);
350			exit(1);
351		}
352	}
353
354	po = (struct opt_list *) malloc(sizeof *po);
355	bzero(po, sizeof(*po));
356	po->o_name = this;
357	po->o_file = val;
358	po->o_next = otab;
359	otab = po;
360
361	goto next;
362}
363
364static char *
365lower(str)
366	register char *str;
367{
368	register char *cp = str;
369
370	while (*str) {
371		if (isupper(*str))
372			*str = tolower(*str);
373		str++;
374	}
375	return (cp);
376}
377
378