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