xref: /freebsd/usr.sbin/config/config.y (revision 1e413cf93298b5b97441a21d9a50fdcd0ee9945e)
1 %union {
2 	char	*str;
3 	int	val;
4 	struct	file_list *file;
5 }
6 
7 %token	ARCH
8 %token	COMMA
9 %token	CONFIG
10 %token	CPU
11 %token	NOCPU
12 %token	DEVICE
13 %token	NODEVICE
14 %token	ENV
15 %token	EQUALS
16 %token	HINTS
17 %token	IDENT
18 %token	MAXUSERS
19 %token	PROFILE
20 %token	OPTIONS
21 %token	NOOPTION
22 %token	MAKEOPTIONS
23 %token	NOMAKEOPTION
24 %token	SEMICOLON
25 %token	INCLUDE
26 %token	FILES
27 
28 %token	<str>	ID
29 %token	<val>	NUMBER
30 
31 %type	<str>	Save_id
32 %type	<str>	Opt_value
33 %type	<str>	Dev
34 
35 %{
36 
37 /*
38  * Copyright (c) 1988, 1993
39  *	The Regents of the University of California.  All rights reserved.
40  *
41  * Redistribution and use in source and binary forms, with or without
42  * modification, are permitted provided that the following conditions
43  * are met:
44  * 1. Redistributions of source code must retain the above copyright
45  *    notice, this list of conditions and the following disclaimer.
46  * 2. Redistributions in binary form must reproduce the above copyright
47  *    notice, this list of conditions and the following disclaimer in the
48  *    documentation and/or other materials provided with the distribution.
49  * 3. All advertising materials mentioning features or use of this software
50  *    must display the following acknowledgement:
51  *	This product includes software developed by the University of
52  *	California, Berkeley and its contributors.
53  * 4. Neither the name of the University nor the names of its contributors
54  *    may be used to endorse or promote products derived from this software
55  *    without specific prior written permission.
56  *
57  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
58  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
59  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
60  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
61  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
62  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
63  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
64  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
65  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
66  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
67  * SUCH DAMAGE.
68  *
69  *	@(#)config.y	8.1 (Berkeley) 6/6/93
70  * $FreeBSD$
71  */
72 
73 #include <assert.h>
74 #include <ctype.h>
75 #include <err.h>
76 #include <stdio.h>
77 #include <string.h>
78 
79 #include "config.h"
80 
81 struct	device_head dtab;
82 char	*ident;
83 char	*env;
84 int	envmode;
85 int	hintmode;
86 int	yyline;
87 const	char *yyfile;
88 struct  file_list_head ftab;
89 struct  files_name_head fntab;
90 char	errbuf[80];
91 int	maxusers;
92 
93 #define ns(s)	strdup(s)
94 int include(const char *, int);
95 void yyerror(const char *s);
96 int yywrap(void);
97 
98 static void newdev(char *name);
99 static void newfile(char *name);
100 static void rmdev_schedule(struct device_head *dh, char *name);
101 static void newopt(struct opt_head *list, char *name, char *value);
102 static void rmopt_schedule(struct opt_head *list, char *name);
103 
104 static char *
105 devopt(char *dev)
106 {
107 	char *ret = malloc(strlen(dev) + 5);
108 
109 	sprintf(ret, "DEV_%s", dev);
110 	raisestr(ret);
111 	return ret;
112 }
113 
114 %}
115 %%
116 Configuration:
117 	Many_specs
118 		;
119 
120 Many_specs:
121 	Many_specs Spec
122 		|
123 	/* lambda */
124 		;
125 
126 Spec:
127 	Device_spec SEMICOLON
128 		|
129 	Config_spec SEMICOLON
130 		|
131 	INCLUDE ID SEMICOLON {
132 	          if (incignore == 0)
133 		  	include($2, 0);
134 		};
135 		|
136 	FILES ID SEMICOLON { newfile($2); };
137 	        |
138 	SEMICOLON
139 		|
140 	error SEMICOLON
141 		;
142 
143 Config_spec:
144 	ARCH Save_id {
145 		if (machinename != NULL && !eq($2, machinename))
146 		    errx(1, "%s:%d: only one machine directive is allowed",
147 			yyfile, yyline);
148 		machinename = $2;
149 		machinearch = $2;
150 	      } |
151 	ARCH Save_id Save_id {
152 		if (machinename != NULL &&
153 		    !(eq($2, machinename) && eq($3, machinearch)))
154 		    errx(1, "%s:%d: only one machine directive is allowed",
155 			yyfile, yyline);
156 		machinename = $2;
157 		machinearch = $3;
158 	      } |
159 	CPU Save_id {
160 		struct cputype *cp =
161 		    (struct cputype *)calloc(1, sizeof (struct cputype));
162 		cp->cpu_name = $2;
163 		SLIST_INSERT_HEAD(&cputype, cp, cpu_next);
164 	      } |
165 	NOCPU Save_id {
166 		struct cputype *cp, *cp2;
167 		SLIST_FOREACH_SAFE(cp, &cputype, cpu_next, cp2) {
168 			if (eq(cp->cpu_name, $2)) {
169 				SLIST_REMOVE(&cputype, cp, cputype, cpu_next);
170 				free(cp);
171 			}
172 		}
173 	      } |
174 	OPTIONS Opt_list
175 		|
176 	NOOPTION Save_id { rmopt_schedule(&opt, $2); } |
177 	MAKEOPTIONS Mkopt_list
178 		|
179 	NOMAKEOPTION Save_id { rmopt_schedule(&mkopt, $2); } |
180 	IDENT ID { ident = $2; } |
181 	System_spec
182 		|
183 	MAXUSERS NUMBER { maxusers = $2; } |
184 	PROFILE NUMBER { profiling = $2; } |
185 	ENV ID {
186 		env = $2;
187 		envmode = 1;
188 		} |
189 	HINTS ID {
190 		struct hint *hint;
191 
192 		hint = (struct hint *)calloc(1, sizeof (struct hint));
193 		hint->hint_name = $2;
194 		STAILQ_INSERT_TAIL(&hints, hint, hint_next);
195 		hintmode = 1;
196 	        }
197 
198 System_spec:
199 	CONFIG System_id System_parameter_list {
200 		errx(1, "%s:%d: root/dump/swap specifications obsolete",
201 		      yyfile, yyline);
202 		}
203 	  |
204 	CONFIG System_id
205 	  ;
206 
207 System_id:
208 	Save_id { newopt(&mkopt, ns("KERNEL"), $1); };
209 
210 System_parameter_list:
211 	  System_parameter_list ID
212 	| ID
213 	;
214 
215 Opt_list:
216 	Opt_list COMMA Option
217 		|
218 	Option
219 		;
220 
221 Option:
222 	Save_id {
223 		newopt(&opt, $1, NULL);
224 		if (strchr($1, '=') != NULL)
225 			errx(1, "%s:%d: The `=' in options should not be "
226 			    "quoted", yyfile, yyline);
227 	      } |
228 	Save_id EQUALS Opt_value {
229 		newopt(&opt, $1, $3);
230 	      } ;
231 
232 Opt_value:
233 	ID { $$ = $1; } |
234 	NUMBER {
235 			char buf[80];
236 
237 			(void) snprintf(buf, sizeof(buf), "%d", $1);
238 			$$ = ns(buf);
239 		} ;
240 
241 Save_id:
242 	ID { $$ = $1; }
243 	;
244 
245 Mkopt_list:
246 	Mkopt_list COMMA Mkoption
247 		|
248 	Mkoption
249 		;
250 
251 Mkoption:
252 	Save_id { newopt(&mkopt, $1, ns("")); } |
253 	Save_id EQUALS Opt_value { newopt(&mkopt, $1, $3); } ;
254 
255 Dev:
256 	ID { $$ = $1; }
257 	;
258 
259 Device_spec:
260 	DEVICE Dev_list
261 		|
262 	NODEVICE NoDev_list
263 		;
264 
265 Dev_list:
266 	Dev_list COMMA Device
267 		|
268 	Device
269 		;
270 
271 NoDev_list:
272 	NoDev_list COMMA NoDevice
273 		|
274 	NoDevice
275 		;
276 
277 Device:
278 	Dev {
279 		newopt(&opt, devopt($1), ns("1"));
280 		/* and the device part */
281 		newdev($1);
282 		}
283 
284 NoDevice:
285 	Dev {
286 		char *s = devopt($1);
287 
288 		rmopt_schedule(&opt, s);
289 		free(s);
290 		/* and the device part */
291 		rmdev_schedule(&dtab, $1);
292 		} ;
293 
294 %%
295 
296 void
297 yyerror(const char *s)
298 {
299 
300 	errx(1, "%s:%d: %s", yyfile, yyline + 1, s);
301 }
302 
303 int
304 yywrap(void)
305 {
306 	if (found_defaults) {
307 		if (freopen(PREFIX, "r", stdin) == NULL)
308 			err(2, "%s", PREFIX);
309 		yyfile = PREFIX;
310 		yyline = 0;
311 		found_defaults = 0;
312 		return 0;
313 	}
314 	return 1;
315 }
316 
317 /*
318  * Add a new file to the list of files.
319  */
320 static void
321 newfile(char *name)
322 {
323 	struct files_name *nl;
324 
325 	nl = (struct files_name *) calloc(1, sizeof *nl);
326 	nl->f_name = name;
327 	STAILQ_INSERT_TAIL(&fntab, nl, f_next);
328 }
329 
330 /*
331  * Find a device in the list of devices.
332  */
333 static struct device *
334 finddev(struct device_head *dlist, char *name)
335 {
336 	struct device *dp;
337 
338 	STAILQ_FOREACH(dp, dlist, d_next)
339 		if (eq(dp->d_name, name))
340 			return (dp);
341 
342 	return (NULL);
343 }
344 
345 /*
346  * Add a device to the list of devices.
347  */
348 static void
349 newdev(char *name)
350 {
351 	struct device *np;
352 
353 	if (finddev(&dtab, name)) {
354 		printf("WARNING: duplicate device `%s' encountered.\n", name);
355 		return;
356 	}
357 
358 	np = (struct device *) calloc(1, sizeof *np);
359 	np->d_name = name;
360 	STAILQ_INSERT_TAIL(&dtab, np, d_next);
361 }
362 
363 /*
364  * Schedule a device to removal.
365  */
366 static void
367 rmdev_schedule(struct device_head *dh, char *name)
368 {
369 	struct device *dp;
370 
371 	dp = finddev(dh, name);
372 	if (dp != NULL) {
373 		STAILQ_REMOVE(dh, dp, device, d_next);
374 		free(dp->d_name);
375 		free(dp);
376 	}
377 }
378 
379 /*
380  * Find an option in the list of options.
381  */
382 static struct opt *
383 findopt(struct opt_head *list, char *name)
384 {
385 	struct opt *op;
386 
387 	SLIST_FOREACH(op, list, op_next)
388 		if (eq(op->op_name, name))
389 			return (op);
390 
391 	return (NULL);
392 }
393 
394 /*
395  * Add an option to the list of options.
396  */
397 static void
398 newopt(struct opt_head *list, char *name, char *value)
399 {
400 	struct opt *op;
401 
402 	/*
403 	 * Ignore inclusions listed explicitly for configuration files.
404 	 */
405 	if (eq(name, OPT_AUTOGEN)) {
406 		incignore = 1;
407 		return;
408 	}
409 
410 	if (findopt(list, name)) {
411 		printf("WARNING: duplicate option `%s' encountered.\n", name);
412 		return;
413 	}
414 
415 	op = (struct opt *)calloc(1, sizeof (struct opt));
416 	op->op_name = name;
417 	op->op_ownfile = 0;
418 	op->op_value = value;
419 	SLIST_INSERT_HEAD(list, op, op_next);
420 }
421 
422 /*
423  * Remove an option from the list of options.
424  */
425 static void
426 rmopt_schedule(struct opt_head *list, char *name)
427 {
428 	struct opt *op;
429 
430 	op = findopt(list, name);
431 	if (op != NULL) {
432 		SLIST_REMOVE(list, op, opt, op_next);
433 		free(op->op_name);
434 		free(op);
435 	}
436 }
437