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