mkoptions.c revision 29451
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$";
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	char *lower __P((char *));
57void read_options __P((void));
58void do_option __P((char *));
59
60void
61options()
62{
63	struct opt_list *ol;
64
65	/* fake the cpu types as options */
66	/* Please forgive me for this hack.. :-) */
67	struct cputype *cp;
68
69	for (cp = cputype; cp; cp = cp->cpu_next) {
70		struct opt *op = (struct opt *)malloc(sizeof (struct opt));
71		memset(op, 0, sizeof(*op));
72		op->op_name = ns(cp->cpu_name);
73		op->op_value = 0;
74		op->op_next = opt;
75		opt = op;
76	}
77
78	read_options();
79	for (ol = otab; ol != 0; ol = ol->o_next)
80		do_option(ol->o_name);
81}
82
83/*
84 * Generate an <options>.h file
85 */
86
87void
88do_option(name)
89	char *name;
90{
91	char *file, *inw, *tooption();
92	struct opt *op, *op_head, *topp;
93	FILE *inf, *outf;
94	char *value;
95	char *oldvalue;
96	int seen;
97
98	file = tooption(name);
99
100	/*
101	 * Check to see if the option was specified..
102	 */
103	value = NULL;
104	for (op = opt; op; op = op->op_next) {
105		if (eq(name, op->op_name)) {
106			value = op->op_value;
107			if (!value)
108				value = ns("1");
109			op->op_ownfile++;
110		}
111	}
112
113	inf = fopen(file, "r");
114	if (inf == 0) {
115		outf = fopen(file, "w");
116		if (outf == 0)
117			err(1, "%s", file);
118
119		/* was the option in the config file? */
120		if (value) {
121			fprintf(outf, "#define %s %s\n", name, value);
122		} /* else empty file */
123
124		(void) fclose(outf);
125		return;
126	}
127	oldvalue = NULL;
128	op_head = NULL;
129	seen = 0;
130	for (;;) {
131		char *cp;
132		char *invalue;
133
134		/* get the #define */
135		if ((inw = get_word(inf)) == 0 || inw == (char *)EOF)
136			break;
137		/* get the option name */
138		if ((inw = get_word(inf)) == 0 || inw == (char *)EOF)
139			break;
140		inw = ns(inw);
141		cp = get_word(inf);
142		if (cp == 0 || cp == (char *)EOF)
143			break;
144		/* option value */
145		invalue = ns(cp); /* malloced */
146		if (eq(inw, name)) {
147			oldvalue = invalue;
148			invalue = value;
149			seen++;
150		}
151		op = (struct opt *) malloc(sizeof *op);
152		bzero(op, sizeof(*op));
153		op->op_name = inw;
154		op->op_value = invalue;
155		op->op_next = op_head;
156		op_head = op;
157
158		/* EOL? */
159		cp = get_word(inf);
160		if (cp == (char *)EOF)
161			break;
162	}
163	(void) fclose(inf);
164	if ((value == NULL && oldvalue == NULL) ||
165	    (value && oldvalue && eq(value,oldvalue))) {
166		for (op = op_head; op != NULL; op = topp) {
167			topp = op->op_next;
168			free(op->op_name);
169			free(op->op_value);
170			free(op);
171		}
172		return;
173	}
174
175	if (value && !seen) {
176		/* New option appears */
177		op = (struct opt *) malloc(sizeof *op);
178		bzero(op, sizeof(*op));
179		op->op_name = ns(name);
180		op->op_value = value ? ns(value) : NULL;
181		op->op_next = op_head;
182		op_head = op;
183	}
184
185	outf = fopen(file, "w");
186	if (outf == 0)
187		err(1, "%s", file);
188	for (op = op_head; op != NULL; op = topp) {
189		/* was the option in the config file? */
190		if (op->op_value) {
191			fprintf(outf, "#define %s %s\n",
192				op->op_name, op->op_value);
193		}
194		topp = op->op_next;
195		free(op->op_name);
196		free(op->op_value);
197		free(op);
198	}
199	(void) fclose(outf);
200}
201
202/*
203 * Find the filename to store the option spec into.
204 */
205char *
206tooption(name)
207	char *name;
208{
209	static char hbuf[80];
210	char nbuf[80];
211	struct opt_list *po;
212
213	/* "cannot happen"?  the otab list should be complete.. */
214	(void) strcpy(nbuf, "options.h");
215
216	for (po = otab ; po != 0; po = po->o_next) {
217		if (eq(po->o_name, name)) {
218			strcpy(nbuf, po->o_file);
219			break;
220		}
221	}
222
223	(void) strcpy(hbuf, path(nbuf));
224	return (hbuf);
225}
226
227/*
228 * read the options and options.<machine> files
229 */
230void
231read_options()
232{
233	FILE *fp;
234	char fname[80];
235	char *wd, *this, *val;
236	struct opt_list *po;
237	int first = 1;
238	char genopt[80];
239
240	otab = 0;
241	(void) snprintf(fname, sizeof fname, "../../conf/options");
242openit:
243	fp = fopen(fname, "r");
244	if (fp == 0) {
245		return;
246	}
247	if(ident == NULL) {
248		printf("no ident line specified\n");
249		exit(1);
250	}
251next:
252	wd = get_word(fp);
253	if (wd == (char *)EOF) {
254		(void) fclose(fp);
255		if (first == 1) {
256			(void) snprintf(fname, sizeof fname, "options.%s", machinename);
257			first++;
258			goto openit;
259		}
260		if (first == 2) {
261			(void) snprintf(fname, sizeof fname, "options.%s", raise(ident));
262			first++;
263			fp = fopen(fname, "r");
264			if (fp != 0)
265				goto next;
266		}
267		return;
268	}
269	if (wd == 0)
270		goto next;
271	/*************************************************\
272	* If it's a comment ignore to the end of the line *
273	\*************************************************/
274	if(wd[0] == '#')
275	{
276		while( ((wd = get_word(fp)) != (char *)EOF) && wd)
277		;
278		goto next;
279	}
280	this = ns(wd);
281	val = get_word(fp);
282	if (val == (char *)EOF)
283		return;
284	if (val == 0) {
285		char *s = ns(this);
286		(void) snprintf(genopt, sizeof genopt, "opt_%s.h", lower(s));
287		val = genopt;
288		free(s);
289	}
290	val = ns(val);
291
292	for (po = otab ; po != 0; po = po->o_next) {
293		if (eq(po->o_name, this)) {
294			printf("%s: Duplicate option %s.\n",
295			       fname, this);
296			exit(1);
297		}
298	}
299
300	po = (struct opt_list *) malloc(sizeof *po);
301	bzero(po, sizeof(*po));
302	po->o_name = this;
303	po->o_file = val;
304	po->o_next = otab;
305	otab = po;
306
307	goto next;
308}
309
310static char *
311lower(str)
312	register char *str;
313{
314	register char *cp = str;
315
316	while (*str) {
317		if (isupper(*str))
318			*str = tolower(*str);
319		str++;
320	}
321	return (cp);
322}
323
324