xref: /dragonfly/usr.sbin/config/mkoptions.c (revision d4ef6694)
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. Neither the name of the University nor the names of its contributors
15  *    may be used to endorse or promote products derived from this software
16  *    without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * @(#)mkheaders.c	8.1 (Berkeley) 6/6/93
31  * $FreeBSD: src/usr.sbin/config/mkoptions.c,v 1.17.2.3 2001/12/13 19:18:01 dillon Exp $
32  */
33 
34 /*
35  * Make all the .h files for the optional entries
36  */
37 
38 #include <ctype.h>
39 #include <err.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <sys/param.h>
43 #include "config.h"
44 #include "y.tab.h"
45 
46 static char *lower(char *);
47 static void read_options(void);
48 static void do_option(char *);
49 static char *tooption(char *);
50 
51 void
52 options(void)
53 {
54 	char buf[40];
55 	struct cputype *cp;
56 	struct opt_list *ol;
57 	struct opt *op;
58 
59 	/* Fake the cpu types as options. */
60 	for (cp = cputype; cp != NULL; cp = cp->cpu_next) {
61 		op = malloc(sizeof(*op));
62 		bzero(op, sizeof(*op));
63 		op->op_name = strdup(cp->cpu_name);
64 		op->op_next = opt;
65 		opt = op;
66 	}
67 
68 	if (maxusers == 0) {
69 		/* printf("maxusers not specified; will auto-size\n"); */
70 		/* maxusers = 0; */
71 	} else if (maxusers < 2) {
72 		puts("minimum of 2 maxusers assumed");
73 		maxusers = 2;
74 	} else if (maxusers > 512) {
75 		printf("warning: maxusers > 512 (%d)\n", maxusers);
76 	}
77 
78 	/* Fake MAXUSERS as an option. */
79 	op = malloc(sizeof(*op));
80 	bzero(op, sizeof(*op));
81 	op->op_name = strdup("MAXUSERS");
82 	snprintf(buf, sizeof(buf), "%d", maxusers);
83 	op->op_value = strdup(buf);
84 	op->op_next = opt;
85 	opt = op;
86 
87 	read_options();
88 	for (ol = otab; ol != NULL; ol = ol->o_next)
89 		do_option(ol->o_name);
90 	for (op = opt; op != NULL; op = op->op_next) {
91 		if (!op->op_ownfile) {
92 			printf("%s:%d: unknown option \"%s\"\n",
93 			       PREFIX, op->op_line, op->op_name);
94 			exit(1);
95 		}
96 	}
97 }
98 
99 /*
100  * Generate an <options>.h file
101  */
102 
103 static void
104 do_option(char *name)
105 {
106 	const char *basefile, *file;
107 	char *inw;
108 	struct opt_list *ol;
109 	struct opt *op, *op_head, *topp;
110 	FILE *inf, *outf;
111 	char *value;
112 	char *oldvalue;
113 	int seen;
114 	int tidy;
115 
116 	file = tooption(name);
117 
118 	/*
119 	 * Check to see if the option was specified..
120 	 */
121 	value = NULL;
122 	for (op = opt; op != NULL; op = op->op_next) {
123 		if (strcmp(name, op->op_name) == 0) {
124 			oldvalue = value;
125 			value = op->op_value;
126 			if (value == NULL)
127 				value = strdup("1");
128 			if (oldvalue != NULL && strcmp(value, oldvalue) != 0)
129 				printf(
130 			    "%s:%d: option \"%s\" redefined from %s to %s\n",
131 				   PREFIX, op->op_line, op->op_name, oldvalue,
132 				   value);
133 			op->op_ownfile++;
134 		}
135 	}
136 
137 	inf = fopen(file, "r");
138 	if (inf == NULL) {
139 		outf = fopen(file, "w");
140 		if (outf == NULL)
141 			err(1, "%s", file);
142 
143 		/* was the option in the config file? */
144 		if (value) {
145 			fprintf(outf, "#define %s %s\n", name, value);
146 		} /* else empty file */
147 
148 		fclose(outf);
149 		return;
150 	}
151 	basefile = "";
152 	for (ol = otab; ol != NULL; ol = ol->o_next)
153 		if (strcmp(name, ol->o_name) == 0) {
154 			basefile = ol->o_file;
155 			break;
156 		}
157 	oldvalue = NULL;
158 	op_head = NULL;
159 	seen = 0;
160 	tidy = 0;
161 	for (;;) {
162 		char *cp;
163 		char *invalue;
164 
165 		/* get the #define */
166 		if ((inw = get_word(inf)) == NULL || inw == (char *)EOF)
167 			break;
168 		/* get the option name */
169 		if ((inw = get_word(inf)) == NULL || inw == (char *)EOF)
170 			break;
171 		inw = strdup(inw);
172 		/* get the option value */
173 		if ((cp = get_word(inf)) == NULL || cp == (char *)EOF)
174 			break;
175 		/* option value */
176 		invalue = strdup(cp); /* malloced */
177 		if (strcmp(inw, name) == 0) {
178 			oldvalue = invalue;
179 			invalue = value;
180 			seen++;
181 		}
182 		for (ol = otab; ol != NULL; ol = ol->o_next)
183 			if (strcmp(inw, ol->o_name) == 0)
184 				break;
185 		if (strcmp(inw, name) != 0 && ol == NULL) {
186 			printf("WARNING: unknown option `%s' removed from %s\n",
187 				inw, file);
188 			tidy++;
189 		} else if (ol != NULL && strcmp(basefile, ol->o_file) != 0) {
190 			printf("WARNING: option `%s' moved from %s to %s\n",
191 				inw, basefile, ol->o_file);
192 			tidy++;
193 		} else {
194 			op = malloc(sizeof(*op));
195 			bzero(op, sizeof(*op));
196 			op->op_name = inw;
197 			op->op_value = invalue;
198 			op->op_next = op_head;
199 			op_head = op;
200 		}
201 
202 		/* EOL? */
203 		cp = get_word(inf);
204 		if (cp == (char *)EOF)
205 			break;
206 	}
207 	fclose(inf);
208 	if (!tidy && ((value == NULL && oldvalue == NULL) ||
209 	    (value && oldvalue && strcmp(value, oldvalue) == 0))) {
210 		for (op = op_head; op != NULL; op = topp) {
211 			topp = op->op_next;
212 			free(op->op_name);
213 			free(op->op_value);
214 			free(op);
215 		}
216 		return;
217 	}
218 
219 	if (value != NULL && !seen) {
220 		/* New option appears */
221 		op = malloc(sizeof(*op));
222 		bzero(op, sizeof(*op));
223 		op->op_name = strdup(name);
224 		op->op_value = value != NULL ? strdup(value) : NULL;
225 		op->op_next = op_head;
226 		op_head = op;
227 	}
228 
229 	outf = fopen(file, "w");
230 	if (outf == NULL)
231 		err(1, "%s", file);
232 	for (op = op_head; op != NULL; op = topp) {
233 		/* was the option in the config file? */
234 		if (op->op_value != NULL) {
235 			fprintf(outf, "#define %s %s\n",
236 				op->op_name, op->op_value);
237 		}
238 		topp = op->op_next;
239 		free(op->op_name);
240 		free(op->op_value);
241 		free(op);
242 	}
243 	fclose(outf);
244 }
245 
246 /*
247  * Find the filename to store the option spec into.
248  */
249 static char *
250 tooption(char *name)
251 {
252 	static char hbuf[MAXPATHLEN];
253 	char nbuf[MAXPATHLEN];
254 	struct opt_list *po;
255 
256 	/* "cannot happen"?  the otab list should be complete.. */
257 	strlcpy(nbuf, "options.h", sizeof(nbuf));
258 
259 	for (po = otab ; po != NULL; po = po->o_next) {
260 		if (strcmp(po->o_name, name) == 0) {
261 			strlcpy(nbuf, po->o_file, sizeof(nbuf));
262 			break;
263 		}
264 	}
265 
266 	strlcpy(hbuf, path(nbuf), sizeof(hbuf));
267 	return(hbuf);
268 }
269 
270 /*
271  * read the options and options.<machine> files
272  */
273 static void
274 read_options(void)
275 {
276 	FILE *fp;
277 	char fname[MAXPATHLEN];
278 	char *wd, *this, *val;
279 	struct opt_list *po;
280 	int first = 1;
281 	char genopt[MAXPATHLEN];
282 
283 	otab = NULL;
284 	if (ident == NULL) {
285 		printf("no ident line specified\n");
286 		exit(1);
287 	}
288 	snprintf(fname, sizeof(fname), "../conf/options");
289 openit:
290 	fp = fopen(fname, "r");
291 	if (fp == NULL) {
292 		return;
293 	}
294 next:
295 	wd = get_word(fp);
296 	if (wd == (char *)EOF) {
297 		fclose(fp);
298 		if (first == 1) {
299 			first++;
300 			snprintf(fname, sizeof(fname),
301 				 "../platform/%s/conf/options",
302 				 platformname);
303 			fp = fopen(fname, "r");
304 			if (fp != NULL)
305 				goto next;
306 			snprintf(fname, sizeof(fname), "options.%s",
307 				 platformname);
308 			goto openit;
309 		}
310 		if (first == 2) {
311 			first++;
312 			snprintf(fname, sizeof(fname), "options.%s", raisestr(ident));
313 			fp = fopen(fname, "r");
314 			if (fp != NULL)
315 				goto next;
316 		}
317 		return;
318 	}
319 	if (wd == NULL)
320 		goto next;
321 	if (wd[0] == '#')
322 	{
323 		while (((wd = get_word(fp)) != (char *)EOF) && wd != NULL)
324 			;
325 		goto next;
326 	}
327 	this = strdup(wd);
328 	val = get_word(fp);
329 	if (val == (char *)EOF)
330 		return;
331 	if (val == NULL) {
332 		char *s;
333 
334 		s = strdup(this);
335 		snprintf(genopt, sizeof(genopt), "opt_%s.h", lower(s));
336 		val = genopt;
337 		free(s);
338 	}
339 	val = strdup(val);
340 
341 	for (po = otab; po != NULL; po = po->o_next) {
342 		if (strcmp(po->o_name, this) == 0) {
343 			printf("%s: Duplicate option %s.\n",
344 			       fname, this);
345 			exit(1);
346 		}
347 	}
348 
349 	po = malloc(sizeof(*po));
350 	bzero(po, sizeof(*po));
351 	po->o_name = this;
352 	po->o_file = val;
353 	po->o_next = otab;
354 	otab = po;
355 
356 	goto next;
357 }
358 
359 static char *
360 lower(char *str)
361 {
362 	char *cp = str;
363 
364 	while (*str) {
365 		if (isupper(*str))
366 			*str = tolower(*str);
367 		str++;
368 	}
369 	return(cp);
370 }
371 
372