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