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