xref: /original-bsd/usr.sbin/config/config.y (revision 62734ea8)
1 %union {
2 	char	*str;
3 	int	val;
4 	struct	idlst *lst;
5 }
6 
7 %token	MACHINE
8 %token	CPU IDENT CONFIG ANY DEVICE UBA MBA NEXUS CSR DRIVE VECTOR OPTIONS
9 %token	CONTROLLER PSEUDO_DEVICE FLAGS SEMICOLON TRACE
10 %token	DISK SLAVE HZ TIMEZONE DST MAXUSERS
11 %token	MASTER PRIORITY COMMA MINUS EQUALS AT
12 
13 %token	<str>	ID
14 %token	<val>	NUMBER
15 %token	<val>	FPNUMBER
16 
17 %type	<str>	Save_id
18 %type	<str>	Opt_value
19 %type	<str>	Dev
20 %type	<lst>	Id_list
21 
22 %{
23 
24 /*	config.y	1.16	82/10/25	*/
25 
26 #include "config.h"
27 #include <stdio.h>
28 
29 struct	device cur;
30 struct	device *curp = 0;
31 char	*temp_id;
32 char	*val_id;
33 char	*malloc();
34 
35 %}
36 %%
37 Configuration:
38 	Many_specs
39 		;
40 
41 Many_specs:
42 	Many_specs Spec
43 		|
44 	/* lambda */
45 		;
46 
47 Spec:
48 	Device_spec SEMICOLON
49 	      = { newdev(&cur); } |
50 	Config_spec SEMICOLON
51 		|
52 	TRACE SEMICOLON
53 	      = { do_trace = !do_trace; } |
54 	SEMICOLON
55 		|
56 	error SEMICOLON
57 		;
58 
59 Config_spec:
60 	MACHINE Save_id
61 	    = {
62 		if (!strcmp($2, "vax")) {
63 			machine = MACHINE_VAX;
64 			machinename = "vax";
65 		} else if (!strcmp($2, "sun")) {
66 			machine = MACHINE_SUN;
67 			machinename = "sun";
68 		} else
69 			yyerror("Unknown machine type");
70 	      } |
71 	CPU Save_id
72 	      = {
73 		struct cputype *cp =
74 		    (struct cputype *)malloc(sizeof (struct cputype));
75 		cp->cpu_name = ns($2);
76 		cp->cpu_next = cputype;
77 		cputype = cp;
78 		free(temp_id);
79 	      } |
80 	OPTIONS Opt_list
81 		|
82 	IDENT ID
83 	      = { ident = ns($2); } |
84 	CONFIG Save_id ID
85 	      = { mkconf(temp_id, $3); free(temp_id); } |
86 	HZ NUMBER
87 	      = { yyerror("HZ specification obsolete; delete"); } |
88 	TIMEZONE NUMBER
89 	      = { timezone = 60 * $2; check_tz(); } |
90 	TIMEZONE NUMBER DST
91 	      = { timezone = 60 * $2; dst = 1; check_tz(); } |
92 	TIMEZONE FPNUMBER
93 	      = { timezone = $2; check_tz(); } |
94 	TIMEZONE FPNUMBER DST
95 	      = { timezone = $2; dst = 1; check_tz(); } |
96 	TIMEZONE MINUS NUMBER
97 	      = { timezone = -60 * $3; check_tz(); } |
98 	TIMEZONE MINUS NUMBER DST
99 	      = { timezone = -60 * $3; dst = 1; check_tz(); } |
100 	TIMEZONE MINUS FPNUMBER
101 	      = { timezone = -$3; check_tz(); } |
102 	TIMEZONE MINUS FPNUMBER DST
103 	      = { timezone = -$3; dst = 1; check_tz(); } |
104 	MAXUSERS NUMBER
105 	      = { maxusers = $2; };
106 
107 Opt_list:
108 	Opt_list COMMA Option
109 		|
110 	Option
111 		;
112 
113 Option:
114 	Save_id
115 	      = {
116 		struct opt *op = (struct opt *)malloc(sizeof (struct opt));
117 		op->op_name = ns($1);
118 		op->op_next = opt;
119 		op->op_value = 0;
120 		opt = op;
121 		free(temp_id);
122 	      } |
123 	Save_id EQUALS Opt_value
124 	      = {
125 		struct opt *op = (struct opt *)malloc(sizeof (struct opt));
126 		op->op_name = ns($1);
127 		op->op_next = opt;
128 		op->op_value = ns($3);
129 		opt = op;
130 		free(temp_id);
131 		free(val_id);
132 	      } ;
133 
134 Opt_value:
135 	ID
136 	      = { $$ = val_id = ns($1); } |
137 	NUMBER
138 	      = { char nb[16]; $$ = val_id = ns(sprintf(nb, "%d", $1)); };
139 
140 
141 Save_id:
142 	ID
143 	      = { $$ = temp_id = ns($1); }
144 	;
145 
146 Dev:
147 	UBA
148 	      = { $$ = ns("uba"); } |
149 	MBA
150 	      = { $$ = ns("mba"); } |
151 	ID
152 	      = { $$ = ns($1); }
153 	;
154 
155 Device_spec:
156 	DEVICE Dev_name Dev_info Int_spec
157 	      = { cur.d_type = DEVICE; } |
158 	MASTER Dev_name Dev_info Int_spec
159 	      = { cur.d_type = MASTER; } |
160 	DISK Dev_name Dev_info Int_spec
161 	      = { cur.d_dk = 1; cur.d_type = DEVICE; } |
162 	CONTROLLER Dev_name Dev_info Int_spec
163 	      = { cur.d_type = CONTROLLER; } |
164 	PSEUDO_DEVICE Init_dev Dev
165 	      = {
166 		cur.d_name = $3;
167 		cur.d_type = PSEUDO_DEVICE;
168 		} |
169 	PSEUDO_DEVICE Init_dev Dev NUMBER
170 	      = {
171 		cur.d_name = $3;
172 		cur.d_type = PSEUDO_DEVICE;
173 		cur.d_slave = $4;
174 		};
175 
176 Dev_name:
177 	Init_dev Dev NUMBER
178 	      = {
179 		cur.d_name = $2;
180 		if (eq($2, "mba"))
181 			seen_mba = 1;
182 		else if (eq($2, "uba"))
183 			seen_uba = 1;
184 		cur.d_unit = $3;
185 		};
186 
187 Init_dev:
188 	/* lambda */
189 	      = { init_dev(&cur); };
190 
191 Dev_info:
192 	Con_info Info_list
193 		|
194 	/* lambda */
195 		;
196 
197 Con_info:
198 	AT Dev NUMBER
199 	      = {
200 		if (eq(cur.d_name, "mba") || eq(cur.d_name, "uba"))
201 			yyerror(sprintf(errbuf,
202 			    "%s must be connected to a nexus", cur.d_name));
203 		cur.d_conn = connect($2, $3);
204 		} |
205 	AT NEXUS NUMBER
206 	      = { check_nexus(&cur, $3); cur.d_conn = TO_NEXUS; };
207 
208 Info_list:
209 	Info_list Info
210 		|
211 	/* lambda */
212 		;
213 
214 Info:
215 	CSR NUMBER
216 	      = { cur.d_addr = $2; } |
217 	DRIVE NUMBER
218 	      = { cur.d_drive = $2; } |
219 	SLAVE NUMBER
220 	      = {
221 		if (cur.d_conn != 0 && cur.d_conn != TO_NEXUS &&
222 		    cur.d_conn->d_type == MASTER)
223 			cur.d_slave = $2;
224 		else
225 			yyerror("can't specify slave--not to master");
226 		} |
227 	FLAGS NUMBER
228 	      = { cur.d_flags = $2; };
229 
230 Int_spec:
231 	VECTOR Id_list
232 	      = { cur.d_vec = $2; } |
233 	PRIORITY NUMBER
234 	      = { cur.d_pri = $2; } |
235 	/* lambda */
236 		;
237 
238 Id_list:
239 	Save_id
240 	      = {
241 		struct idlst *a = (struct idlst *)malloc(sizeof(struct idlst));
242 		a->id = $1; a->id_next = 0; $$ = a;
243 		} |
244 	Save_id Id_list =
245 		{
246 		struct idlst *a = (struct idlst *)malloc(sizeof(struct idlst));
247 	        a->id = $1; a->id_next = $2; $$ = a;
248 		};
249 
250 %%
251 
252 yyerror(s)
253 	char *s;
254 {
255 
256 	fprintf(stderr, "config: %s at line %d\n", s, yyline);
257 }
258 
259 /*
260  * return the passed string in a new space
261  */
262 char *
263 ns(str)
264 	register char *str;
265 {
266 	register char *cp;
267 
268 	cp = malloc((unsigned)(strlen(str)+1));
269 	(void) strcpy(cp, str);
270 	return (cp);
271 }
272 
273 /*
274  * add a device to the list of devices
275  */
276 newdev(dp)
277 	register struct device *dp;
278 {
279 	register struct device *np;
280 
281 	np = (struct device *) malloc(sizeof *np);
282 	*np = *dp;
283 	if (curp == 0)
284 		dtab = np;
285 	else
286 		curp->d_next = np;
287 	curp = np;
288 }
289 
290 /*
291  * note that a configuration should be made
292  */
293 mkconf(dev, sysname)
294 	char *dev, *sysname;
295 {
296 	register struct file_list *fl;
297 
298 	fl = (struct file_list *) malloc(sizeof *fl);
299 	fl->f_fn = ns(dev);
300 	fl->f_needs = ns(sysname);
301 	if (confp == 0)
302 		conf_list = fl;
303 	else
304 		confp->f_next = fl;
305 	confp = fl;
306 }
307 
308 /*
309  * find the pointer to connect to the given device and number.
310  * returns 0 if no such device and prints an error message
311  */
312 struct device *
313 connect(dev, num)
314 	register char *dev;
315 	register int num;
316 {
317 	register struct device *dp;
318 	struct device *huhcon();
319 
320 	if (num == QUES)
321 		return (huhcon(dev));
322 	for (dp = dtab; dp != 0; dp = dp->d_next) {
323 		if ((num != dp->d_unit) || !eq(dev, dp->d_name))
324 			continue;
325 		if (dp->d_type != CONTROLLER && dp->d_type != MASTER) {
326 			yyerror(sprintf(errbuf,
327 			    "%s connected to non-controller", dev));
328 			return (0);
329 		}
330 		return (dp);
331 	}
332 	yyerror(sprintf(errbuf, "%s %d not defined", dev, num));
333 	return (0);
334 }
335 
336 /*
337  * connect to an unspecific thing
338  */
339 struct device *
340 huhcon(dev)
341 	register char *dev;
342 {
343 	register struct device *dp, *dcp;
344 	struct device rdev;
345 	int oldtype;
346 
347 	/*
348 	 * First make certain that there are some of these to wildcard on
349 	 */
350 	for (dp = dtab; dp != 0; dp = dp->d_next)
351 		if (eq(dp->d_name, dev))
352 			break;
353 	if (dp == 0) {
354 		yyerror(sprintf(errbuf, "no %s's to wildcard", dev));
355 		return (0);
356 	}
357 	oldtype = dp->d_type;
358 	dcp = dp->d_conn;
359 	/*
360 	 * Now see if there is already a wildcard entry for this device
361 	 * (e.g. Search for a "uba ?")
362 	 */
363 	for (; dp != 0; dp = dp->d_next)
364 		if (eq(dev, dp->d_name) && dp->d_unit == -1)
365 			break;
366 	/*
367 	 * If there isn't, make one because everything needs to be connected
368 	 * to something.
369 	 */
370 	if (dp == 0) {
371 		dp = &rdev;
372 		init_dev(dp);
373 		dp->d_unit = QUES;
374 		dp->d_name = ns(dev);
375 		dp->d_type = oldtype;
376 		newdev(dp);
377 		dp = curp;
378 		/*
379 		 * Connect it to the same thing that other similar things are
380 		 * connected to, but make sure it is a wildcard unit
381 		 * (e.g. up connected to sc ?, here we make connect sc? to a
382 		 * uba?).  If other things like this are on the NEXUS or
383 		 * if they aren't connected to anything, then make the same
384 		 * connection, else call ourself to connect to another
385 		 * unspecific device.
386 		 */
387 		if (dcp == TO_NEXUS || dcp == 0)
388 			dp->d_conn = dcp;
389 		else
390 			dp->d_conn = connect(dcp->d_name, QUES);
391 	}
392 	return (dp);
393 }
394 
395 init_dev(dp)
396 	register struct device *dp;
397 {
398 
399 	dp->d_name = "OHNO!!!";
400 	dp->d_type = DEVICE;
401 	dp->d_conn = 0;
402 	dp->d_vec = 0;
403 	dp->d_addr = dp->d_pri = dp->d_flags = dp->d_dk = 0;
404 	dp->d_slave = dp->d_drive = dp->d_unit = UNKNOWN;
405 }
406 
407 /*
408  * make certain that this is a reasonable type of thing to connect to a nexus
409  */
410 check_nexus(dev, num)
411 	register struct device *dev;
412 	int num;
413 {
414 
415 	switch (machine) {
416 
417 	case MACHINE_VAX:
418 		if (!eq(dev->d_name, "uba") && !eq(dev->d_name, "mba"))
419 			yyerror("only uba's and mba's should be connected to the nexus");
420 		if (num != QUES)
421 			yyerror("can't give specific nexus numbers");
422 		break;
423 
424 	case MACHINE_SUN:
425 		if (!eq(dev->d_name, "mb"))
426 			yyerror("only mb's should be connected to the nexus");
427 		break;
428 	}
429 }
430 
431 /*
432  * Check the timezone to make certain it is sensible
433  */
434 
435 check_tz()
436 {
437 	if (abs(timezone) > 12 * 60)
438 		yyerror("timezone is unreasonable");
439 	else
440 		hadtz = 1;
441 }
442