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