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