1 %{ 2 /* $NetBSD: gram.y,v 1.52 2015/09/01 13:42:48 uebayasi Exp $ */ 3 4 /* 5 * Copyright (c) 1992, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This software was developed by the Computer Systems Engineering group 9 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 10 * contributed to Berkeley. 11 * 12 * All advertising materials mentioning features or use of this software 13 * must display the following acknowledgement: 14 * This product includes software developed by the University of 15 * California, Lawrence Berkeley Laboratories. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions 19 * are met: 20 * 1. Redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer. 22 * 2. Redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution. 25 * 3. Neither the name of the University nor the names of its contributors 26 * may be used to endorse or promote products derived from this software 27 * without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 * 41 * from: @(#)gram.y 8.1 (Berkeley) 6/6/93 42 */ 43 44 #include <sys/cdefs.h> 45 __RCSID("$NetBSD: gram.y,v 1.52 2015/09/01 13:42:48 uebayasi Exp $"); 46 47 #include <sys/types.h> 48 #include <sys/param.h> 49 #include <ctype.h> 50 #include <stdio.h> 51 #include <stdlib.h> 52 #include <string.h> 53 #include <errno.h> 54 #include "defs.h" 55 #include "sem.h" 56 57 #define FORMAT(n) (((n).fmt == 8 && (n).val != 0) ? "0%llo" : \ 58 ((n).fmt == 16) ? "0x%llx" : "%lld") 59 60 #define stop(s) cfgerror(s), exit(1) 61 62 static struct config conf; /* at most one active at a time */ 63 64 65 /* 66 * Allocation wrapper functions 67 */ 68 static void wrap_alloc(void *ptr, unsigned code); 69 static void wrap_continue(void); 70 static void wrap_cleanup(void); 71 72 /* 73 * Allocation wrapper type codes 74 */ 75 #define WRAP_CODE_nvlist 1 76 #define WRAP_CODE_defoptlist 2 77 #define WRAP_CODE_loclist 3 78 #define WRAP_CODE_attrlist 4 79 #define WRAP_CODE_condexpr 5 80 81 /* 82 * The allocation wrappers themselves 83 */ 84 #define DECL_ALLOCWRAP(t) static struct t *wrap_mk_##t(struct t *arg) 85 86 DECL_ALLOCWRAP(nvlist); 87 DECL_ALLOCWRAP(defoptlist); 88 DECL_ALLOCWRAP(loclist); 89 DECL_ALLOCWRAP(attrlist); 90 DECL_ALLOCWRAP(condexpr); 91 92 /* allow shorter names */ 93 #define wrap_mk_loc(p) wrap_mk_loclist(p) 94 #define wrap_mk_cx(p) wrap_mk_condexpr(p) 95 96 /* 97 * Macros for allocating new objects 98 */ 99 100 /* old-style for struct nvlist */ 101 #define new0(n,s,p,i,x) wrap_mk_nvlist(newnv(n, s, p, i, x)) 102 #define new_n(n) new0(n, NULL, NULL, 0, NULL) 103 #define new_nx(n, x) new0(n, NULL, NULL, 0, x) 104 #define new_ns(n, s) new0(n, s, NULL, 0, NULL) 105 #define new_si(s, i) new0(NULL, s, NULL, i, NULL) 106 #define new_nsi(n,s,i) new0(n, s, NULL, i, NULL) 107 #define new_np(n, p) new0(n, NULL, p, 0, NULL) 108 #define new_s(s) new0(NULL, s, NULL, 0, NULL) 109 #define new_p(p) new0(NULL, NULL, p, 0, NULL) 110 #define new_px(p, x) new0(NULL, NULL, p, 0, x) 111 #define new_sx(s, x) new0(NULL, s, NULL, 0, x) 112 #define new_nsx(n,s,x) new0(n, s, NULL, 0, x) 113 #define new_i(i) new0(NULL, NULL, NULL, i, NULL) 114 115 /* new style, type-polymorphic; ordinary and for types with multiple flavors */ 116 #define MK0(t) wrap_mk_##t(mk_##t()) 117 #define MK1(t, a0) wrap_mk_##t(mk_##t(a0)) 118 #define MK2(t, a0, a1) wrap_mk_##t(mk_##t(a0, a1)) 119 #define MK3(t, a0, a1, a2) wrap_mk_##t(mk_##t(a0, a1, a2)) 120 121 #define MKF0(t, f) wrap_mk_##t(mk_##t##_##f()) 122 #define MKF1(t, f, a0) wrap_mk_##t(mk_##t##_##f(a0)) 123 #define MKF2(t, f, a0, a1) wrap_mk_##t(mk_##t##_##f(a0, a1)) 124 125 /* 126 * Data constructors 127 */ 128 129 static struct defoptlist *mk_defoptlist(const char *, const char *, 130 const char *); 131 static struct loclist *mk_loc(const char *, const char *, long long); 132 static struct loclist *mk_loc_val(const char *, struct loclist *); 133 static struct attrlist *mk_attrlist(struct attrlist *, struct attr *); 134 static struct condexpr *mk_cx_atom(const char *); 135 static struct condexpr *mk_cx_not(struct condexpr *); 136 static struct condexpr *mk_cx_and(struct condexpr *, struct condexpr *); 137 static struct condexpr *mk_cx_or(struct condexpr *, struct condexpr *); 138 139 /* 140 * Other private functions 141 */ 142 143 static void setmachine(const char *, const char *, struct nvlist *, int); 144 static void check_maxpart(void); 145 146 static struct loclist *present_loclist(struct loclist *ll); 147 static void app(struct loclist *, struct loclist *); 148 static struct loclist *locarray(const char *, int, struct loclist *, int); 149 static struct loclist *namelocvals(const char *, struct loclist *); 150 151 %} 152 153 %union { 154 struct attr *attr; 155 struct devbase *devb; 156 struct deva *deva; 157 struct nvlist *list; 158 struct defoptlist *defoptlist; 159 struct loclist *loclist; 160 struct attrlist *attrlist; 161 struct condexpr *condexpr; 162 const char *str; 163 struct numconst num; 164 int64_t val; 165 u_char flag; 166 devmajor_t devmajor; 167 int32_t i32; 168 } 169 170 %token AND AT ATTACH 171 %token BLOCK BUILD 172 %token CHAR COLONEQ COMPILE_WITH CONFIG 173 %token DEFFS DEFINE DEFOPT DEFPARAM DEFFLAG DEFPSEUDO DEFPSEUDODEV 174 %token DEVICE DEVCLASS DUMPS DEVICE_MAJOR 175 %token ENDFILE 176 %token XFILE FILE_SYSTEM FLAGS 177 %token IDENT IOCONF 178 %token LINKZERO 179 %token XMACHINE MAJOR MAKEOPTIONS MAXUSERS MAXPARTITIONS MINOR 180 %token NEEDS_COUNT NEEDS_FLAG NO 181 %token XOBJECT OBSOLETE ON OPTIONS 182 %token PACKAGE PLUSEQ PREFIX BUILDPREFIX PSEUDO_DEVICE PSEUDO_ROOT 183 %token ROOT 184 %token SELECT SINGLE SOURCE 185 %token TYPE 186 %token VECTOR VERSION 187 %token WITH 188 %token <num> NUMBER 189 %token <str> PATHNAME QSTRING WORD EMPTYSTRING 190 %token ENDDEFS 191 192 %type <condexpr> fopts condexpr condatom 193 %type <condexpr> cond_or_expr cond_and_expr cond_prefix_expr 194 %type <condexpr> cond_base_expr 195 %type <str> fs_spec 196 %type <flag> fflags fflag oflags oflag 197 %type <str> rule 198 %type <attr> depend 199 %type <devb> devbase 200 %type <deva> devattach_opt 201 %type <list> atlist 202 %type <loclist> interface_opt 203 %type <str> atname 204 %type <loclist> loclist locdef 205 %type <str> locdefault 206 %type <loclist> values locdefaults 207 %type <attrlist> depend_list depends 208 %type <loclist> locators locator 209 %type <list> dev_spec 210 %type <str> device_instance 211 %type <str> attachment 212 %type <str> value 213 %type <val> major_minor 214 %type <num> signed_number 215 %type <i32> int32 npseudo device_flags 216 %type <str> deffs 217 %type <list> deffses 218 %type <defoptlist> defopt 219 %type <defoptlist> defopts 220 %type <str> optdepend 221 %type <list> optdepends 222 %type <list> optdepend_list 223 %type <str> optfile_opt 224 %type <list> subarches 225 %type <str> filename stringvalue locname mkvarname 226 %type <devmajor> device_major_block device_major_char 227 %type <list> devnodes devnodetype devnodeflags devnode_dims 228 229 %% 230 231 /* 232 * A complete configuration consists of both the selection part (a 233 * kernel config such as GENERIC or SKYNET, plus also the various 234 * std.* files), which selects the material to be in the kernel, and 235 * also the definition part (files, files.*, etc.) that declares what 236 * material is available to be placed in kernels. 237 * 238 * The two parts have almost entirely separate syntaxes. This grammar 239 * covers both of them. When config is run on a kernel configuration 240 * file, the std.* file for the port is included explicitly. The 241 * files.* files are included implicitly when the std.* file declares 242 * the machine type. 243 * 244 * The machine spec, which brings in the definition part, must appear 245 * before all configuration material except for the "topthings"; these 246 * are the "source" and "build" declarations that tell config where 247 * things are. These are not used by default. 248 * 249 * A previous version of this comment contained the following text: 250 * 251 * Note that we do not have sufficient keywords to enforce any 252 * order between elements of "topthings" without introducing 253 * shift/reduce conflicts. Instead, check order requirements in 254 * the C code. 255 * 256 * As of March 2012 this comment makes no sense, as there are only two 257 * topthings and no reason for them to be forcibly ordered. 258 * Furthermore, the statement about conflicts is false. 259 */ 260 261 /* Complete configuration. */ 262 configuration: 263 topthings machine_spec definition_part selection_part 264 ; 265 266 /* Sequence of zero or more topthings. */ 267 topthings: 268 /* empty */ 269 | topthings topthing 270 ; 271 272 /* Directory specification. */ 273 topthing: 274 '\n' 275 | SOURCE filename '\n' { if (!srcdir) srcdir = $2; } 276 | BUILD filename '\n' { if (!builddir) builddir = $2; } 277 ; 278 279 /* "machine foo" from std.whatever */ 280 machine_spec: 281 XMACHINE WORD '\n' { setmachine($2,NULL,NULL,0); } 282 | XMACHINE WORD WORD '\n' { setmachine($2,$3,NULL,0); } 283 | XMACHINE WORD WORD subarches '\n' { setmachine($2,$3,$4,0); } 284 | IOCONF WORD '\n' { setmachine($2,NULL,NULL,1); } 285 | error { stop("cannot proceed without machine or ioconf specifier"); } 286 ; 287 288 /* One or more sub-arches. */ 289 subarches: 290 WORD { $$ = new_n($1); } 291 | subarches WORD { $$ = new_nx($2, $1); } 292 ; 293 294 /************************************************************/ 295 296 /* 297 * The machine definitions grammar. 298 */ 299 300 /* Complete definition part: the contents of all files.* files. */ 301 definition_part: 302 definitions ENDDEFS { check_maxpart(); check_version(); } 303 ; 304 305 /* Zero or more definitions. Trap errors. */ 306 definitions: 307 /* empty */ 308 | definitions '\n' 309 | definitions definition '\n' { wrap_continue(); } 310 | definitions error '\n' { wrap_cleanup(); } 311 | definitions ENDFILE { enddefs(); checkfiles(); } 312 ; 313 314 /* A single definition. */ 315 definition: 316 define_file 317 | define_object 318 | define_device_major 319 | define_prefix 320 | define_buildprefix 321 | define_devclass 322 | define_filesystems 323 | define_attribute 324 | define_option 325 | define_flag 326 | define_obsolete_flag 327 | define_param 328 | define_obsolete_param 329 | define_device 330 | define_device_attachment 331 | define_maxpartitions 332 | define_maxusers 333 | define_makeoptions 334 | define_pseudo 335 | define_pseudodev 336 | define_major 337 | define_version 338 ; 339 340 /* source file: file foo/bar.c bar|baz needs-flag compile-with blah */ 341 define_file: 342 XFILE filename fopts fflags rule { addfile($2, $3, $4, $5); } 343 ; 344 345 /* object file: object zot.o foo|zot needs-flag */ 346 define_object: 347 XOBJECT filename fopts oflags { addfile($2, $3, $4, NULL); } 348 ; 349 350 /* device major declaration */ 351 define_device_major: 352 DEVICE_MAJOR WORD device_major_char device_major_block fopts devnodes 353 { 354 adddevm($2, $3, $4, $5, $6); 355 do_devsw = 1; 356 } 357 ; 358 359 /* prefix delimiter */ 360 define_prefix: 361 PREFIX filename { prefix_push($2); } 362 | PREFIX { prefix_pop(); } 363 ; 364 365 define_buildprefix: 366 BUILDPREFIX filename { buildprefix_push($2); } 367 | BUILDPREFIX WORD { buildprefix_push($2); } 368 | BUILDPREFIX { buildprefix_pop(); } 369 ; 370 371 define_devclass: 372 DEVCLASS WORD { (void)defdevclass($2, NULL, NULL, 1); } 373 ; 374 375 define_filesystems: 376 DEFFS deffses optdepend_list { deffilesystem($2, $3); } 377 ; 378 379 define_attribute: 380 DEFINE WORD interface_opt depend_list 381 { (void)defattr0($2, $3, $4, 0); } 382 ; 383 384 define_option: 385 DEFOPT optfile_opt defopts optdepend_list 386 { defoption($2, $3, $4); } 387 ; 388 389 define_flag: 390 DEFFLAG optfile_opt defopts optdepend_list 391 { defflag($2, $3, $4, 0); } 392 ; 393 394 define_obsolete_flag: 395 OBSOLETE DEFFLAG optfile_opt defopts 396 { defflag($3, $4, NULL, 1); } 397 ; 398 399 define_param: 400 DEFPARAM optfile_opt defopts optdepend_list 401 { defparam($2, $3, $4, 0); } 402 ; 403 404 define_obsolete_param: 405 OBSOLETE DEFPARAM optfile_opt defopts 406 { defparam($3, $4, NULL, 1); } 407 ; 408 409 define_device: 410 DEVICE devbase interface_opt depend_list 411 { defdev($2, $3, $4, 0); } 412 ; 413 414 define_device_attachment: 415 ATTACH devbase AT atlist devattach_opt depend_list 416 { defdevattach($5, $2, $4, $6); } 417 ; 418 419 define_maxpartitions: 420 MAXPARTITIONS int32 { maxpartitions = $2; } 421 ; 422 423 define_maxusers: 424 MAXUSERS int32 int32 int32 425 { setdefmaxusers($2, $3, $4); } 426 ; 427 428 define_makeoptions: 429 MAKEOPTIONS condmkopt_list 430 ; 431 432 define_pseudo: 433 /* interface_opt in DEFPSEUDO is for backwards compatibility */ 434 DEFPSEUDO devbase interface_opt depend_list 435 { defdev($2, $3, $4, 1); } 436 ; 437 438 define_pseudodev: 439 DEFPSEUDODEV devbase interface_opt depend_list 440 { defdev($2, $3, $4, 2); } 441 ; 442 443 define_major: 444 MAJOR '{' majorlist '}' 445 ; 446 447 define_version: 448 VERSION int32 { setversion($2); } 449 ; 450 451 /* file options: optional expression of conditions */ 452 fopts: 453 /* empty */ { $$ = NULL; } 454 | condexpr { $$ = $1; } 455 ; 456 457 /* zero or more flags for a file */ 458 fflags: 459 /* empty */ { $$ = 0; } 460 | fflags fflag { $$ = $1 | $2; } 461 ; 462 463 /* one flag for a file */ 464 fflag: 465 NEEDS_COUNT { $$ = FI_NEEDSCOUNT; } 466 | NEEDS_FLAG { $$ = FI_NEEDSFLAG; } 467 ; 468 469 /* extra compile directive for a source file */ 470 rule: 471 /* empty */ { $$ = NULL; } 472 | COMPILE_WITH stringvalue { $$ = $2; } 473 ; 474 475 /* zero or more flags for an object file */ 476 oflags: 477 /* empty */ { $$ = 0; } 478 | oflags oflag { $$ = $1 | $2; } 479 ; 480 481 /* a single flag for an object file */ 482 oflag: 483 NEEDS_FLAG { $$ = FI_NEEDSFLAG; } 484 ; 485 486 /* char 55 */ 487 device_major_char: 488 /* empty */ { $$ = -1; } 489 | CHAR int32 { $$ = $2; } 490 ; 491 492 /* block 33 */ 493 device_major_block: 494 /* empty */ { $$ = -1; } 495 | BLOCK int32 { $$ = $2; } 496 ; 497 498 /* device node specification */ 499 devnodes: 500 /* empty */ { $$ = new_s("DEVNODE_DONTBOTHER"); } 501 | devnodetype ',' devnodeflags { $$ = nvcat($1, $3); } 502 | devnodetype { $$ = $1; } 503 ; 504 505 /* device nodes without flags */ 506 devnodetype: 507 SINGLE { $$ = new_s("DEVNODE_SINGLE"); } 508 | VECTOR '=' devnode_dims { $$ = nvcat(new_s("DEVNODE_VECTOR"), $3); } 509 ; 510 511 /* dimensions (?) */ 512 devnode_dims: 513 NUMBER { $$ = new_i($1.val); } 514 | NUMBER ':' NUMBER { 515 struct nvlist *__nv1, *__nv2; 516 517 __nv1 = new_i($1.val); 518 __nv2 = new_i($3.val); 519 $$ = nvcat(__nv1, __nv2); 520 } 521 ; 522 523 /* flags for device nodes */ 524 devnodeflags: 525 LINKZERO { $$ = new_s("DEVNODE_FLAG_LINKZERO");} 526 ; 527 528 /* one or more file system names */ 529 deffses: 530 deffs { $$ = new_n($1); } 531 | deffses deffs { $$ = new_nx($2, $1); } 532 ; 533 534 /* a single file system name */ 535 deffs: 536 WORD { $$ = $1; } 537 ; 538 539 /* optional locator specification */ 540 interface_opt: 541 /* empty */ { $$ = NULL; } 542 | '{' '}' { $$ = present_loclist(NULL); } 543 | '{' loclist '}' { $$ = present_loclist($2); } 544 ; 545 546 /* 547 * loclist order matters, must use right recursion 548 * XXX wot? 549 */ 550 551 /* list of locator definitions */ 552 loclist: 553 locdef { $$ = $1; } 554 | locdef ',' loclist { $$ = $1; app($1, $3); } 555 ; 556 557 /* 558 * "[ WORD locdefault ]" syntax may be unnecessary... 559 */ 560 561 /* one locator definition */ 562 locdef: 563 locname locdefault { $$ = MK3(loc, $1, $2, 0); } 564 | locname { $$ = MK3(loc, $1, NULL, 0); } 565 | '[' locname locdefault ']' { $$ = MK3(loc, $2, $3, 1); } 566 | locname '[' int32 ']' { $$ = locarray($1, $3, NULL, 0); } 567 | locname '[' int32 ']' locdefaults 568 { $$ = locarray($1, $3, $5, 0); } 569 | '[' locname '[' int32 ']' locdefaults ']' 570 { $$ = locarray($2, $4, $6, 1); } 571 ; 572 573 /* locator name */ 574 locname: 575 WORD { $$ = $1; } 576 | QSTRING { $$ = $1; } 577 ; 578 579 /* locator default value */ 580 locdefault: 581 '=' value { $$ = $2; } 582 ; 583 584 /* multiple locator default values */ 585 locdefaults: 586 '=' '{' values '}' { $$ = $3; } 587 ; 588 589 /* list of depends, may be empty */ 590 depend_list: 591 /* empty */ { $$ = NULL; } 592 | ':' depends { $$ = $2; } 593 ; 594 595 /* one or more depend items */ 596 depends: 597 depend { $$ = MK2(attrlist, NULL, $1); } 598 | depends ',' depend { $$ = MK2(attrlist, $1, $3); } 599 ; 600 601 /* one depend item (which is an attribute) */ 602 depend: 603 WORD { $$ = refattr($1); } 604 ; 605 606 /* list of option depends, may be empty */ 607 optdepend_list: 608 /* empty */ { $$ = NULL; } 609 | ':' optdepends { $$ = $2; } 610 ; 611 612 /* a list of option dependencies */ 613 optdepends: 614 optdepend { $$ = new_n($1); } 615 | optdepends ',' optdepend { $$ = new_nx($3, $1); } 616 ; 617 618 /* one option depend, which is an option name */ 619 optdepend: 620 WORD { $$ = $1; } 621 ; 622 623 624 /* list of places to attach: attach blah at ... */ 625 atlist: 626 atname { $$ = new_n($1); } 627 | atlist ',' atname { $$ = new_nx($3, $1); } 628 ; 629 630 /* a place to attach a device */ 631 atname: 632 WORD { $$ = $1; } 633 | ROOT { $$ = NULL; } 634 ; 635 636 /* one or more defined options */ 637 defopts: 638 defopt { $$ = $1; } 639 | defopts defopt { $$ = defoptlist_append($2, $1); } 640 ; 641 642 /* one defined option */ 643 defopt: 644 WORD { $$ = MK3(defoptlist, $1, NULL, NULL); } 645 | WORD '=' value { $$ = MK3(defoptlist, $1, $3, NULL); } 646 | WORD COLONEQ value { $$ = MK3(defoptlist, $1, NULL, $3); } 647 | WORD '=' value COLONEQ value { $$ = MK3(defoptlist, $1, $3, $5); } 648 ; 649 650 /* list of conditional makeoptions */ 651 condmkopt_list: 652 condmkoption 653 | condmkopt_list ',' condmkoption 654 ; 655 656 /* one conditional make option */ 657 condmkoption: 658 condexpr mkvarname PLUSEQ value { appendcondmkoption($1, $2, $4); } 659 ; 660 661 /* device name */ 662 devbase: 663 WORD { $$ = getdevbase($1); } 664 ; 665 666 /* optional attachment: with foo */ 667 devattach_opt: 668 /* empty */ { $$ = NULL; } 669 | WITH WORD { $$ = getdevattach($2); } 670 ; 671 672 /* list of major numbers */ 673 /* XXX why is this right-recursive? */ 674 majorlist: 675 majordef 676 | majorlist ',' majordef 677 ; 678 679 /* one major number */ 680 majordef: 681 devbase '=' int32 { setmajor($1, $3); } 682 ; 683 684 int32: 685 NUMBER { 686 if ($1.val > INT_MAX || $1.val < INT_MIN) 687 cfgerror("overflow %" PRId64, $1.val); 688 else 689 $$ = (int32_t)$1.val; 690 } 691 ; 692 693 /************************************************************/ 694 695 /* 696 * The selection grammar. 697 */ 698 699 /* Complete selection part: all std.* files plus selected config. */ 700 selection_part: 701 selections 702 ; 703 704 /* Zero or more config items. Trap errors. */ 705 selections: 706 /* empty */ 707 | selections '\n' 708 | selections selection '\n' { wrap_continue(); } 709 | selections error '\n' { wrap_cleanup(); } 710 ; 711 712 /* One config item. */ 713 selection: 714 definition 715 | select_attr 716 | select_no_attr 717 | select_no_filesystems 718 | select_filesystems 719 | select_no_makeoptions 720 | select_makeoptions 721 | select_no_options 722 | select_options 723 | select_maxusers 724 | select_ident 725 | select_no_ident 726 | select_config 727 | select_no_config 728 | select_no_pseudodev 729 | select_pseudodev 730 | select_pseudoroot 731 | select_no_device_instance_attachment 732 | select_no_device_attachment 733 | select_no_device_instance 734 | select_device_instance 735 ; 736 737 select_attr: 738 SELECT WORD { addattr($2); } 739 ; 740 741 select_no_attr: 742 NO SELECT WORD { delattr($3); } 743 ; 744 745 select_no_filesystems: 746 NO FILE_SYSTEM no_fs_list 747 ; 748 749 select_filesystems: 750 FILE_SYSTEM fs_list 751 ; 752 753 select_no_makeoptions: 754 NO MAKEOPTIONS no_mkopt_list 755 ; 756 757 select_makeoptions: 758 MAKEOPTIONS mkopt_list 759 ; 760 761 select_no_options: 762 NO OPTIONS no_opt_list 763 ; 764 765 select_options: 766 OPTIONS opt_list 767 ; 768 769 select_maxusers: 770 MAXUSERS int32 { setmaxusers($2); } 771 ; 772 773 select_ident: 774 IDENT stringvalue { setident($2); } 775 ; 776 777 select_no_ident: 778 NO IDENT { setident(NULL); } 779 ; 780 781 select_config: 782 CONFIG conf root_spec sysparam_list 783 { addconf(&conf); } 784 ; 785 786 select_no_config: 787 NO CONFIG WORD { delconf($3); } 788 ; 789 790 select_no_pseudodev: 791 NO PSEUDO_DEVICE WORD { delpseudo($3); } 792 ; 793 794 select_pseudodev: 795 PSEUDO_DEVICE WORD npseudo { addpseudo($2, $3); } 796 ; 797 798 select_pseudoroot: 799 PSEUDO_ROOT device_instance { addpseudoroot($2); } 800 ; 801 802 select_no_device_instance_attachment: 803 NO device_instance AT attachment 804 { deldevi($2, $4); } 805 ; 806 807 select_no_device_attachment: 808 NO DEVICE AT attachment { deldeva($4); } 809 ; 810 811 select_no_device_instance: 812 NO device_instance { deldev($2); } 813 ; 814 815 select_device_instance: 816 device_instance AT attachment locators device_flags 817 { adddev($1, $3, $4, $5); } 818 ; 819 820 /* list of filesystems */ 821 fs_list: 822 fsoption 823 | fs_list ',' fsoption 824 ; 825 826 /* one filesystem */ 827 fsoption: 828 WORD { addfsoption($1); } 829 ; 830 831 /* list of filesystems that had NO in front */ 832 no_fs_list: 833 no_fsoption 834 | no_fs_list ',' no_fsoption 835 ; 836 837 /* one filesystem that had NO in front */ 838 no_fsoption: 839 WORD { delfsoption($1); } 840 ; 841 842 /* list of make options */ 843 /* XXX why is this right-recursive? */ 844 mkopt_list: 845 mkoption 846 | mkopt_list ',' mkoption 847 ; 848 849 /* one make option */ 850 mkoption: 851 mkvarname '=' value { addmkoption($1, $3); } 852 | mkvarname PLUSEQ value { appendmkoption($1, $3); } 853 ; 854 855 /* list of make options that had NO in front */ 856 no_mkopt_list: 857 no_mkoption 858 | no_mkopt_list ',' no_mkoption 859 ; 860 861 /* one make option that had NO in front */ 862 /* XXX shouldn't this be mkvarname rather than WORD? */ 863 no_mkoption: 864 WORD { delmkoption($1); } 865 ; 866 867 /* list of options */ 868 opt_list: 869 option 870 | opt_list ',' option 871 ; 872 873 /* one option */ 874 option: 875 WORD { addoption($1, NULL); } 876 | WORD '=' value { addoption($1, $3); } 877 ; 878 879 /* list of options that had NO in front */ 880 no_opt_list: 881 no_option 882 | no_opt_list ',' no_option 883 ; 884 885 /* one option that had NO in front */ 886 no_option: 887 WORD { deloption($1); } 888 ; 889 890 /* the name in "config name root on ..." */ 891 conf: 892 WORD { 893 conf.cf_name = $1; 894 conf.cf_lineno = currentline(); 895 conf.cf_fstype = NULL; 896 conf.cf_root = NULL; 897 conf.cf_dump = NULL; 898 } 899 ; 900 901 /* root fs specification */ 902 root_spec: 903 ROOT on_opt dev_spec { setconf(&conf.cf_root, "root", $3); } 904 | ROOT on_opt dev_spec fs_spec { setconf(&conf.cf_root, "root", $3); } 905 ; 906 907 /* device for root fs or dump */ 908 dev_spec: 909 '?' { $$ = new_si(intern("?"), 910 (long long)NODEV); } 911 | WORD { $$ = new_si($1, 912 (long long)NODEV); } 913 | major_minor { $$ = new_si(NULL, $1); } 914 ; 915 916 /* major and minor device number */ 917 major_minor: 918 MAJOR NUMBER MINOR NUMBER { $$ = (int64_t)makedev($2.val, $4.val); } 919 ; 920 921 /* filesystem type for root fs specification */ 922 fs_spec: 923 TYPE '?' { setfstype(&conf.cf_fstype, intern("?")); } 924 | TYPE WORD { setfstype(&conf.cf_fstype, $2); } 925 ; 926 927 /* zero or more additional system parameters */ 928 sysparam_list: 929 /* empty */ 930 | sysparam_list sysparam 931 ; 932 933 /* one additional system parameter (there's only one: dumps) */ 934 sysparam: 935 DUMPS on_opt dev_spec { setconf(&conf.cf_dump, "dumps", $3); } 936 ; 937 938 /* number of pseudo devices to configure (which is optional) */ 939 npseudo: 940 /* empty */ { $$ = 1; } 941 | int32 { $$ = $1; } 942 ; 943 944 /* name of a device to configure */ 945 device_instance: 946 WORD { $$ = $1; } 947 | WORD '*' { $$ = starref($1); } 948 ; 949 950 /* name of a device to configure an attachment to */ 951 attachment: 952 ROOT { $$ = NULL; } 953 | WORD { $$ = $1; } 954 | WORD '?' { $$ = wildref($1); } 955 ; 956 957 /* zero or more locators */ 958 locators: 959 /* empty */ { $$ = NULL; } 960 | locators locator { $$ = $2; app($2, $1); } 961 ; 962 963 /* one locator */ 964 locator: 965 WORD '?' { $$ = MK3(loc, $1, NULL, 0); } 966 | WORD values { $$ = namelocvals($1, $2); } 967 ; 968 969 /* optional device flags */ 970 device_flags: 971 /* empty */ { $$ = 0; } 972 | FLAGS int32 { $$ = $2; } 973 ; 974 975 /************************************************************/ 976 977 /* 978 * conditions 979 */ 980 981 982 /* 983 * order of options is important, must use right recursion 984 * 985 * dholland 20120310: wut? 986 */ 987 988 /* expression of conditions */ 989 condexpr: 990 cond_or_expr 991 ; 992 993 cond_or_expr: 994 cond_and_expr 995 | cond_or_expr '|' cond_and_expr { $$ = MKF2(cx, or, $1, $3); } 996 ; 997 998 cond_and_expr: 999 cond_prefix_expr 1000 | cond_and_expr '&' cond_prefix_expr { $$ = MKF2(cx, and, $1, $3); } 1001 ; 1002 1003 cond_prefix_expr: 1004 cond_base_expr 1005 /* XXX notyet - need to strengthen downstream first */ 1006 /* | '!' cond_prefix_expr { $$ = MKF1(cx, not, $2); } */ 1007 ; 1008 1009 cond_base_expr: 1010 condatom { $$ = $1; } 1011 | '!' condatom { $$ = MKF1(cx, not, $2); } 1012 | '(' condexpr ')' { $$ = $2; } 1013 ; 1014 1015 /* basic element of config element expression: a config element */ 1016 condatom: 1017 WORD { $$ = MKF1(cx, atom, $1); } 1018 ; 1019 1020 /************************************************************/ 1021 1022 /* 1023 * Various nonterminals shared between the grammars. 1024 */ 1025 1026 /* variable name for make option */ 1027 mkvarname: 1028 QSTRING { $$ = $1; } 1029 | WORD { $$ = $1; } 1030 ; 1031 1032 /* optional file for an option */ 1033 optfile_opt: 1034 /* empty */ { $$ = NULL; } 1035 | filename { $$ = $1; } 1036 ; 1037 1038 /* filename. */ 1039 filename: 1040 QSTRING { $$ = $1; } 1041 | PATHNAME { $$ = $1; } 1042 ; 1043 1044 /* constant value */ 1045 value: 1046 QSTRING { $$ = $1; } 1047 | WORD { $$ = $1; } 1048 | EMPTYSTRING { $$ = $1; } 1049 | signed_number { 1050 char bf[40]; 1051 1052 (void)snprintf(bf, sizeof(bf), FORMAT($1), (long long)$1.val); 1053 $$ = intern(bf); 1054 } 1055 ; 1056 1057 /* constant value that is a string */ 1058 stringvalue: 1059 QSTRING { $$ = $1; } 1060 | WORD { $$ = $1; } 1061 ; 1062 1063 /* comma-separated list of values */ 1064 /* XXX why right-recursive? */ 1065 values: 1066 value { $$ = MKF2(loc, val, $1, NULL); } 1067 | value ',' values { $$ = MKF2(loc, val, $1, $3); } 1068 ; 1069 1070 /* possibly negative number */ 1071 signed_number: 1072 NUMBER { $$ = $1; } 1073 | '-' NUMBER { $$.fmt = $2.fmt; $$.val = -$2.val; } 1074 ; 1075 1076 /* optional ON keyword */ 1077 on_opt: 1078 /* empty */ 1079 | ON 1080 ; 1081 1082 %% 1083 1084 void 1085 yyerror(const char *s) 1086 { 1087 1088 cfgerror("%s", s); 1089 } 1090 1091 /************************************************************/ 1092 1093 /* 1094 * Wrap allocations that live on the parser stack so that we can free 1095 * them again on error instead of leaking. 1096 */ 1097 1098 #define MAX_WRAP 1000 1099 1100 struct wrap_entry { 1101 void *ptr; 1102 unsigned typecode; 1103 }; 1104 1105 static struct wrap_entry wrapstack[MAX_WRAP]; 1106 static unsigned wrap_depth; 1107 1108 /* 1109 * Remember pointer PTR with type-code CODE. 1110 */ 1111 static void 1112 wrap_alloc(void *ptr, unsigned code) 1113 { 1114 unsigned pos; 1115 1116 if (wrap_depth >= MAX_WRAP) { 1117 panic("allocation wrapper stack overflow"); 1118 } 1119 pos = wrap_depth++; 1120 wrapstack[pos].ptr = ptr; 1121 wrapstack[pos].typecode = code; 1122 } 1123 1124 /* 1125 * We succeeded; commit to keeping everything that's been allocated so 1126 * far and clear the stack. 1127 */ 1128 static void 1129 wrap_continue(void) 1130 { 1131 wrap_depth = 0; 1132 } 1133 1134 /* 1135 * We failed; destroy all the objects allocated. 1136 */ 1137 static void 1138 wrap_cleanup(void) 1139 { 1140 unsigned i; 1141 1142 /* 1143 * Destroy each item. Note that because everything allocated 1144 * is entered on the list separately, lists and trees need to 1145 * have their links blanked before being destroyed. Also note 1146 * that strings are interned elsewhere and not handled by this 1147 * mechanism. 1148 */ 1149 1150 for (i=0; i<wrap_depth; i++) { 1151 switch (wrapstack[i].typecode) { 1152 case WRAP_CODE_nvlist: 1153 nvfree(wrapstack[i].ptr); 1154 break; 1155 case WRAP_CODE_defoptlist: 1156 { 1157 struct defoptlist *dl = wrapstack[i].ptr; 1158 1159 dl->dl_next = NULL; 1160 defoptlist_destroy(dl); 1161 } 1162 break; 1163 case WRAP_CODE_loclist: 1164 { 1165 struct loclist *ll = wrapstack[i].ptr; 1166 1167 ll->ll_next = NULL; 1168 loclist_destroy(ll); 1169 } 1170 break; 1171 case WRAP_CODE_attrlist: 1172 { 1173 struct attrlist *al = wrapstack[i].ptr; 1174 1175 al->al_next = NULL; 1176 al->al_this = NULL; 1177 attrlist_destroy(al); 1178 } 1179 break; 1180 case WRAP_CODE_condexpr: 1181 { 1182 struct condexpr *cx = wrapstack[i].ptr; 1183 1184 cx->cx_type = CX_ATOM; 1185 cx->cx_atom = NULL; 1186 condexpr_destroy(cx); 1187 } 1188 break; 1189 default: 1190 panic("invalid code %u on allocation wrapper stack", 1191 wrapstack[i].typecode); 1192 } 1193 } 1194 1195 wrap_depth = 0; 1196 } 1197 1198 /* 1199 * Instantiate the wrapper functions. 1200 * 1201 * Each one calls wrap_alloc to save the pointer and then returns the 1202 * pointer again; these need to be generated with the preprocessor in 1203 * order to be typesafe. 1204 */ 1205 #define DEF_ALLOCWRAP(t) \ 1206 static struct t * \ 1207 wrap_mk_##t(struct t *arg) \ 1208 { \ 1209 wrap_alloc(arg, WRAP_CODE_##t); \ 1210 return arg; \ 1211 } 1212 1213 DEF_ALLOCWRAP(nvlist); 1214 DEF_ALLOCWRAP(defoptlist); 1215 DEF_ALLOCWRAP(loclist); 1216 DEF_ALLOCWRAP(attrlist); 1217 DEF_ALLOCWRAP(condexpr); 1218 1219 /************************************************************/ 1220 1221 /* 1222 * Data constructors 1223 * 1224 * (These are *beneath* the allocation wrappers.) 1225 */ 1226 1227 static struct defoptlist * 1228 mk_defoptlist(const char *name, const char *val, const char *lintval) 1229 { 1230 return defoptlist_create(name, val, lintval); 1231 } 1232 1233 static struct loclist * 1234 mk_loc(const char *name, const char *str, long long num) 1235 { 1236 return loclist_create(name, str, num); 1237 } 1238 1239 static struct loclist * 1240 mk_loc_val(const char *str, struct loclist *next) 1241 { 1242 struct loclist *ll; 1243 1244 ll = mk_loc(NULL, str, 0); 1245 ll->ll_next = next; 1246 return ll; 1247 } 1248 1249 static struct attrlist * 1250 mk_attrlist(struct attrlist *next, struct attr *a) 1251 { 1252 return attrlist_cons(next, a); 1253 } 1254 1255 static struct condexpr * 1256 mk_cx_atom(const char *s) 1257 { 1258 struct condexpr *cx; 1259 1260 cx = condexpr_create(CX_ATOM); 1261 cx->cx_atom = s; 1262 return cx; 1263 } 1264 1265 static struct condexpr * 1266 mk_cx_not(struct condexpr *sub) 1267 { 1268 struct condexpr *cx; 1269 1270 cx = condexpr_create(CX_NOT); 1271 cx->cx_not = sub; 1272 return cx; 1273 } 1274 1275 static struct condexpr * 1276 mk_cx_and(struct condexpr *left, struct condexpr *right) 1277 { 1278 struct condexpr *cx; 1279 1280 cx = condexpr_create(CX_AND); 1281 cx->cx_and.left = left; 1282 cx->cx_and.right = right; 1283 return cx; 1284 } 1285 1286 static struct condexpr * 1287 mk_cx_or(struct condexpr *left, struct condexpr *right) 1288 { 1289 struct condexpr *cx; 1290 1291 cx = condexpr_create(CX_OR); 1292 cx->cx_or.left = left; 1293 cx->cx_or.right = right; 1294 return cx; 1295 } 1296 1297 /************************************************************/ 1298 1299 static void 1300 setmachine(const char *mch, const char *mcharch, struct nvlist *mchsubarches, 1301 int isioconf) 1302 { 1303 char buf[MAXPATHLEN]; 1304 struct nvlist *nv; 1305 1306 if (isioconf) { 1307 if (include(_PATH_DEVNULL, ENDDEFS, 0, 0) != 0) 1308 exit(1); 1309 ioconfname = mch; 1310 return; 1311 } 1312 1313 machine = mch; 1314 machinearch = mcharch; 1315 machinesubarches = mchsubarches; 1316 1317 /* 1318 * Define attributes for all the given names 1319 */ 1320 if (defattr(machine, NULL, NULL, 0) != 0 || 1321 (machinearch != NULL && 1322 defattr(machinearch, NULL, NULL, 0) != 0)) 1323 exit(1); 1324 for (nv = machinesubarches; nv != NULL; nv = nv->nv_next) { 1325 if (defattr(nv->nv_name, NULL, NULL, 0) != 0) 1326 exit(1); 1327 } 1328 1329 /* 1330 * Set up the file inclusion stack. This empty include tells 1331 * the parser there are no more device definitions coming. 1332 */ 1333 if (include(_PATH_DEVNULL, ENDDEFS, 0, 0) != 0) 1334 exit(1); 1335 1336 /* Include arch/${MACHINE}/conf/files.${MACHINE} */ 1337 (void)snprintf(buf, sizeof(buf), "arch/%s/conf/files.%s", 1338 machine, machine); 1339 if (include(buf, ENDFILE, 0, 0) != 0) 1340 exit(1); 1341 1342 /* Include any arch/${MACHINE_SUBARCH}/conf/files.${MACHINE_SUBARCH} */ 1343 for (nv = machinesubarches; nv != NULL; nv = nv->nv_next) { 1344 (void)snprintf(buf, sizeof(buf), "arch/%s/conf/files.%s", 1345 nv->nv_name, nv->nv_name); 1346 if (include(buf, ENDFILE, 0, 0) != 0) 1347 exit(1); 1348 } 1349 1350 /* Include any arch/${MACHINE_ARCH}/conf/files.${MACHINE_ARCH} */ 1351 if (machinearch != NULL) 1352 (void)snprintf(buf, sizeof(buf), "arch/%s/conf/files.%s", 1353 machinearch, machinearch); 1354 else 1355 strlcpy(buf, _PATH_DEVNULL, sizeof(buf)); 1356 if (include(buf, ENDFILE, 0, 0) != 0) 1357 exit(1); 1358 1359 /* 1360 * Include the global conf/files. As the last thing 1361 * pushed on the stack, it will be processed first. 1362 */ 1363 if (include("conf/files", ENDFILE, 0, 0) != 0) 1364 exit(1); 1365 1366 oktopackage = 1; 1367 } 1368 1369 static void 1370 check_maxpart(void) 1371 { 1372 1373 if (maxpartitions <= 0 && ioconfname == NULL) { 1374 stop("cannot proceed without maxpartitions specifier"); 1375 } 1376 } 1377 1378 static void 1379 check_version(void) 1380 { 1381 /* 1382 * In essence, version is 0 and is not supported anymore 1383 */ 1384 if (version < CONFIG_MINVERSION) 1385 stop("your sources are out of date -- please update."); 1386 } 1387 1388 /* 1389 * Prepend a blank entry to the locator definitions so the code in 1390 * sem.c can distinguish "empty locator list" from "no locator list". 1391 * XXX gross. 1392 */ 1393 static struct loclist * 1394 present_loclist(struct loclist *ll) 1395 { 1396 struct loclist *ret; 1397 1398 ret = MK3(loc, "", NULL, 0); 1399 ret->ll_next = ll; 1400 return ret; 1401 } 1402 1403 static void 1404 app(struct loclist *p, struct loclist *q) 1405 { 1406 while (p->ll_next) 1407 p = p->ll_next; 1408 p->ll_next = q; 1409 } 1410 1411 static struct loclist * 1412 locarray(const char *name, int count, struct loclist *adefs, int opt) 1413 { 1414 struct loclist *defs = adefs; 1415 struct loclist **p; 1416 char buf[200]; 1417 int i; 1418 1419 if (count <= 0) { 1420 fprintf(stderr, "config: array with <= 0 size: %s\n", name); 1421 exit(1); 1422 } 1423 p = &defs; 1424 for(i = 0; i < count; i++) { 1425 if (*p == NULL) 1426 *p = MK3(loc, NULL, "0", 0); 1427 snprintf(buf, sizeof(buf), "%s%c%d", name, ARRCHR, i); 1428 (*p)->ll_name = i == 0 ? name : intern(buf); 1429 (*p)->ll_num = i > 0 || opt; 1430 p = &(*p)->ll_next; 1431 } 1432 *p = 0; 1433 return defs; 1434 } 1435 1436 1437 static struct loclist * 1438 namelocvals(const char *name, struct loclist *vals) 1439 { 1440 struct loclist *p; 1441 char buf[200]; 1442 int i; 1443 1444 for (i = 0, p = vals; p; i++, p = p->ll_next) { 1445 snprintf(buf, sizeof(buf), "%s%c%d", name, ARRCHR, i); 1446 p->ll_name = i == 0 ? name : intern(buf); 1447 } 1448 return vals; 1449 } 1450 1451