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