xref: /dragonfly/usr.sbin/config/config.y (revision 335b9e93)
1 %union {
2 	char	*str;
3 	int	val;
4 	struct	file_list *file;
5 }
6 
7 %token	ANY
8 %token	AT
9 %token	BUS
10 %token	COMMA
11 %token	CONFIG
12 %token	CONFIG_MACHINE
13 %token	CONFIG_MACHINE_ARCH
14 %token	CONFIG_PLATFORM
15 %token	CPU
16 %token	DEVICE
17 %token	DISABLE
18 %token	DRIVE
19 %token	DRQ
20 %token	EQUALS
21 %token	FLAGS
22 %token	IDENT
23 %token	IOMEM
24 %token	IOSIZ
25 %token	IRQ
26 %token	MAXUSERS
27 %token	MINUS
28 %token	NEXUS
29 %token	OPTIONS
30 %token	MAKEOPTIONS
31 %token	PORT
32 %token	PSEUDO_DEVICE
33 %token	SEMICOLON
34 %token	TARGET
35 %token	TTY
36 %token	UNIT
37 %token	VECTOR
38 
39 %token	<str>	ID
40 %token	<val>	NUMBER
41 %token	<val>	FPNUMBER
42 
43 %type	<str>	Save_id
44 %type	<str>	Opt_value
45 %type	<str>	Dev
46 %type	<str>	device_name
47 
48 %{
49 
50 /*
51  * Copyright (c) 1988, 1993
52  *	The Regents of the University of California.  All rights reserved.
53  *
54  * Redistribution and use in source and binary forms, with or without
55  * modification, are permitted provided that the following conditions
56  * are met:
57  * 1. Redistributions of source code must retain the above copyright
58  *    notice, this list of conditions and the following disclaimer.
59  * 2. Redistributions in binary form must reproduce the above copyright
60  *    notice, this list of conditions and the following disclaimer in the
61  *    documentation and/or other materials provided with the distribution.
62  * 3. Neither the name of the University nor the names of its contributors
63  *    may be used to endorse or promote products derived from this software
64  *    without specific prior written permission.
65  *
66  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
67  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
68  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
69  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
70  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
71  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
72  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
73  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
74  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
75  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
76  * SUCH DAMAGE.
77  *
78  *	@(#)config.y	8.1 (Berkeley) 6/6/93
79  * $FreeBSD: src/usr.sbin/config/config.y,v 1.42.2.1 2001/01/23 00:09:32 peter Exp $
80  * $DragonFly: src/usr.sbin/config/config.y,v 1.15 2008/05/01 09:24:42 swildner Exp $
81  */
82 
83 #include <ctype.h>
84 #include <err.h>
85 #include <stdio.h>
86 #include <string.h>
87 
88 #include "config.h"
89 
90 static struct	device cur;
91 static struct	device *curp = 0;
92 
93 struct  device *dtab;
94 char	*ident;
95 int	yyline;
96 struct  file_list *ftab;
97 char	errbuf[80];
98 int	maxusers;
99 
100 static int connect(char *, int);
101 static void yyerror(const char *s);
102 
103 int yylex(void);
104 
105 %}
106 %%
107 Configuration:
108 	Many_specs
109 		;
110 
111 Many_specs:
112 	Many_specs Spec
113 		|
114 	/* lambda */
115 		;
116 
117 Spec:
118 	Device_spec SEMICOLON { newdev(&cur); }
119 		|
120 	Config_spec SEMICOLON
121 		|
122 	SEMICOLON
123 		|
124 	error SEMICOLON
125 		;
126 
127 Config_spec:
128 	CONFIG_PLATFORM Save_id {
129 		if (platformname != NULL) {
130 		    errx(1, "%d: only one platform directive is allowed",
131 			yyline);
132 		}
133 		platformname = $2;
134 	      } |
135 	CONFIG_MACHINE Save_id {
136 		if (machinename != NULL) {
137 		    errx(1, "%d: only one machine directive is allowed",
138 			yyline);
139 		}
140 		machinename = $2;
141 	      } |
142 	CONFIG_MACHINE_ARCH Save_id {
143 		if (machinearchname != NULL) {
144 		    errx(1, "%d: only one machine_arch directive is allowed",
145 			yyline);
146 		}
147 		machinearchname = $2;
148 	      } |
149 	CPU Save_id {
150 		struct cputype *cp;
151 
152 		cp = malloc(sizeof(struct cputype));
153 		bzero(cp, sizeof(*cp));
154 		cp->cpu_name = $2;
155 		cp->cpu_next = cputype;
156 		cputype = cp;
157 	      } |
158 	OPTIONS Opt_list
159 		|
160 	MAKEOPTIONS Mkopt_list
161 		|
162 	IDENT ID { ident = $2; }
163 		|
164 	System_spec
165 		|
166 	MAXUSERS NUMBER { maxusers = $2; };
167 
168 System_spec:
169 	CONFIG System_id System_parameter_list {
170 		errx(1,"line %d: root/dump/swap specifications obsolete",
171 		    yyline);
172 	      } |
173 	CONFIG System_id
174 		;
175 
176 System_id:
177 	Save_id {
178 		struct opt *op;
179 
180 		op = malloc(sizeof(struct opt));
181 		bzero(op, sizeof(*op));
182 		op->op_name = strdup("KERNEL");
183 		op->op_ownfile = 0;
184 		op->op_next = mkopt;
185 		op->op_value = $1;
186 		op->op_line = yyline + 1;
187 		mkopt = op;
188 	      };
189 
190 System_parameter_list:
191 	  System_parameter_list ID
192 	| ID
193 	;
194 
195 device_name:
196 	  Save_id { $$ = $1; }
197 	| Save_id NUMBER {
198 			char buf[80];
199 
200 			snprintf(buf, sizeof(buf), "%s%d", $1, $2);
201 			$$ = strdup(buf);
202 			free($1);
203 		}
204 	| Save_id NUMBER ID {
205 			char buf[80];
206 
207 			snprintf(buf, sizeof(buf), "%s%d%s", $1, $2, $3);
208 			$$ = strdup(buf);
209 			free($1);
210 		}
211 	| Save_id NUMBER ID NUMBER {
212 			char buf[80];
213 
214 			snprintf(buf, sizeof(buf), "%s%d%s%d",
215 			     $1, $2, $3, $4);
216 			$$ = strdup(buf);
217 			free($1);
218 		}
219 	| Save_id NUMBER ID NUMBER ID {
220 			char buf[80];
221 
222 			snprintf(buf, sizeof(buf), "%s%d%s%d%s",
223 			     $1, $2, $3, $4, $5);
224 			$$ = strdup(buf);
225 			free($1);
226 		}
227 	;
228 
229 Opt_list:
230 	Opt_list COMMA Option
231 		|
232 	Option
233 		;
234 
235 Option:
236 	Save_id {
237 		struct opt *op;
238 
239 		op = malloc(sizeof(struct opt));
240 		bzero(op, sizeof(*op));
241 		op->op_name = $1;
242 		op->op_next = opt;
243 		op->op_value = 0;
244 		/*
245 		 * op->op_line is 1-based; yyline is 0-based but is now 1
246 		 * larger than when `Save_id' was lexed.
247 		 */
248 		op->op_line = yyline;
249 		opt = op;
250 		if (strchr(op->op_name, '=') != NULL)
251 			errx(1, "line %d: The `=' in options should not be quoted", yyline);
252 	      } |
253 	Save_id EQUALS Opt_value {
254 		struct opt *op;
255 
256 		op = malloc(sizeof(struct opt));
257 		bzero(op, sizeof(*op));
258 		op->op_name = $1;
259 		op->op_next = opt;
260 		op->op_value = $3;
261 		op->op_line = yyline + 1;
262 		opt = op;
263 	      } ;
264 
265 Opt_value:
266 	ID	{ $$ = $1; } |
267 	NUMBER	{
268 			char buf[80];
269 
270 			snprintf(buf, sizeof(buf), "%d", $1);
271 			$$ = strdup(buf);
272 		} ;
273 
274 Save_id:
275 	ID	{ $$ = $1; }
276 	;
277 
278 Mkopt_list:
279 	Mkopt_list COMMA Mkoption
280 		|
281 	Mkoption
282 		;
283 
284 Mkoption:
285 	Save_id EQUALS Opt_value {
286 		struct opt *op;
287 
288 		op = malloc(sizeof(struct opt));
289 		bzero(op, sizeof(*op));
290 		op->op_name = $1;
291 		op->op_ownfile = 0;	/* for now */
292 		op->op_next = mkopt;
293 		op->op_value = $3;
294 		op->op_line = yyline + 1;
295 		mkopt = op;
296 	      } ;
297 
298 Dev:
299 	ID	{ $$ = $1; }
300 	;
301 
302 Device_spec:
303 	DEVICE Dev_spec { cur.d_type = DEVICE; }
304 		|
305 	PSEUDO_DEVICE Init_dev Dev {
306 		cur.d_name = $3;
307 		cur.d_type = PSEUDO_DEVICE;
308 	      } |
309 	PSEUDO_DEVICE Init_dev Dev NUMBER {
310 		cur.d_name = $3;
311 		cur.d_type = PSEUDO_DEVICE;
312 		cur.d_count = $4;
313 	      } ;
314 
315 Dev_spec:
316 	Init_dev Dev {
317 		cur.d_name = $2;
318 		cur.d_unit = UNKNOWN;
319 	      } |
320 	Init_dev Dev NUMBER Dev_info {
321 		cur.d_name = $2;
322 		cur.d_unit = $3;
323 	      } ;
324 
325 Init_dev:
326 	/* lambda */ { init_dev(&cur); };
327 
328 Dev_info:
329 	Con_info Info_list
330 		|
331 	/* lambda */
332 		;
333 
334 Con_info:
335 	AT Dev NUMBER {
336 		connect($2, $3);
337 		cur.d_conn = $2;
338 		cur.d_connunit = $3;
339 	      } |
340 	AT NEXUS NUMBER {
341 	        cur.d_conn = "nexus";
342 	        cur.d_connunit = 0;
343 	      } ;
344 
345 Info_list:
346 	Info_list Info
347 		|
348 	/* lambda */
349 		;
350 
351 Info:
352 	BUS NUMBER	{ cur.d_bus = $2; }
353 		|
354 	TARGET NUMBER	{ cur.d_target = $2; }
355 		|
356 	UNIT NUMBER	{ cur.d_lun = $2; }
357 		|
358 	DRIVE NUMBER	{ cur.d_drive = $2; }
359 		|
360 	IRQ NUMBER	{ cur.d_irq = $2; }
361 		|
362 	DRQ NUMBER	{ cur.d_drq = $2; }
363 		|
364 	IOMEM NUMBER	{ cur.d_maddr = $2; }
365 		|
366 	IOSIZ NUMBER	{ cur.d_msize = $2; }
367 		|
368 	PORT device_name { cur.d_port = $2; }
369 		|
370 	PORT NUMBER	{ cur.d_portn = $2; }
371 		|
372 	FLAGS NUMBER	{ cur.d_flags = $2; }
373 		|
374 	DISABLE		{ cur.d_disabled = 1; }
375 
376 %%
377 
378 static void
379 yyerror(const char *s)
380 {
381 
382 	errx(1, "line %d: %s", yyline + 1, s);
383 }
384 
385 /*
386  * add a device to the list of devices
387  */
388 static void
389 newdev(struct device *dp)
390 {
391 	struct device *np, *xp;
392 
393 	if (dp->d_unit >= 0) {
394 		for (xp = dtab; xp != NULL; xp = xp->d_next) {
395 			if ((xp->d_unit == dp->d_unit) &&
396 			    !strcmp(xp->d_name, dp->d_name)) {
397 				errx(1, "line %d: already seen device %s%d",
398 				    yyline, xp->d_name, xp->d_unit);
399 			}
400 		}
401 	}
402 	np = malloc(sizeof(*np));
403 	bzero(np, sizeof(*np));
404 	*np = *dp;
405 	np->d_next = NULL;
406 	if (curp == NULL)
407 		dtab = np;
408 	else
409 		curp->d_next = np;
410 	curp = np;
411 }
412 
413 
414 /*
415  * find the pointer to connect to the given device and number.
416  * returns 0 if no such device and prints an error message
417  */
418 static int
419 connect(char *dev, int num)
420 {
421 	struct device *dp;
422 
423 	if (num == QUES) {
424 		for (dp = dtab; dp != NULL; dp = dp->d_next)
425 			if (!strcmp(dp->d_name, dev))
426 				break;
427 		if (dp == NULL) {
428 			snprintf(errbuf, sizeof(errbuf),
429 			    "no %s's to wildcard", dev);
430 			yyerror(errbuf);
431 			return(0);
432 		}
433 		return(1);
434 	}
435 	for (dp = dtab; dp != NULL; dp = dp->d_next) {
436 		if ((num != dp->d_unit) || strcmp(dev, dp->d_name))
437 			continue;
438 		if (dp->d_type != DEVICE) {
439 			snprintf(errbuf, sizeof(errbuf),
440 			    "%s connected to non-device", dev);
441 			yyerror(errbuf);
442 			return(0);
443 		}
444 		return(1);
445 	}
446 	snprintf(errbuf, sizeof(errbuf), "%s %d not defined", dev, num);
447 	yyerror(errbuf);
448 	return(0);
449 }
450 
451 void
452 init_dev(struct device *dp)
453 {
454 
455 	dp->d_name = "OHNO!!!";
456 	dp->d_type = DEVICE;
457 	dp->d_conn = 0;
458 	dp->d_disabled = 0;
459 	dp->d_flags = 0;
460 	dp->d_bus = dp->d_lun = dp->d_target = dp->d_drive = dp->d_unit =
461 	    dp->d_count = UNKNOWN;
462 	dp->d_port = NULL;
463 	dp->d_portn = -1;
464 	dp->d_irq = -1;
465 	dp->d_drq = -1;
466 	dp->d_maddr = 0;
467 	dp->d_msize = 0;
468 }
469