config.y revision 331722
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: stable/11/usr.sbin/config/config.y 331722 2018-03-29 02:50:57Z eadler $
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 NoOpt_list |
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
228NoOpt_list:
229	NoOpt_list COMMA NoOption
230	  	|
231	NoOption
232		;
233Option:
234	Save_id {
235		newopt(&opt, $1, NULL, 0);
236		if (strchr($1, '=') != NULL)
237			errx(1, "%s:%d: The `=' in options should not be "
238			    "quoted", yyfile, yyline);
239	      } |
240	Save_id EQUALS Opt_value {
241		newopt(&opt, $1, $3, 0);
242	      } ;
243
244NoOption:
245	Save_id {
246		rmopt_schedule(&opt, $1);
247		};
248
249Opt_value:
250	ID { $$ = $1; } |
251	NUMBER {
252			char buf[80];
253
254			(void) snprintf(buf, sizeof(buf), "%d", $1);
255			$$ = ns(buf);
256		} ;
257
258Save_id:
259	ID { $$ = $1; }
260	;
261
262Mkopt_list:
263	Mkopt_list COMMA Mkoption
264		|
265	Mkoption
266		;
267
268Mkoption:
269	Save_id { newopt(&mkopt, $1, ns(""), 0); } |
270	Save_id EQUALS { newopt(&mkopt, $1, ns(""), 0); } |
271	Save_id EQUALS Opt_value { newopt(&mkopt, $1, $3, 0); } |
272	Save_id PLUSEQUALS Opt_value { newopt(&mkopt, $1, $3, 1); } ;
273
274Dev:
275	ID { $$ = $1; }
276	;
277
278Device_spec:
279	DEVICE Dev_list
280		|
281	NODEVICE NoDev_list
282		;
283
284Dev_list:
285	Dev_list COMMA Device
286		|
287	Device
288		;
289
290NoDev_list:
291	NoDev_list COMMA NoDevice
292		|
293	NoDevice
294		;
295
296Device:
297	Dev {
298		newopt(&opt, devopt($1), ns("1"), 0);
299		/* and the device part */
300		newdev($1);
301		}
302
303NoDevice:
304	Dev {
305		char *s = devopt($1);
306
307		rmopt_schedule(&opt, s);
308		free(s);
309		/* and the device part */
310		rmdev_schedule(&dtab, $1);
311		} ;
312
313%%
314
315void
316yyerror(const char *s)
317{
318
319	errx(1, "%s:%d: %s", yyfile, yyline + 1, s);
320}
321
322int
323yywrap(void)
324{
325	if (found_defaults) {
326		if (freopen(PREFIX, "r", stdin) == NULL)
327			err(2, "%s", PREFIX);
328		yyfile = PREFIX;
329		yyline = 0;
330		found_defaults = 0;
331		return 0;
332	}
333	return 1;
334}
335
336/*
337 * Add a new file to the list of files.
338 */
339static void
340newfile(char *name)
341{
342	struct files_name *nl;
343
344	nl = (struct files_name *) calloc(1, sizeof *nl);
345	if (nl == NULL)
346		err(EXIT_FAILURE, "calloc");
347	nl->f_name = name;
348	STAILQ_INSERT_TAIL(&fntab, nl, f_next);
349}
350
351/*
352 * Find a device in the list of devices.
353 */
354static struct device *
355finddev(struct device_head *dlist, char *name)
356{
357	struct device *dp;
358
359	STAILQ_FOREACH(dp, dlist, d_next)
360		if (eq(dp->d_name, name))
361			return (dp);
362
363	return (NULL);
364}
365
366/*
367 * Add a device to the list of devices.
368 */
369static void
370newdev(char *name)
371{
372	struct device *np;
373
374	if (finddev(&dtab, name)) {
375		fprintf(stderr,
376		    "WARNING: duplicate device `%s' encountered.\n", name);
377		return;
378	}
379
380	np = (struct device *) calloc(1, sizeof *np);
381	if (np == NULL)
382		err(EXIT_FAILURE, "calloc");
383	np->d_name = name;
384	STAILQ_INSERT_TAIL(&dtab, np, d_next);
385}
386
387/*
388 * Schedule a device to removal.
389 */
390static void
391rmdev_schedule(struct device_head *dh, char *name)
392{
393	struct device *dp;
394
395	dp = finddev(dh, name);
396	if (dp != NULL) {
397		STAILQ_REMOVE(dh, dp, device, d_next);
398		free(dp->d_name);
399		free(dp);
400	}
401}
402
403/*
404 * Find an option in the list of options.
405 */
406static struct opt *
407findopt(struct opt_head *list, char *name)
408{
409	struct opt *op;
410
411	SLIST_FOREACH(op, list, op_next)
412		if (eq(op->op_name, name))
413			return (op);
414
415	return (NULL);
416}
417
418/*
419 * Add an option to the list of options.
420 */
421static void
422newopt(struct opt_head *list, char *name, char *value, int append)
423{
424	struct opt *op, *op2;
425
426	/*
427	 * Ignore inclusions listed explicitly for configuration files.
428	 */
429	if (eq(name, OPT_AUTOGEN)) {
430		incignore = 1;
431		return;
432	}
433
434	op2 = findopt(list, name);
435	if (op2 != NULL && !append) {
436		fprintf(stderr,
437		    "WARNING: duplicate option `%s' encountered.\n", name);
438		return;
439	}
440
441	op = (struct opt *)calloc(1, sizeof (struct opt));
442	if (op == NULL)
443		err(EXIT_FAILURE, "calloc");
444	op->op_name = name;
445	op->op_ownfile = 0;
446	op->op_value = value;
447	if (op2 != NULL) {
448		while (SLIST_NEXT(op2, op_append) != NULL)
449			op2 = SLIST_NEXT(op2, op_append);
450		SLIST_NEXT(op2, op_append) = op;
451	} else
452		SLIST_INSERT_HEAD(list, op, op_next);
453}
454
455/*
456 * Remove an option from the list of options.
457 */
458static void
459rmopt_schedule(struct opt_head *list, char *name)
460{
461	struct opt *op;
462
463	op = findopt(list, name);
464	if (op != NULL) {
465		SLIST_REMOVE(list, op, opt, op_next);
466		free(op->op_name);
467		free(op);
468	}
469}
470