xref: /freebsd/usr.sbin/config/config.y (revision 7bd6fde3)
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 <ctype.h>
74 #include <err.h>
75 #include <stdio.h>
76 #include <string.h>
77 
78 #include "config.h"
79 
80 struct	device_head dtab;
81 char	*ident;
82 char	*env;
83 int	envmode;
84 int	hintmode;
85 int	yyline;
86 const	char *yyfile;
87 struct  file_list_head ftab;
88 struct  files_name_head fntab;
89 char	errbuf[80];
90 int	maxusers;
91 
92 #define ns(s)	strdup(s)
93 int include(const char *, int);
94 void yyerror(const char *s);
95 int yywrap(void);
96 
97 static char *
98 devopt(char *dev)
99 {
100 	char *ret = malloc(strlen(dev) + 5);
101 
102 	sprintf(ret, "DEV_%s", dev);
103 	raisestr(ret);
104 	return ret;
105 }
106 
107 %}
108 %%
109 Configuration:
110 	Many_specs
111 		;
112 
113 Many_specs:
114 	Many_specs Spec
115 		|
116 	/* lambda */
117 		;
118 
119 Spec:
120 	Device_spec SEMICOLON
121 		|
122 	Config_spec SEMICOLON
123 		|
124 	INCLUDE ID SEMICOLON
125 	      = { include($2, 0); };
126 		|
127 	FILES ID SEMICOLON
128 	      = { newfile($2); };
129 	        |
130 	SEMICOLON
131 		|
132 	error SEMICOLON
133 		;
134 
135 Config_spec:
136 	ARCH Save_id
137 	    = {
138 		if (machinename != NULL && !eq($2, machinename))
139 		    errx(1, "%s:%d: only one machine directive is allowed",
140 			yyfile, yyline);
141 		machinename = $2;
142 		machinearch = $2;
143 	      } |
144 	ARCH Save_id Save_id
145 	    = {
146 		if (machinename != NULL &&
147 		    !(eq($2, machinename) && eq($3, machinearch)))
148 		    errx(1, "%s:%d: only one machine directive is allowed",
149 			yyfile, yyline);
150 		machinename = $2;
151 		machinearch = $3;
152 	      } |
153 	CPU Save_id
154 	      = {
155 		struct cputype *cp =
156 		    (struct cputype *)calloc(1, sizeof (struct cputype));
157 		cp->cpu_name = $2;
158 		SLIST_INSERT_HEAD(&cputype, cp, cpu_next);
159 	      } |
160 	NOCPU Save_id
161 	      = {
162 		struct cputype *cp, *cp2;
163 		SLIST_FOREACH_SAFE(cp, &cputype, cpu_next, cp2) {
164 			if (eq(cp->cpu_name, $2)) {
165 				SLIST_REMOVE(&cputype, cp, cputype, cpu_next);
166 				free(cp);
167 			}
168 		}
169 	      } |
170 	OPTIONS Opt_list
171 		|
172 	NOOPTION Save_id
173 	      = { rmopt(&opt, $2); } |
174 	MAKEOPTIONS Mkopt_list
175 		|
176 	NOMAKEOPTION Save_id
177 	      = { rmopt(&mkopt, $2); } |
178 	IDENT ID
179 	      = { ident = $2; } |
180 	System_spec
181 		|
182 	MAXUSERS NUMBER
183 	      = { maxusers = $2; } |
184 	PROFILE NUMBER
185 	      = { profiling = $2; } |
186 	ENV ID
187 	      = {
188 		env = $2;
189 		envmode = 1;
190 		} |
191 	HINTS ID
192 	      = {
193 		struct hint *hint;
194 
195 		hint = (struct hint *)calloc(1, sizeof (struct hint));
196 		hint->hint_name = $2;
197 		STAILQ_INSERT_TAIL(&hints, hint, hint_next);
198 		hintmode = 1;
199 	        }
200 
201 System_spec:
202 	CONFIG System_id System_parameter_list
203 	  = { errx(1, "%s:%d: root/dump/swap specifications obsolete",
204 	      yyfile, yyline);}
205 	  |
206 	CONFIG System_id
207 	  ;
208 
209 System_id:
210 	Save_id
211 	      = { newopt(&mkopt, ns("KERNEL"), $1); };
212 
213 System_parameter_list:
214 	  System_parameter_list ID
215 	| ID
216 	;
217 
218 Opt_list:
219 	Opt_list COMMA Option
220 		|
221 	Option
222 		;
223 
224 Option:
225 	Save_id
226 	      = {
227 		newopt(&opt, $1, NULL);
228 		if (strchr($1, '=') != NULL)
229 			errx(1, "%s:%d: The `=' in options should not be "
230 			    "quoted", yyfile, yyline);
231 	      } |
232 	Save_id EQUALS Opt_value
233 	      = {
234 		newopt(&opt, $1, $3);
235 	      } ;
236 
237 Opt_value:
238 	ID
239 		= { $$ = $1; } |
240 	NUMBER
241 		= {
242 			char buf[80];
243 
244 			(void) snprintf(buf, sizeof(buf), "%d", $1);
245 			$$ = ns(buf);
246 		} ;
247 
248 Save_id:
249 	ID
250 	      = { $$ = $1; }
251 	;
252 
253 Mkopt_list:
254 	Mkopt_list COMMA Mkoption
255 		|
256 	Mkoption
257 		;
258 
259 Mkoption:
260 	Save_id
261 	      = { newopt(&mkopt, $1, ns("")); } |
262 	Save_id EQUALS Opt_value
263 	      = { newopt(&mkopt, $1, $3); } ;
264 
265 Dev:
266 	ID
267 	      = { $$ = $1; }
268 	;
269 
270 Device_spec:
271 	DEVICE Dev_list
272 		|
273 	NODEVICE NoDev_list
274 		;
275 
276 Dev_list:
277 	Dev_list COMMA Device
278 		|
279 	Device
280 		;
281 
282 NoDev_list:
283 	NoDev_list COMMA NoDevice
284 		|
285 	NoDevice
286 		;
287 
288 Device:
289 	Dev
290 	      = {
291 		newopt(&opt, devopt($1), ns("1"));
292 		/* and the device part */
293 		newdev($1);
294 		}
295 
296 NoDevice:
297 	Dev
298 	      = {
299 		char *s = devopt($1);
300 
301 		rmopt(&opt, s);
302 		free(s);
303 		/* and the device part */
304 		rmdev($1);
305 		} ;
306 
307 %%
308 
309 void
310 yyerror(const char *s)
311 {
312 
313 	errx(1, "%s:%d: %s", yyfile, yyline + 1, s);
314 }
315 
316 int
317 yywrap(void)
318 {
319 
320 	if (found_defaults) {
321 		if (freopen(PREFIX, "r", stdin) == NULL)
322 			err(2, "%s", PREFIX);
323 		yyfile = PREFIX;
324 		yyline = 0;
325 		found_defaults = 0;
326 		return 0;
327 	}
328 	return 1;
329 }
330 
331 /*
332  * Add a new file to the list of files.
333  */
334 static void
335 newfile(char *name)
336 {
337 	struct files_name *nl;
338 
339 	nl = (struct files_name *) calloc(1, sizeof *nl);
340 	nl->f_name = name;
341 	STAILQ_INSERT_TAIL(&fntab, nl, f_next);
342 }
343 
344 /*
345  * Find a device in the list of devices.
346  */
347 static struct device *
348 finddev(char *name)
349 {
350 	struct device *dp;
351 
352 	STAILQ_FOREACH(dp, &dtab, d_next)
353 		if (eq(dp->d_name, name))
354 			return (dp);
355 
356 	return (NULL);
357 }
358 
359 /*
360  * Add a device to the list of devices.
361  */
362 static void
363 newdev(char *name)
364 {
365 	struct device *np;
366 
367 	if (finddev(name)) {
368 		printf("WARNING: duplicate device `%s' encountered.\n", name);
369 		return;
370 	}
371 
372 	np = (struct device *) calloc(1, sizeof *np);
373 	np->d_name = name;
374 	STAILQ_INSERT_TAIL(&dtab, np, d_next);
375 }
376 
377 /*
378  * Remove a device from the list of devices.
379  */
380 static void
381 rmdev(char *name)
382 {
383 	struct device *dp;
384 
385 	dp = finddev(name);
386 	if (dp != NULL) {
387 		STAILQ_REMOVE(&dtab, dp, device, d_next);
388 		free(dp->d_name);
389 		free(dp);
390 	}
391 }
392 
393 /*
394  * Find an option in the list of options.
395  */
396 static struct opt *
397 findopt(struct opt_head *list, char *name)
398 {
399 	struct opt *op;
400 
401 	SLIST_FOREACH(op, list, op_next)
402 		if (eq(op->op_name, name))
403 			return (op);
404 
405 	return (NULL);
406 }
407 
408 /*
409  * Add an option to the list of options.
410  */
411 static void
412 newopt(struct opt_head *list, char *name, char *value)
413 {
414 	struct opt *op;
415 
416 	if (findopt(list, name)) {
417 		printf("WARNING: duplicate option `%s' encountered.\n", name);
418 		return;
419 	}
420 
421 	op = (struct opt *)calloc(1, sizeof (struct opt));
422 	op->op_name = name;
423 	op->op_ownfile = 0;
424 	op->op_value = value;
425 	SLIST_INSERT_HEAD(list, op, op_next);
426 }
427 
428 /*
429  * Remove an option from the list of options.
430  */
431 static void
432 rmopt(struct opt_head *list, char *name)
433 {
434 	struct opt *op;
435 
436 	op = findopt(list, name);
437 	if (op != NULL) {
438 		SLIST_REMOVE(list, op, opt, op_next);
439 		free(op->op_name);
440 		if (op->op_value != NULL)
441 			free(op->op_value);
442 		free(op);
443 	}
444 }
445