xref: /dragonfly/usr.sbin/config/config.y (revision 9348a738)
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
119 	      = { newdev(&cur); } |
120 	Config_spec SEMICOLON
121 		|
122 	SEMICOLON
123 		|
124 	error SEMICOLON
125 		;
126 
127 Config_spec:
128 	CONFIG_PLATFORM Save_id
129 	    = {
130 		if (platformname != NULL) {
131 		    errx(1, "%d: only one platform directive is allowed",
132 			yyline);
133 		}
134 		platformname = $2;
135 	      } |
136 	CONFIG_MACHINE Save_id
137 	    = {
138 		if (machinename != NULL) {
139 		    errx(1, "%d: only one machine directive is allowed",
140 			yyline);
141 		}
142 		machinename = $2;
143 	      } |
144 	CONFIG_MACHINE_ARCH Save_id
145 	      = {
146 		if (machinearchname != NULL) {
147 		    errx(1, "%d: only one machine_arch directive is allowed",
148 			yyline);
149 		}
150 		machinearchname = $2;
151 	      } |
152 	CPU Save_id
153 	      = {
154 		struct cputype *cp;
155 
156 		cp = malloc(sizeof(struct cputype));
157 		bzero(cp, sizeof(*cp));
158 		cp->cpu_name = $2;
159 		cp->cpu_next = cputype;
160 		cputype = cp;
161 	      } |
162 	OPTIONS Opt_list
163 		|
164 	MAKEOPTIONS Mkopt_list
165 		|
166 	IDENT ID
167 	      = { ident = $2; } |
168 	System_spec
169 		|
170 	MAXUSERS NUMBER
171 	      = { maxusers = $2; };
172 
173 System_spec:
174 	CONFIG System_id System_parameter_list
175 	  = { errx(1,"line %d: root/dump/swap specifications obsolete", yyline);}
176 	  |
177 	CONFIG System_id
178 	  ;
179 
180 System_id:
181 	Save_id
182 	      = {
183 		struct opt *op;
184 
185 		op = malloc(sizeof(struct opt));
186 		bzero(op, sizeof(*op));
187 		op->op_name = strdup("KERNEL");
188 		op->op_ownfile = 0;
189 		op->op_next = mkopt;
190 		op->op_value = $1;
191 		op->op_line = yyline + 1;
192 		mkopt = op;
193 	      };
194 
195 System_parameter_list:
196 	  System_parameter_list ID
197 	| ID
198 	;
199 
200 device_name:
201 	  Save_id
202 		= { $$ = $1; }
203 	| Save_id NUMBER
204 		= {
205 			char buf[80];
206 
207 			snprintf(buf, sizeof(buf), "%s%d", $1, $2);
208 			$$ = strdup(buf);
209 			free($1);
210 		}
211 	| Save_id NUMBER ID
212 		= {
213 			char buf[80];
214 
215 			snprintf(buf, sizeof(buf), "%s%d%s", $1, $2, $3);
216 			$$ = strdup(buf);
217 			free($1);
218 		}
219 	| Save_id NUMBER ID NUMBER
220 		= {
221 			char buf[80];
222 
223 			snprintf(buf, sizeof(buf), "%s%d%s%d",
224 			     $1, $2, $3, $4);
225 			$$ = strdup(buf);
226 			free($1);
227 		}
228 	| Save_id NUMBER ID NUMBER ID
229 		= {
230 			char buf[80];
231 
232 			snprintf(buf, sizeof(buf), "%s%d%s%d%s",
233 			     $1, $2, $3, $4, $5);
234 			$$ = strdup(buf);
235 			free($1);
236 		}
237 	;
238 
239 Opt_list:
240 	Opt_list COMMA Option
241 		|
242 	Option
243 		;
244 
245 Option:
246 	Save_id
247 	      = {
248 		struct opt *op;
249 
250 		op = malloc(sizeof(struct opt));
251 		bzero(op, sizeof(*op));
252 		op->op_name = $1;
253 		op->op_next = opt;
254 		op->op_value = 0;
255 		/*
256 		 * op->op_line is 1-based; yyline is 0-based but is now 1
257 		 * larger than when `Save_id' was lexed.
258 		 */
259 		op->op_line = yyline;
260 		opt = op;
261 		if (strchr(op->op_name, '=') != NULL)
262 			errx(1, "line %d: The `=' in options should not be quoted", yyline);
263 	      } |
264 	Save_id EQUALS Opt_value
265 	      = {
266 		struct opt *op;
267 
268 		op = malloc(sizeof(struct opt));
269 		bzero(op, sizeof(*op));
270 		op->op_name = $1;
271 		op->op_next = opt;
272 		op->op_value = $3;
273 		op->op_line = yyline + 1;
274 		opt = op;
275 	      } ;
276 
277 Opt_value:
278 	ID
279 		= { $$ = $1; } |
280 	NUMBER
281 		= {
282 			char buf[80];
283 
284 			snprintf(buf, sizeof(buf), "%d", $1);
285 			$$ = strdup(buf);
286 		} ;
287 
288 Save_id:
289 	ID
290 	      = { $$ = $1; }
291 	;
292 
293 Mkopt_list:
294 	Mkopt_list COMMA Mkoption
295 		|
296 	Mkoption
297 		;
298 
299 Mkoption:
300 	Save_id EQUALS Opt_value
301 	      = {
302 		struct opt *op;
303 
304 		op = malloc(sizeof(struct opt));
305 		bzero(op, sizeof(*op));
306 		op->op_name = $1;
307 		op->op_ownfile = 0;	/* for now */
308 		op->op_next = mkopt;
309 		op->op_value = $3;
310 		op->op_line = yyline + 1;
311 		mkopt = op;
312 	      } ;
313 
314 Dev:
315 	ID
316 	      = { $$ = $1; }
317 	;
318 
319 Device_spec:
320 	DEVICE Dev_spec
321 	      = { cur.d_type = DEVICE; } |
322 	PSEUDO_DEVICE Init_dev Dev
323 	      = {
324 		cur.d_name = $3;
325 		cur.d_type = PSEUDO_DEVICE;
326 		} |
327 	PSEUDO_DEVICE Init_dev Dev NUMBER
328 	      = {
329 		cur.d_name = $3;
330 		cur.d_type = PSEUDO_DEVICE;
331 		cur.d_count = $4;
332 		} ;
333 
334 Dev_spec:
335 	Init_dev Dev
336 	      = {
337 		cur.d_name = $2;
338 		cur.d_unit = UNKNOWN;
339 		} |
340 	Init_dev Dev NUMBER Dev_info
341 	      = {
342 		cur.d_name = $2;
343 		cur.d_unit = $3;
344 		};
345 
346 Init_dev:
347 	/* lambda */
348 	      = { init_dev(&cur); };
349 
350 Dev_info:
351 	Con_info Info_list
352 		|
353 	/* lambda */
354 		;
355 
356 Con_info:
357 	AT Dev NUMBER
358 	      = {
359 		connect($2, $3);
360 		cur.d_conn = $2;
361 		cur.d_connunit = $3;
362 		} |
363 	AT NEXUS NUMBER
364 	      = {
365 	        cur.d_conn = "nexus";
366 	        cur.d_connunit = 0;
367 	        };
368 
369 Info_list:
370 	Info_list Info
371 		|
372 	/* lambda */
373 		;
374 
375 Info:
376 	BUS NUMBER	/* device scbus1 at ahc0 bus 1 - twin channel */
377 	      = { cur.d_bus = $2; } |
378 	TARGET NUMBER
379 	      = { cur.d_target = $2; } |
380 	UNIT NUMBER
381 	      = { cur.d_lun = $2; } |
382 	DRIVE NUMBER
383 	      = { cur.d_drive = $2; } |
384 	IRQ NUMBER
385 	      = { cur.d_irq = $2; } |
386 	DRQ NUMBER
387 	      = { cur.d_drq = $2; } |
388 	IOMEM NUMBER
389 	      = { cur.d_maddr = $2; } |
390 	IOSIZ NUMBER
391 	      = { cur.d_msize = $2; } |
392 	PORT device_name
393 	      = { cur.d_port = $2; } |
394 	PORT NUMBER
395 	      = { cur.d_portn = $2; } |
396 	FLAGS NUMBER
397 	      = { cur.d_flags = $2; } |
398 	DISABLE
399 	      = { cur.d_disabled = 1; }
400 
401 %%
402 
403 static void
404 yyerror(const char *s)
405 {
406 
407 	errx(1, "line %d: %s", yyline + 1, s);
408 }
409 
410 /*
411  * add a device to the list of devices
412  */
413 static void
414 newdev(struct device *dp)
415 {
416 	struct device *np, *xp;
417 
418 	if (dp->d_unit >= 0) {
419 		for (xp = dtab; xp != NULL; xp = xp->d_next) {
420 			if ((xp->d_unit == dp->d_unit) &&
421 			    !strcmp(xp->d_name, dp->d_name)) {
422 				errx(1, "line %d: already seen device %s%d",
423 				    yyline, xp->d_name, xp->d_unit);
424 			}
425 		}
426 	}
427 	np = malloc(sizeof(*np));
428 	bzero(np, sizeof(*np));
429 	*np = *dp;
430 	np->d_next = NULL;
431 	if (curp == NULL)
432 		dtab = np;
433 	else
434 		curp->d_next = np;
435 	curp = np;
436 }
437 
438 
439 /*
440  * find the pointer to connect to the given device and number.
441  * returns 0 if no such device and prints an error message
442  */
443 static int
444 connect(char *dev, int num)
445 {
446 	struct device *dp;
447 
448 	if (num == QUES) {
449 		for (dp = dtab; dp != NULL; dp = dp->d_next)
450 			if (!strcmp(dp->d_name, dev))
451 				break;
452 		if (dp == NULL) {
453 			snprintf(errbuf, sizeof(errbuf),
454 			    "no %s's to wildcard", dev);
455 			yyerror(errbuf);
456 			return(0);
457 		}
458 		return(1);
459 	}
460 	for (dp = dtab; dp != NULL; dp = dp->d_next) {
461 		if ((num != dp->d_unit) || strcmp(dev, dp->d_name))
462 			continue;
463 		if (dp->d_type != DEVICE) {
464 			snprintf(errbuf, sizeof(errbuf),
465 			    "%s connected to non-device", dev);
466 			yyerror(errbuf);
467 			return(0);
468 		}
469 		return(1);
470 	}
471 	snprintf(errbuf, sizeof(errbuf), "%s %d not defined", dev, num);
472 	yyerror(errbuf);
473 	return(0);
474 }
475 
476 void
477 init_dev(struct device *dp)
478 {
479 
480 	dp->d_name = "OHNO!!!";
481 	dp->d_type = DEVICE;
482 	dp->d_conn = 0;
483 	dp->d_disabled = 0;
484 	dp->d_flags = 0;
485 	dp->d_bus = dp->d_lun = dp->d_target = dp->d_drive = dp->d_unit =
486 	    dp->d_count = UNKNOWN;
487 	dp->d_port = NULL;
488 	dp->d_portn = -1;
489 	dp->d_irq = -1;
490 	dp->d_drq = -1;
491 	dp->d_maddr = 0;
492 	dp->d_msize = 0;
493 }
494