1331722Seadler/*
212772Speter * Copyright (c) 1995  Peter Wemm
312772Speter * Copyright (c) 1980, 1993
412772Speter *	The Regents of the University of California.  All rights reserved.
512772Speter *
612772Speter * Redistribution and use in source and binary forms, with or without
712772Speter * modification, are permitted provided that the following conditions
812772Speter * are met:
912772Speter * 1. Redistributions of source code must retain the above copyright
1012772Speter *    notice, this list of conditions and the following disclaimer.
1112772Speter * 2. Redistributions in binary form must reproduce the above copyright
1212772Speter *    notice, this list of conditions and the following disclaimer in the
1312772Speter *    documentation and/or other materials provided with the distribution.
1412772Speter * 4. Neither the name of the University nor the names of its contributors
1512772Speter *    may be used to endorse or promote products derived from this software
1612772Speter *    without specific prior written permission.
1712772Speter *
1812772Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1912772Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2012772Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2112772Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2212772Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2312772Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2412772Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2512772Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2612772Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2712772Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2812772Speter * SUCH DAMAGE.
2912772Speter */
3012772Speter
3112772Speter#ifndef lint
3229451Scharnier#if 0
3312772Speterstatic char sccsid[] = "@(#)mkheaders.c	8.1 (Berkeley) 6/6/93";
3429451Scharnier#endif
3529451Scharnierstatic const char rcsid[] =
3650479Speter  "$FreeBSD$";
3712772Speter#endif /* not lint */
3812772Speter
3912772Speter/*
4012772Speter * Make all the .h files for the optional entries
4112772Speter */
4212772Speter
4329451Scharnier#include <ctype.h>
4429451Scharnier#include <err.h>
4512772Speter#include <stdio.h>
4620458Sjoerg#include <string.h>
4769004Simp#include <sys/param.h>
4812772Speter#include "config.h"
4916073Sphk#include "y.tab.h"
5012772Speter
5137578Sbdestatic	struct users {
5237578Sbde	int	u_default;
5337578Sbde	int	u_min;
5437578Sbde	int	u_max;
55125935Sdes} users = { 8, 2, 512 };
5637578Sbde
5761640Speterstatic char *lower(char *);
5861640Speterstatic void read_options(void);
5961640Speterstatic void do_option(char *);
6061640Speterstatic char *tooption(char *);
6120458Sjoerg
6229451Scharniervoid
6361640Speteroptions(void)
6412772Speter{
6537578Sbde	char buf[40];
6637578Sbde	struct cputype *cp;
6712772Speter	struct opt_list *ol;
6837578Sbde	struct opt *op;
6912772Speter
7037578Sbde	/* Fake the cpu types as options. */
71110895Sru	SLIST_FOREACH(cp, &cputype, cpu_next) {
72159362Sdelphij		op = (struct opt *)calloc(1, sizeof(*op));
73205880Sru		if (op == NULL)
74205880Sru			err(EXIT_FAILURE, "calloc");
7520458Sjoerg		op->op_name = ns(cp->cpu_name);
76110895Sru		SLIST_INSERT_HEAD(&opt, op, op_next);
7712772Speter	}
7812772Speter
7937578Sbde	if (maxusers == 0) {
80210144Simp		/* fprintf(stderr, "maxusers not specified; will auto-size\n"); */
8172000Speter	} else if (maxusers < users.u_min) {
82210144Simp		fprintf(stderr, "minimum of %d maxusers assumed\n",
83210144Simp		    users.u_min);
8472000Speter		maxusers = users.u_min;
8572000Speter	} else if (maxusers > users.u_max)
86210144Simp		fprintf(stderr, "warning: maxusers > %d (%d)\n",
87210144Simp		    users.u_max, maxusers);
8837578Sbde
8937578Sbde	/* Fake MAXUSERS as an option. */
90159362Sdelphij	op = (struct opt *)calloc(1, sizeof(*op));
91205880Sru	if (op == NULL)
92205880Sru		err(EXIT_FAILURE, "calloc");
9372684Speter	op->op_name = ns("MAXUSERS");
9446021Speter	snprintf(buf, sizeof(buf), "%d", maxusers);
9537578Sbde	op->op_value = ns(buf);
96110895Sru	SLIST_INSERT_HEAD(&opt, op, op_next);
9737578Sbde
9812772Speter	read_options();
99209969Snwhitehorn
100209969Snwhitehorn	/* Fake the value of MACHINE_ARCH as an option if necessary */
101209969Snwhitehorn	SLIST_FOREACH(ol, &otab, o_next) {
102209969Snwhitehorn		if (strcasecmp(ol->o_name, machinearch) != 0)
103209969Snwhitehorn			continue;
104209969Snwhitehorn
105209969Snwhitehorn		op = (struct opt *)calloc(1, sizeof(*op));
106209969Snwhitehorn		if (op == NULL)
107209969Snwhitehorn			err(EXIT_FAILURE, "calloc");
108209969Snwhitehorn		op->op_name = ns(ol->o_name);
109209969Snwhitehorn		SLIST_INSERT_HEAD(&opt, op, op_next);
110209969Snwhitehorn		break;
111209969Snwhitehorn	}
112209969Snwhitehorn
113206664Simp	SLIST_FOREACH(op, &opt, op_next) {
114206664Simp		SLIST_FOREACH(ol, &otab, o_next) {
115206664Simp			if (eq(op->op_name, ol->o_name) &&
116206664Simp			    (ol->o_flags & OL_ALIAS)) {
117210144Simp				fprintf(stderr, "Mapping option %s to %s.\n",
118206664Simp				    op->op_name, ol->o_file);
119206664Simp				op->op_name = ol->o_file;
120206664Simp				break;
121206664Simp			}
122206664Simp		}
123206664Simp	}
124110895Sru	SLIST_FOREACH(ol, &otab, o_next)
12512772Speter		do_option(ol->o_name);
126110895Sru	SLIST_FOREACH(op, &opt, op_next) {
12771251Speter		if (!op->op_ownfile && strncmp(op->op_name, "DEV_", 4)) {
128210144Simp			fprintf(stderr, "%s: unknown option \"%s\"\n",
12972841Speter			       PREFIX, op->op_name);
13061523Speter			exit(1);
13161523Speter		}
13261523Speter	}
13312772Speter}
13412772Speter
13512772Speter/*
13612772Speter * Generate an <options>.h file
13712772Speter */
13812772Speter
13945744Speterstatic void
14061640Speterdo_option(char *name)
14112772Speter{
14272684Speter	char *file, *inw;
14372684Speter	const char *basefile;
14448401Speter	struct opt_list *ol;
145110895Sru	struct opt *op;
146110895Sru	struct opt_head op_head;
14712772Speter	FILE *inf, *outf;
14812772Speter	char *value;
14912772Speter	char *oldvalue;
15012772Speter	int seen;
15148401Speter	int tidy;
15212772Speter
15312772Speter	file = tooption(name);
15412772Speter	/*
15512772Speter	 * Check to see if the option was specified..
15612772Speter	 */
15712772Speter	value = NULL;
158110895Sru	SLIST_FOREACH(op, &opt, op_next) {
15912772Speter		if (eq(name, op->op_name)) {
16037577Sbde			oldvalue = value;
16112772Speter			value = op->op_value;
16237577Sbde			if (value == NULL)
16312772Speter				value = ns("1");
16437577Sbde			if (oldvalue != NULL && !eq(value, oldvalue))
165210144Simp				fprintf(stderr,
16672841Speter			    "%s: option \"%s\" redefined from %s to %s\n",
16772841Speter				   PREFIX, op->op_name, oldvalue,
16837577Sbde				   value);
16912772Speter			op->op_ownfile++;
17012772Speter		}
17112772Speter	}
17212772Speter
17371866Speter	remember(file);
17412772Speter	inf = fopen(file, "r");
175298687Saraujo	if (inf == NULL) {
17612772Speter		outf = fopen(file, "w");
177298687Saraujo		if (outf == NULL)
17829451Scharnier			err(1, "%s", file);
17912772Speter
18012772Speter		/* was the option in the config file? */
18112772Speter		if (value) {
18212772Speter			fprintf(outf, "#define %s %s\n", name, value);
18312772Speter		} /* else empty file */
18412772Speter
185207263Simp		(void)fclose(outf);
18612772Speter		return;
18712772Speter	}
18855659Sbde	basefile = "";
189110895Sru	SLIST_FOREACH(ol, &otab, o_next)
19055659Sbde		if (eq(name, ol->o_name)) {
19155659Sbde			basefile = ol->o_file;
19255659Sbde			break;
19355659Sbde		}
19412772Speter	oldvalue = NULL;
195110895Sru	SLIST_INIT(&op_head);
19612772Speter	seen = 0;
19748401Speter	tidy = 0;
19812772Speter	for (;;) {
19912772Speter		char *cp;
20012772Speter		char *invalue;
20112772Speter
20212772Speter		/* get the #define */
203298687Saraujo		if ((inw = get_word(inf)) == NULL || inw == (char *)EOF)
20412772Speter			break;
20512772Speter		/* get the option name */
206298687Saraujo		if ((inw = get_word(inf)) == NULL || inw == (char *)EOF)
20712772Speter			break;
20812772Speter		inw = ns(inw);
20948401Speter		/* get the option value */
210298687Saraujo		if ((cp = get_word(inf)) == NULL || cp == (char *)EOF)
21112772Speter			break;
21212772Speter		/* option value */
21312772Speter		invalue = ns(cp); /* malloced */
21412772Speter		if (eq(inw, name)) {
21512772Speter			oldvalue = invalue;
21612772Speter			invalue = value;
21712772Speter			seen++;
21812772Speter		}
219110895Sru		SLIST_FOREACH(ol, &otab, o_next)
22048401Speter			if (eq(inw, ol->o_name))
22148401Speter				break;
22255603Sbde		if (!eq(inw, name) && !ol) {
223210144Simp			fprintf(stderr,
224210144Simp			    "WARNING: unknown option `%s' removed from %s\n",
225210144Simp			    inw, file);
22648401Speter			tidy++;
22755659Sbde		} else if (ol != NULL && !eq(basefile, ol->o_file)) {
228210144Simp			fprintf(stderr,
229210144Simp			    "WARNING: option `%s' moved from %s to %s\n",
230210144Simp			    inw, basefile, ol->o_file);
23155659Sbde			tidy++;
23248401Speter		} else {
233159362Sdelphij			op = (struct opt *) calloc(1, sizeof *op);
234205880Sru			if (op == NULL)
235205880Sru				err(EXIT_FAILURE, "calloc");
23648401Speter			op->op_name = inw;
23748401Speter			op->op_value = invalue;
238110895Sru			SLIST_INSERT_HEAD(&op_head, op, op_next);
23948401Speter		}
24012772Speter
24112772Speter		/* EOL? */
24212772Speter		cp = get_word(inf);
24312772Speter		if (cp == (char *)EOF)
24412772Speter			break;
24512772Speter	}
246207263Simp	(void)fclose(inf);
24748401Speter	if (!tidy && ((value == NULL && oldvalue == NULL) ||
24848401Speter	    (value && oldvalue && eq(value, oldvalue)))) {
249110895Sru		while (!SLIST_EMPTY(&op_head)) {
250110895Sru			op = SLIST_FIRST(&op_head);
251110895Sru			SLIST_REMOVE_HEAD(&op_head, op_next);
25212772Speter			free(op->op_name);
25312772Speter			free(op->op_value);
25412772Speter			free(op);
25512772Speter		}
25612772Speter		return;
25712772Speter	}
25812772Speter
25912772Speter	if (value && !seen) {
26012772Speter		/* New option appears */
261159362Sdelphij		op = (struct opt *) calloc(1, sizeof *op);
262205880Sru		if (op == NULL)
263205880Sru			err(EXIT_FAILURE, "calloc");
26412772Speter		op->op_name = ns(name);
26512772Speter		op->op_value = value ? ns(value) : NULL;
266110895Sru		SLIST_INSERT_HEAD(&op_head, op, op_next);
26712772Speter	}
26812772Speter
26912772Speter	outf = fopen(file, "w");
270298687Saraujo	if (outf == NULL)
27129451Scharnier		err(1, "%s", file);
272110895Sru	while (!SLIST_EMPTY(&op_head)) {
273110895Sru		op = SLIST_FIRST(&op_head);
27412772Speter		/* was the option in the config file? */
27512772Speter		if (op->op_value) {
27612772Speter			fprintf(outf, "#define %s %s\n",
27712772Speter				op->op_name, op->op_value);
27812772Speter		}
279110895Sru		SLIST_REMOVE_HEAD(&op_head, op_next);
28012772Speter		free(op->op_name);
28112772Speter		free(op->op_value);
28212772Speter		free(op);
28312772Speter	}
284207263Simp	(void)fclose(outf);
28512772Speter}
28612772Speter
28712772Speter/*
28812772Speter * Find the filename to store the option spec into.
28912772Speter */
29045744Speterstatic char *
29161640Spetertooption(char *name)
29212772Speter{
29369004Simp	static char hbuf[MAXPATHLEN];
29469004Simp	char nbuf[MAXPATHLEN];
29512772Speter	struct opt_list *po;
29612772Speter
29712772Speter	/* "cannot happen"?  the otab list should be complete.. */
298207263Simp	(void)strlcpy(nbuf, "options.h", sizeof(nbuf));
29912772Speter
300110895Sru	SLIST_FOREACH(po, &otab, o_next) {
30112772Speter		if (eq(po->o_name, name)) {
30269004Simp			strlcpy(nbuf, po->o_file, sizeof(nbuf));
30312772Speter			break;
30412772Speter		}
30512772Speter	}
30612772Speter
307207263Simp	(void)strlcpy(hbuf, path(nbuf), sizeof(hbuf));
30812772Speter	return (hbuf);
30912772Speter}
31012772Speter
311207263Simp
31245744Speterstatic void
313207265Simpcheck_duplicate(const char *fname, const char *this)
31412772Speter{
315207263Simp	struct opt_list *po;
316207263Simp
317207265Simp	SLIST_FOREACH(po, &otab, o_next) {
318207265Simp		if (eq(po->o_name, this)) {
319210144Simp			fprintf(stderr, "%s: Duplicate option %s.\n",
320210144Simp			    fname, this);
321207265Simp			exit(1);
322207265Simp		}
323207265Simp	}
324207265Simp}
325207265Simp
326207265Simpstatic void
327207265Simpinsert_option(const char *fname, char *this, char *val)
328207265Simp{
329207265Simp	struct opt_list *po;
330207265Simp
331207265Simp	check_duplicate(fname, this);
332207263Simp	po = (struct opt_list *) calloc(1, sizeof *po);
333207263Simp	if (po == NULL)
334207263Simp		err(EXIT_FAILURE, "calloc");
335207263Simp	po->o_name = this;
336207263Simp	po->o_file = val;
337207265Simp	po->o_flags = 0;
338207263Simp	SLIST_INSERT_HEAD(&otab, po, o_next);
339207263Simp}
340207263Simp
341207263Simpstatic void
342207265Simpupdate_option(const char *this, char *val, int flags)
343207263Simp{
344207263Simp	struct opt_list *po;
345207263Simp
346207263Simp	SLIST_FOREACH(po, &otab, o_next) {
347207263Simp		if (eq(po->o_name, this)) {
348207265Simp			free(po->o_file);
349207265Simp			po->o_file = val;
350207265Simp			po->o_flags = flags;
351207265Simp			return;
352207263Simp		}
353207263Simp	}
354211325Simp	/*
355211325Simp	 * Option not found, but that's OK, we just ignore it since it
356211325Simp	 * may be for another arch.
357211325Simp	 */
358211325Simp	return;
359207263Simp}
360207263Simp
361207263Simpstatic int
362207263Simpread_option_file(const char *fname, int flags)
363207263Simp{
36412772Speter	FILE *fp;
36512772Speter	char *wd, *this, *val;
36669004Simp	char genopt[MAXPATHLEN];
36712772Speter
36812772Speter	fp = fopen(fname, "r");
369298687Saraujo	if (fp == NULL)
370207263Simp		return (0);
371207263Simp	while ((wd = get_word(fp)) != (char *)EOF) {
372298687Saraujo		if (wd == NULL)
373207263Simp			continue;
374207263Simp		if (wd[0] == '#') {
375207263Simp			while (((wd = get_word(fp)) != (char *)EOF) && wd)
376207263Simp				continue;
377207263Simp			continue;
37812772Speter		}
379207263Simp		this = ns(wd);
380206664Simp		val = get_word(fp);
381207263Simp		if (val == (char *)EOF)
382207263Simp			return (1);
383298687Saraujo		if (val == NULL) {
384207263Simp			if (flags) {
385210144Simp				fprintf(stderr, "%s: compat file requires two"
386210144Simp				    " words per line at %s\n", fname, this);
387207263Simp				exit(1);
388207263Simp			}
389207263Simp			char *s = ns(this);
390207263Simp			(void)snprintf(genopt, sizeof(genopt), "opt_%s.h",
391207263Simp			    lower(s));
392207263Simp			val = genopt;
393207263Simp			free(s);
394206664Simp		}
395207263Simp		val = ns(val);
396207265Simp		if (flags == 0)
397207265Simp			insert_option(fname, this, val);
398207265Simp		else
399207265Simp			update_option(this, val, flags);
40012772Speter	}
401207263Simp	(void)fclose(fp);
402207263Simp	return (1);
403207263Simp}
40412772Speter
405207263Simp/*
406207263Simp * read the options and options.<machine> files
407207263Simp */
408207263Simpstatic void
409207263Simpread_options(void)
410207263Simp{
411207263Simp	char fname[MAXPATHLEN];
412207263Simp
413207263Simp	SLIST_INIT(&otab);
414207263Simp	read_option_file("../../conf/options", 0);
415207263Simp	(void)snprintf(fname, sizeof fname, "../../conf/options.%s",
416207263Simp	    machinename);
417207263Simp	if (!read_option_file(fname, 0)) {
418207263Simp		(void)snprintf(fname, sizeof fname, "options.%s", machinename);
419207263Simp		read_option_file(fname, 0);
42012772Speter	}
421207263Simp	read_option_file("../../conf/options-compat", OL_ALIAS);
42212772Speter}
42312772Speter
42420458Sjoergstatic char *
42561640Speterlower(char *str)
42612772Speter{
42761640Speter	char *cp = str;
42812772Speter
42912772Speter	while (*str) {
43012772Speter		if (isupper(*str))
43112772Speter			*str = tolower(*str);
43212772Speter		str++;
43312772Speter	}
43412772Speter	return (cp);
43512772Speter}
436