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