mkoptions.c revision 55659
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 55659 2000-01-09 12:52:01Z bde $";
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
54static	struct users {
55	int	u_default;
56	int	u_min;
57	int	u_max;
58} users[] = {
59	{ 8, 2, 512 },			/* MACHINE_I386 */
60	{ 8, 2, 512 },			/* MACHINE_PC98 */
61	{ 8, 2, 512 },			/* MACHINE_ALPHA */
62};
63#define	NUSERS	(sizeof (users) / sizeof (users[0]))
64
65static char *lower __P((char *));
66static void read_options __P((void));
67static void do_option __P((char *));
68static char *tooption __P((char *));
69
70void
71options()
72{
73	char buf[40];
74	struct cputype *cp;
75	struct opt_list *ol;
76	struct opt *op;
77	struct users *up;
78
79	/* Fake the cpu types as options. */
80	for (cp = cputype; cp != NULL; cp = cp->cpu_next) {
81		op = (struct opt *)malloc(sizeof(*op));
82		memset(op, 0, sizeof(*op));
83		op->op_name = ns(cp->cpu_name);
84		op->op_next = opt;
85		opt = op;
86	}
87
88	/* Initialize `maxusers'. */
89	if ((unsigned)machine > NUSERS) {
90		printf("maxusers config info isn't present, using i386\n");
91		up = &users[MACHINE_I386 - 1];
92	} else
93		up = &users[machine - 1];
94	if (maxusers == 0) {
95		printf("maxusers not specified; %d assumed\n", up->u_default);
96		maxusers = up->u_default;
97	} else if (maxusers < up->u_min) {
98		printf("minimum of %d maxusers assumed\n", up->u_min);
99		maxusers = up->u_min;
100	} else if (maxusers > up->u_max)
101		printf("warning: maxusers > %d (%d)\n", up->u_max, maxusers);
102
103	/* Fake MAXUSERS as an option. */
104	op = (struct opt *)malloc(sizeof(*op));
105	memset(op, 0, sizeof(*op));
106	op->op_name = "MAXUSERS";
107	snprintf(buf, sizeof(buf), "%d", maxusers);
108	op->op_value = ns(buf);
109	op->op_next = opt;
110	opt = op;
111
112	read_options();
113	for (ol = otab; ol != 0; ol = ol->o_next)
114		do_option(ol->o_name);
115}
116
117/*
118 * Generate an <options>.h file
119 */
120
121static void
122do_option(name)
123	char *name;
124{
125	char *basefile, *file, *inw;
126	struct opt_list *ol;
127	struct opt *op, *op_head, *topp;
128	FILE *inf, *outf;
129	char *value;
130	char *oldvalue;
131	int seen;
132	int tidy;
133
134	file = tooption(name);
135
136	/*
137	 * Check to see if the option was specified..
138	 */
139	value = NULL;
140	for (op = opt; op; op = op->op_next) {
141		if (eq(name, op->op_name)) {
142			oldvalue = value;
143			value = op->op_value;
144			if (value == NULL)
145				value = ns("1");
146			if (oldvalue != NULL && !eq(value, oldvalue))
147				printf(
148			    "%s:%d: option \"%s\" redefined from %s to %s\n",
149				   PREFIX, op->op_line, op->op_name, oldvalue,
150				   value);
151			op->op_ownfile++;
152		}
153	}
154
155	inf = fopen(file, "r");
156	if (inf == 0) {
157		outf = fopen(file, "w");
158		if (outf == 0)
159			err(1, "%s", file);
160
161		/* was the option in the config file? */
162		if (value) {
163			fprintf(outf, "#define %s %s\n", name, value);
164		} /* else empty file */
165
166		(void) fclose(outf);
167		return;
168	}
169	basefile = "";
170	for (ol = otab; ol != 0; ol = ol->o_next)
171		if (eq(name, ol->o_name)) {
172			basefile = ol->o_file;
173			break;
174		}
175	oldvalue = NULL;
176	op_head = NULL;
177	seen = 0;
178	tidy = 0;
179	for (;;) {
180		char *cp;
181		char *invalue;
182
183		/* get the #define */
184		if ((inw = get_word(inf)) == 0 || inw == (char *)EOF)
185			break;
186		/* get the option name */
187		if ((inw = get_word(inf)) == 0 || inw == (char *)EOF)
188			break;
189		inw = ns(inw);
190		/* get the option value */
191		if ((cp = get_word(inf)) == 0 || cp == (char *)EOF)
192			break;
193		/* option value */
194		invalue = ns(cp); /* malloced */
195		if (eq(inw, name)) {
196			oldvalue = invalue;
197			invalue = value;
198			seen++;
199		}
200		for (ol = otab; ol != 0; ol = ol->o_next)
201			if (eq(inw, ol->o_name))
202				break;
203		if (!eq(inw, name) && !ol) {
204			printf("WARNING: unknown option `%s' removed from %s\n",
205				inw, file);
206			tidy++;
207		} else if (ol != NULL && !eq(basefile, ol->o_file)) {
208			printf("WARNING: option `%s' moved from %s to %s\n",
209				inw, basefile, ol->o_file);
210			tidy++;
211		} else {
212			op = (struct opt *) malloc(sizeof *op);
213			bzero(op, sizeof(*op));
214			op->op_name = inw;
215			op->op_value = invalue;
216			op->op_next = op_head;
217			op_head = op;
218		}
219
220		/* EOL? */
221		cp = get_word(inf);
222		if (cp == (char *)EOF)
223			break;
224	}
225	(void) fclose(inf);
226	if (!tidy && ((value == NULL && oldvalue == NULL) ||
227	    (value && oldvalue && eq(value, oldvalue)))) {
228		for (op = op_head; op != NULL; op = topp) {
229			topp = op->op_next;
230			free(op->op_name);
231			free(op->op_value);
232			free(op);
233		}
234		return;
235	}
236
237	if (value && !seen) {
238		/* New option appears */
239		op = (struct opt *) malloc(sizeof *op);
240		bzero(op, sizeof(*op));
241		op->op_name = ns(name);
242		op->op_value = value ? ns(value) : NULL;
243		op->op_next = op_head;
244		op_head = op;
245	}
246
247	outf = fopen(file, "w");
248	if (outf == 0)
249		err(1, "%s", file);
250	for (op = op_head; op != NULL; op = topp) {
251		/* was the option in the config file? */
252		if (op->op_value) {
253			fprintf(outf, "#define %s %s\n",
254				op->op_name, op->op_value);
255		}
256		topp = op->op_next;
257		free(op->op_name);
258		free(op->op_value);
259		free(op);
260	}
261	(void) fclose(outf);
262}
263
264/*
265 * Find the filename to store the option spec into.
266 */
267static char *
268tooption(name)
269	char *name;
270{
271	static char hbuf[80];
272	char nbuf[80];
273	struct opt_list *po;
274
275	/* "cannot happen"?  the otab list should be complete.. */
276	(void) strcpy(nbuf, "options.h");
277
278	for (po = otab ; po != 0; po = po->o_next) {
279		if (eq(po->o_name, name)) {
280			strcpy(nbuf, po->o_file);
281			break;
282		}
283	}
284
285	(void) strcpy(hbuf, path(nbuf));
286	return (hbuf);
287}
288
289/*
290 * read the options and options.<machine> files
291 */
292static void
293read_options()
294{
295	FILE *fp;
296	char fname[80];
297	char *wd, *this, *val;
298	struct opt_list *po;
299	int first = 1;
300	char genopt[80];
301
302	otab = 0;
303	if (ident == NULL) {
304		printf("no ident line specified\n");
305		exit(1);
306	}
307	(void) snprintf(fname, sizeof fname, "../../conf/options");
308openit:
309	fp = fopen(fname, "r");
310	if (fp == 0) {
311		return;
312	}
313next:
314	wd = get_word(fp);
315	if (wd == (char *)EOF) {
316		(void) fclose(fp);
317		if (first == 1) {
318			first++;
319			(void) snprintf(fname, sizeof fname, "../../conf/options.%s", machinename);
320			fp = fopen(fname, "r");
321			if (fp != 0)
322				goto next;
323			(void) snprintf(fname, sizeof fname, "options.%s", machinename);
324			goto openit;
325		}
326		if (first == 2) {
327			first++;
328			(void) snprintf(fname, sizeof fname, "options.%s", raisestr(ident));
329			fp = fopen(fname, "r");
330			if (fp != 0)
331				goto next;
332		}
333		return;
334	}
335	if (wd == 0)
336		goto next;
337	if (wd[0] == '#')
338	{
339		while (((wd = get_word(fp)) != (char *)EOF) && wd)
340		;
341		goto next;
342	}
343	this = ns(wd);
344	val = get_word(fp);
345	if (val == (char *)EOF)
346		return;
347	if (val == 0) {
348		char *s = ns(this);
349		(void) snprintf(genopt, sizeof genopt, "opt_%s.h", lower(s));
350		val = genopt;
351		free(s);
352	}
353	val = ns(val);
354
355	for (po = otab ; po != 0; po = po->o_next) {
356		if (eq(po->o_name, this)) {
357			printf("%s: Duplicate option %s.\n",
358			       fname, this);
359			exit(1);
360		}
361	}
362
363	po = (struct opt_list *) malloc(sizeof *po);
364	bzero(po, sizeof(*po));
365	po->o_name = this;
366	po->o_file = val;
367	po->o_next = otab;
368	otab = po;
369
370	goto next;
371}
372
373static char *
374lower(str)
375	register char *str;
376{
377	register char *cp = str;
378
379	while (*str) {
380		if (isupper(*str))
381			*str = tolower(*str);
382		str++;
383	}
384	return (cp);
385}
386
387