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