mkoptions.c revision 45775
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.9 1999/04/17 14:41:40 peter 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_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	sprintf(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 *op, *op_head, *topp;
129	FILE *inf, *outf;
130	char *value;
131	char *oldvalue;
132	int seen;
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	oldvalue = NULL;
170	op_head = NULL;
171	seen = 0;
172	for (;;) {
173		char *cp;
174		char *invalue;
175
176		/* get the #define */
177		if ((inw = get_word(inf)) == 0 || inw == (char *)EOF)
178			break;
179		/* get the option name */
180		if ((inw = get_word(inf)) == 0 || inw == (char *)EOF)
181			break;
182		inw = ns(inw);
183		cp = get_word(inf);
184		if (cp == 0 || cp == (char *)EOF)
185			break;
186		/* option value */
187		invalue = ns(cp); /* malloced */
188		if (eq(inw, name)) {
189			oldvalue = invalue;
190			invalue = value;
191			seen++;
192		}
193		op = (struct opt *) malloc(sizeof *op);
194		bzero(op, sizeof(*op));
195		op->op_name = inw;
196		op->op_value = invalue;
197		op->op_next = op_head;
198		op_head = op;
199
200		/* EOL? */
201		cp = get_word(inf);
202		if (cp == (char *)EOF)
203			break;
204	}
205	(void) fclose(inf);
206	if ((value == NULL && oldvalue == NULL) ||
207	    (value && oldvalue && eq(value,oldvalue))) {
208		for (op = op_head; op != NULL; op = topp) {
209			topp = op->op_next;
210			free(op->op_name);
211			free(op->op_value);
212			free(op);
213		}
214		return;
215	}
216
217	if (value && !seen) {
218		/* New option appears */
219		op = (struct opt *) malloc(sizeof *op);
220		bzero(op, sizeof(*op));
221		op->op_name = ns(name);
222		op->op_value = value ? ns(value) : NULL;
223		op->op_next = op_head;
224		op_head = op;
225	}
226
227	outf = fopen(file, "w");
228	if (outf == 0)
229		err(1, "%s", file);
230	for (op = op_head; op != NULL; op = topp) {
231		/* was the option in the config file? */
232		if (op->op_value) {
233			fprintf(outf, "#define %s %s\n",
234				op->op_name, op->op_value);
235		}
236		topp = op->op_next;
237		free(op->op_name);
238		free(op->op_value);
239		free(op);
240	}
241	(void) fclose(outf);
242}
243
244/*
245 * Find the filename to store the option spec into.
246 */
247static char *
248tooption(name)
249	char *name;
250{
251	static char hbuf[80];
252	char nbuf[80];
253	struct opt_list *po;
254
255	/* "cannot happen"?  the otab list should be complete.. */
256	(void) strcpy(nbuf, "options.h");
257
258	for (po = otab ; po != 0; po = po->o_next) {
259		if (eq(po->o_name, name)) {
260			strcpy(nbuf, po->o_file);
261			break;
262		}
263	}
264
265	(void) strcpy(hbuf, path(nbuf));
266	return (hbuf);
267}
268
269/*
270 * read the options and options.<machine> files
271 */
272static void
273read_options()
274{
275	FILE *fp;
276	char fname[80];
277	char *wd, *this, *val;
278	struct opt_list *po;
279	int first = 1;
280	char genopt[80];
281
282	otab = 0;
283	(void) snprintf(fname, sizeof fname, "../../conf/options");
284openit:
285	fp = fopen(fname, "r");
286	if (fp == 0) {
287		return;
288	}
289	if(ident == NULL) {
290		printf("no ident line specified\n");
291		exit(1);
292	}
293next:
294	wd = get_word(fp);
295	if (wd == (char *)EOF) {
296		(void) fclose(fp);
297		if (first == 1) {
298			(void) snprintf(fname, sizeof fname, "options.%s", machinename);
299			first++;
300			goto openit;
301		}
302		if (first == 2) {
303			(void) snprintf(fname, sizeof fname, "options.%s", raisestr(ident));
304			first++;
305			fp = fopen(fname, "r");
306			if (fp != 0)
307				goto next;
308		}
309		return;
310	}
311	if (wd == 0)
312		goto next;
313	/*************************************************\
314	* If it's a comment ignore to the end of the line *
315	\*************************************************/
316	if(wd[0] == '#')
317	{
318		while( ((wd = get_word(fp)) != (char *)EOF) && wd)
319		;
320		goto next;
321	}
322	this = ns(wd);
323	val = get_word(fp);
324	if (val == (char *)EOF)
325		return;
326	if (val == 0) {
327		char *s = ns(this);
328		(void) snprintf(genopt, sizeof genopt, "opt_%s.h", lower(s));
329		val = genopt;
330		free(s);
331	}
332	val = ns(val);
333
334	for (po = otab ; po != 0; po = po->o_next) {
335		if (eq(po->o_name, this)) {
336			printf("%s: Duplicate option %s.\n",
337			       fname, this);
338			exit(1);
339		}
340	}
341
342	po = (struct opt_list *) malloc(sizeof *po);
343	bzero(po, sizeof(*po));
344	po->o_name = this;
345	po->o_file = val;
346	po->o_next = otab;
347	otab = po;
348
349	goto next;
350}
351
352static char *
353lower(str)
354	register char *str;
355{
356	register char *cp = str;
357
358	while (*str) {
359		if (isupper(*str))
360			*str = tolower(*str);
361		str++;
362	}
363	return (cp);
364}
365
366