1 %union { 2 char *str; 3 int val; 4 struct file_list *file; 5 } 6 7 %token ARCH 8 %token COMMA 9 %token CONFIG 10 %token CPU 11 %token NOCPU 12 %token DEVICE 13 %token NODEVICE 14 %token ENV 15 %token EQUALS 16 %token HINTS 17 %token IDENT 18 %token MAXUSERS 19 %token PROFILE 20 %token OPTIONS 21 %token NOOPTION 22 %token MAKEOPTIONS 23 %token NOMAKEOPTION 24 %token SEMICOLON 25 %token INCLUDE 26 %token FILES 27 28 %token <str> ID 29 %token <val> NUMBER 30 31 %type <str> Save_id 32 %type <str> Opt_value 33 %type <str> Dev 34 35 %{ 36 37 /* 38 * Copyright (c) 1988, 1993 39 * The Regents of the University of California. All rights reserved. 40 * 41 * Redistribution and use in source and binary forms, with or without 42 * modification, are permitted provided that the following conditions 43 * are met: 44 * 1. Redistributions of source code must retain the above copyright 45 * notice, this list of conditions and the following disclaimer. 46 * 2. Redistributions in binary form must reproduce the above copyright 47 * notice, this list of conditions and the following disclaimer in the 48 * documentation and/or other materials provided with the distribution. 49 * 3. All advertising materials mentioning features or use of this software 50 * must display the following acknowledgement: 51 * This product includes software developed by the University of 52 * California, Berkeley and its contributors. 53 * 4. Neither the name of the University nor the names of its contributors 54 * may be used to endorse or promote products derived from this software 55 * without specific prior written permission. 56 * 57 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 58 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 59 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 60 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 61 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 62 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 63 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 64 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 65 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 66 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 67 * SUCH DAMAGE. 68 * 69 * @(#)config.y 8.1 (Berkeley) 6/6/93 70 * $FreeBSD$ 71 */ 72 73 #include <assert.h> 74 #include <ctype.h> 75 #include <err.h> 76 #include <stdio.h> 77 #include <string.h> 78 79 #include "config.h" 80 81 struct device_head dtab; 82 char *ident; 83 char *env; 84 int envmode; 85 int hintmode; 86 int yyline; 87 const char *yyfile; 88 struct file_list_head ftab; 89 struct files_name_head fntab; 90 char errbuf[80]; 91 int maxusers; 92 93 #define ns(s) strdup(s) 94 int include(const char *, int); 95 void yyerror(const char *s); 96 int yywrap(void); 97 98 static void newdev(char *name); 99 static void newfile(char *name); 100 static void rmdev_schedule(struct device_head *dh, char *name); 101 static void newopt(struct opt_head *list, char *name, char *value); 102 static void rmopt_schedule(struct opt_head *list, char *name); 103 104 static char * 105 devopt(char *dev) 106 { 107 char *ret = malloc(strlen(dev) + 5); 108 109 sprintf(ret, "DEV_%s", dev); 110 raisestr(ret); 111 return ret; 112 } 113 114 %} 115 %% 116 Configuration: 117 Many_specs 118 ; 119 120 Many_specs: 121 Many_specs Spec 122 | 123 /* lambda */ 124 ; 125 126 Spec: 127 Device_spec SEMICOLON 128 | 129 Config_spec SEMICOLON 130 | 131 INCLUDE ID SEMICOLON { 132 if (incignore == 0) 133 include($2, 0); 134 }; 135 | 136 FILES ID SEMICOLON { newfile($2); }; 137 | 138 SEMICOLON 139 | 140 error SEMICOLON 141 ; 142 143 Config_spec: 144 ARCH Save_id { 145 if (machinename != NULL && !eq($2, machinename)) 146 errx(1, "%s:%d: only one machine directive is allowed", 147 yyfile, yyline); 148 machinename = $2; 149 machinearch = $2; 150 } | 151 ARCH Save_id Save_id { 152 if (machinename != NULL && 153 !(eq($2, machinename) && eq($3, machinearch))) 154 errx(1, "%s:%d: only one machine directive is allowed", 155 yyfile, yyline); 156 machinename = $2; 157 machinearch = $3; 158 } | 159 CPU Save_id { 160 struct cputype *cp = 161 (struct cputype *)calloc(1, sizeof (struct cputype)); 162 cp->cpu_name = $2; 163 SLIST_INSERT_HEAD(&cputype, cp, cpu_next); 164 } | 165 NOCPU Save_id { 166 struct cputype *cp, *cp2; 167 SLIST_FOREACH_SAFE(cp, &cputype, cpu_next, cp2) { 168 if (eq(cp->cpu_name, $2)) { 169 SLIST_REMOVE(&cputype, cp, cputype, cpu_next); 170 free(cp); 171 } 172 } 173 } | 174 OPTIONS Opt_list 175 | 176 NOOPTION Save_id { rmopt_schedule(&opt, $2); } | 177 MAKEOPTIONS Mkopt_list 178 | 179 NOMAKEOPTION Save_id { rmopt_schedule(&mkopt, $2); } | 180 IDENT ID { ident = $2; } | 181 System_spec 182 | 183 MAXUSERS NUMBER { maxusers = $2; } | 184 PROFILE NUMBER { profiling = $2; } | 185 ENV ID { 186 env = $2; 187 envmode = 1; 188 } | 189 HINTS ID { 190 struct hint *hint; 191 192 hint = (struct hint *)calloc(1, sizeof (struct hint)); 193 hint->hint_name = $2; 194 STAILQ_INSERT_TAIL(&hints, hint, hint_next); 195 hintmode = 1; 196 } 197 198 System_spec: 199 CONFIG System_id System_parameter_list { 200 errx(1, "%s:%d: root/dump/swap specifications obsolete", 201 yyfile, yyline); 202 } 203 | 204 CONFIG System_id 205 ; 206 207 System_id: 208 Save_id { newopt(&mkopt, ns("KERNEL"), $1); }; 209 210 System_parameter_list: 211 System_parameter_list ID 212 | ID 213 ; 214 215 Opt_list: 216 Opt_list COMMA Option 217 | 218 Option 219 ; 220 221 Option: 222 Save_id { 223 newopt(&opt, $1, NULL); 224 if (strchr($1, '=') != NULL) 225 errx(1, "%s:%d: The `=' in options should not be " 226 "quoted", yyfile, yyline); 227 } | 228 Save_id EQUALS Opt_value { 229 newopt(&opt, $1, $3); 230 } ; 231 232 Opt_value: 233 ID { $$ = $1; } | 234 NUMBER { 235 char buf[80]; 236 237 (void) snprintf(buf, sizeof(buf), "%d", $1); 238 $$ = ns(buf); 239 } ; 240 241 Save_id: 242 ID { $$ = $1; } 243 ; 244 245 Mkopt_list: 246 Mkopt_list COMMA Mkoption 247 | 248 Mkoption 249 ; 250 251 Mkoption: 252 Save_id { newopt(&mkopt, $1, ns("")); } | 253 Save_id EQUALS Opt_value { newopt(&mkopt, $1, $3); } ; 254 255 Dev: 256 ID { $$ = $1; } 257 ; 258 259 Device_spec: 260 DEVICE Dev_list 261 | 262 NODEVICE NoDev_list 263 ; 264 265 Dev_list: 266 Dev_list COMMA Device 267 | 268 Device 269 ; 270 271 NoDev_list: 272 NoDev_list COMMA NoDevice 273 | 274 NoDevice 275 ; 276 277 Device: 278 Dev { 279 newopt(&opt, devopt($1), ns("1")); 280 /* and the device part */ 281 newdev($1); 282 } 283 284 NoDevice: 285 Dev { 286 char *s = devopt($1); 287 288 rmopt_schedule(&opt, s); 289 free(s); 290 /* and the device part */ 291 rmdev_schedule(&dtab, $1); 292 } ; 293 294 %% 295 296 void 297 yyerror(const char *s) 298 { 299 300 errx(1, "%s:%d: %s", yyfile, yyline + 1, s); 301 } 302 303 int 304 yywrap(void) 305 { 306 if (found_defaults) { 307 if (freopen(PREFIX, "r", stdin) == NULL) 308 err(2, "%s", PREFIX); 309 yyfile = PREFIX; 310 yyline = 0; 311 found_defaults = 0; 312 return 0; 313 } 314 return 1; 315 } 316 317 /* 318 * Add a new file to the list of files. 319 */ 320 static void 321 newfile(char *name) 322 { 323 struct files_name *nl; 324 325 nl = (struct files_name *) calloc(1, sizeof *nl); 326 nl->f_name = name; 327 STAILQ_INSERT_TAIL(&fntab, nl, f_next); 328 } 329 330 /* 331 * Find a device in the list of devices. 332 */ 333 static struct device * 334 finddev(struct device_head *dlist, char *name) 335 { 336 struct device *dp; 337 338 STAILQ_FOREACH(dp, dlist, d_next) 339 if (eq(dp->d_name, name)) 340 return (dp); 341 342 return (NULL); 343 } 344 345 /* 346 * Add a device to the list of devices. 347 */ 348 static void 349 newdev(char *name) 350 { 351 struct device *np; 352 353 if (finddev(&dtab, name)) { 354 printf("WARNING: duplicate device `%s' encountered.\n", name); 355 return; 356 } 357 358 np = (struct device *) calloc(1, sizeof *np); 359 np->d_name = name; 360 STAILQ_INSERT_TAIL(&dtab, np, d_next); 361 } 362 363 /* 364 * Schedule a device to removal. 365 */ 366 static void 367 rmdev_schedule(struct device_head *dh, char *name) 368 { 369 struct device *dp; 370 371 dp = finddev(dh, name); 372 if (dp != NULL) { 373 STAILQ_REMOVE(dh, dp, device, d_next); 374 free(dp->d_name); 375 free(dp); 376 } 377 } 378 379 /* 380 * Find an option in the list of options. 381 */ 382 static struct opt * 383 findopt(struct opt_head *list, char *name) 384 { 385 struct opt *op; 386 387 SLIST_FOREACH(op, list, op_next) 388 if (eq(op->op_name, name)) 389 return (op); 390 391 return (NULL); 392 } 393 394 /* 395 * Add an option to the list of options. 396 */ 397 static void 398 newopt(struct opt_head *list, char *name, char *value) 399 { 400 struct opt *op; 401 402 /* 403 * Ignore inclusions listed explicitly for configuration files. 404 */ 405 if (eq(name, OPT_AUTOGEN)) { 406 incignore = 1; 407 return; 408 } 409 410 if (findopt(list, name)) { 411 printf("WARNING: duplicate option `%s' encountered.\n", name); 412 return; 413 } 414 415 op = (struct opt *)calloc(1, sizeof (struct opt)); 416 op->op_name = name; 417 op->op_ownfile = 0; 418 op->op_value = value; 419 SLIST_INSERT_HEAD(list, op, op_next); 420 } 421 422 /* 423 * Remove an option from the list of options. 424 */ 425 static void 426 rmopt_schedule(struct opt_head *list, char *name) 427 { 428 struct opt *op; 429 430 op = findopt(list, name); 431 if (op != NULL) { 432 SLIST_REMOVE(list, op, opt, op_next); 433 free(op->op_name); 434 free(op); 435 } 436 } 437