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