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 62static struct config conf; /* at most one active at a time */ 63static int nowarn; /* if warning suppression is on */ 64 65 66/* 67 * Allocation wrapper functions 68 */ 69static void wrap_alloc(void *ptr, unsigned code); 70static void wrap_continue(void); 71static 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 87DECL_ALLOCWRAP(nvlist); 88DECL_ALLOCWRAP(defoptlist); 89DECL_ALLOCWRAP(loclist); 90DECL_ALLOCWRAP(attrlist); 91DECL_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 131static struct defoptlist *mk_defoptlist(const char *, const char *, 132 const char *); 133static struct loclist *mk_loc(const char *, const char *, long long); 134static struct loclist *mk_loc_val(const char *, struct loclist *); 135static struct attrlist *mk_attrlist(struct attrlist *, struct attr *); 136static struct condexpr *mk_cx_atom(const char *); 137static struct condexpr *mk_cx_not(struct condexpr *); 138static struct condexpr *mk_cx_and(struct condexpr *, struct condexpr *); 139static struct condexpr *mk_cx_or(struct condexpr *, struct condexpr *); 140 141/* 142 * Other private functions 143 */ 144 145static void setmachine(const char *, const char *, struct nvlist *, int); 146static void check_maxpart(void); 147 148static struct loclist *present_loclist(struct loclist *ll); 149static void app(struct loclist *, struct loclist *); 150static struct loclist *locarray(const char *, int, struct loclist *, int); 151static 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. */ 265configuration: 266 topthings machine_spec definition_part selection_part 267; 268 269/* Sequence of zero or more topthings. */ 270topthings: 271 /* empty */ 272 | topthings topthing 273; 274 275/* Directory specification. */ 276topthing: 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 */ 283machine_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. */ 292subarches: 293 WORD { $$ = new_n($1); } 294 | subarches WORD { $$ = new_nx($2, $1); } 295; 296 297no: 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. */ 309definition_part: 310 definitions ENDDEFS { 311 CFGDBG(1, "ENDDEFS"); 312 check_maxpart(); 313 check_version(); 314 } 315; 316 317/* Zero or more definitions. Trap errors. */ 318definitions: 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. */ 327definition: 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 */ 354define_file: 355 XFILE filename fopts fflags rule { addfile($2, $3, $4, $5); } 356; 357 358/* object file: object zot.o foo|zot needs-flag */ 359define_object: 360 XOBJECT filename fopts oflags { addfile($2, $3, $4, NULL); } 361; 362 363/* device major declaration */ 364define_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 */ 373define_prefix: 374 PREFIX filename { prefix_push($2); } 375 | PREFIX { prefix_pop(); } 376; 377 378define_buildprefix: 379 BUILDPREFIX filename { buildprefix_push($2); } 380 | BUILDPREFIX WORD { buildprefix_push($2); } 381 | BUILDPREFIX { buildprefix_pop(); } 382; 383 384define_devclass: 385 DEVCLASS WORD { (void)defdevclass($2, NULL, NULL, 1); } 386; 387 388define_filesystems: 389 DEFFS deffses optdepend_list { deffilesystem($2, $3); } 390; 391 392define_attribute: 393 DEFINE WORD interface_opt depend_list 394 { (void)defattr0($2, $3, $4, 0); } 395; 396 397define_option: 398 DEFOPT optfile_opt defopts optdepend_list 399 { defoption($2, $3, $4); } 400; 401 402define_flag: 403 DEFFLAG optfile_opt defopts optdepend_list 404 { defflag($2, $3, $4, 0); } 405; 406 407define_flag_mkvar: 408 MKFLAGVAR defopts 409 { mkflagvar($2); } 410 411define_obsolete_flag: 412 OBSOLETE DEFFLAG optfile_opt defopts 413 { defflag($3, $4, NULL, 1); } 414; 415 416define_param: 417 DEFPARAM optfile_opt defopts optdepend_list 418 { defparam($2, $3, $4, 0); } 419; 420 421define_obsolete_param: 422 OBSOLETE DEFPARAM optfile_opt defopts 423 { defparam($3, $4, NULL, 1); } 424; 425 426define_device: 427 DEVICE devbase interface_opt depend_list 428 { defdev($2, $3, $4, 0); } 429; 430 431define_device_attachment: 432 ATTACH devbase AT atlist devattach_opt depend_list 433 { defdevattach($5, $2, $4, $6); } 434; 435 436define_maxpartitions: 437 MAXPARTITIONS int32 { maxpartitions = $2; } 438; 439 440define_maxusers: 441 MAXUSERS int32 int32 int32 442 { setdefmaxusers($2, $3, $4); } 443; 444 445define_makeoptions: 446 MAKEOPTIONS condmkopt_list 447; 448 449define_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 455define_pseudodev: 456 DEFPSEUDODEV devbase interface_opt depend_list 457 { defdev($2, $3, $4, 2); } 458; 459 460define_major: 461 MAJOR '{' majorlist '}' 462; 463 464define_version: 465 VERSION int32 { setversion($2); } 466; 467 468/* file options: optional expression of conditions */ 469fopts: 470 /* empty */ { $$ = NULL; } 471 | condexpr { $$ = $1; } 472; 473 474/* zero or more flags for a file */ 475fflags: 476 /* empty */ { $$ = 0; } 477 | fflags fflag { $$ = $1 | $2; } 478; 479 480/* one flag for a file */ 481fflag: 482 NEEDS_COUNT { $$ = FI_NEEDSCOUNT; } 483 | NEEDS_FLAG { $$ = FI_NEEDSFLAG; } 484; 485 486/* extra compile directive for a source file */ 487rule: 488 /* empty */ { $$ = NULL; } 489 | COMPILE_WITH stringvalue { $$ = $2; } 490; 491 492/* zero or more flags for an object file */ 493oflags: 494 /* empty */ { $$ = 0; } 495 | oflags oflag { $$ = $1 | $2; } 496; 497 498/* a single flag for an object file */ 499oflag: 500 NEEDS_FLAG { $$ = FI_NEEDSFLAG; } 501; 502 503/* char 55 */ 504device_major_char: 505 /* empty */ { $$ = -1; } 506 | CHAR int32 { $$ = $2; } 507; 508 509/* block 33 */ 510device_major_block: 511 /* empty */ { $$ = -1; } 512 | BLOCK int32 { $$ = $2; } 513; 514 515/* device node specification */ 516devnodes: 517 /* empty */ { $$ = new_s("DEVNODE_DONTBOTHER"); } 518 | devnodetype ',' devnodeflags { $$ = nvcat($1, $3); } 519 | devnodetype { $$ = $1; } 520; 521 522/* device nodes without flags */ 523devnodetype: 524 SINGLE { $$ = new_s("DEVNODE_SINGLE"); } 525 | VECTOR '=' devnode_dims { $$ = nvcat(new_s("DEVNODE_VECTOR"), $3); } 526; 527 528/* dimensions (?) */ 529devnode_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 */ 541devnodeflags: 542 LINKZERO { $$ = new_s("DEVNODE_FLAG_LINKZERO");} 543; 544 545/* one or more file system names */ 546deffses: 547 deffs { $$ = new_n($1); } 548 | deffses deffs { $$ = new_nx($2, $1); } 549; 550 551/* a single file system name */ 552deffs: 553 WORD { $$ = $1; } 554; 555 556/* optional locator specification */ 557interface_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 */ 569loclist: 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 */ 579locdef: 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 */ 591locname: 592 WORD { $$ = $1; } 593 | QSTRING { $$ = $1; } 594; 595 596/* locator default value */ 597locdefault: 598 '=' value { $$ = $2; } 599; 600 601/* multiple locator default values */ 602locdefaults: 603 '=' '{' values '}' { $$ = $3; } 604; 605 606/* list of depends, may be empty */ 607depend_list: 608 /* empty */ { $$ = NULL; } 609 | ':' depends { $$ = $2; } 610; 611 612/* one or more depend items */ 613depends: 614 depend { $$ = MK2(attrlist, NULL, $1); } 615 | depends ',' depend { $$ = MK2(attrlist, $1, $3); } 616; 617 618/* one depend item (which is an attribute) */ 619depend: 620 WORD { $$ = refattr($1); } 621; 622 623/* list of option depends, may be empty */ 624optdepend_list: 625 /* empty */ { $$ = NULL; } 626 | ':' optdepends { $$ = $2; } 627; 628 629/* a list of option dependencies */ 630optdepends: 631 optdepend { $$ = new_n($1); } 632 | optdepends ',' optdepend { $$ = new_nx($3, $1); } 633; 634 635/* one option depend, which is an option name */ 636optdepend: 637 WORD { $$ = $1; } 638; 639 640 641/* list of places to attach: attach blah at ... */ 642atlist: 643 atname { $$ = new_n($1); } 644 | atlist ',' atname { $$ = new_nx($3, $1); } 645; 646 647/* a place to attach a device */ 648atname: 649 WORD { $$ = $1; } 650 | ROOT { $$ = NULL; } 651; 652 653/* one or more defined options */ 654defopts: 655 defopt { $$ = $1; } 656 | defopts defopt { $$ = defoptlist_append($2, $1); } 657; 658 659/* one defined option */ 660defopt: 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 */ 668condmkopt_list: 669 condmkoption 670 | condmkopt_list ',' condmkoption 671; 672 673/* one conditional make option */ 674condmkoption: 675 condexpr mkvarname PLUSEQ value { appendcondmkoption($1, $2, $4); } 676; 677 678/* device name */ 679devbase: 680 WORD { $$ = getdevbase($1); } 681; 682 683/* optional attachment: with foo */ 684devattach_opt: 685 /* empty */ { $$ = NULL; } 686 | WITH WORD { $$ = getdevattach($2); } 687; 688 689/* list of major numbers */ 690/* XXX why is this right-recursive? */ 691majorlist: 692 majordef 693 | majorlist ',' majordef 694; 695 696/* one major number */ 697majordef: 698 devbase '=' int32 { setmajor($1, $3); } 699; 700 701int32: 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. */ 717selection_part: 718 selections 719; 720 721/* Zero or more config items. Trap errors. */ 722selections: 723 /* empty */ 724 | selections '\n' 725 | selections selection '\n' { wrap_continue(); } 726 | selections error '\n' { wrap_cleanup(); } 727; 728 729/* One config item. */ 730selection: 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 754select_attr: 755 SELECT WORD { addattr($2); } 756; 757 758select_no_attr: 759 no SELECT WORD { delattr($3, $1); } 760; 761 762select_no_filesystems: 763 no FILE_SYSTEM { nowarn = $1; } no_fs_list { nowarn = 0; } 764; 765 766select_filesystems: 767 FILE_SYSTEM fs_list 768; 769 770select_no_makeoptions: 771 no MAKEOPTIONS { nowarn = $1; } no_mkopt_list { nowarn = 0; } 772; 773 774select_makeoptions: 775 MAKEOPTIONS mkopt_list 776; 777 778select_no_options: 779 no OPTIONS { nowarn = $1; } no_opt_list { nowarn = 0; } 780; 781 782select_options: 783 OPTIONS opt_list 784; 785 786select_maxusers: 787 MAXUSERS int32 { setmaxusers($2); } 788; 789 790select_ident: 791 IDENT stringvalue { setident($2); } 792; 793 794select_no_ident: 795 no IDENT { setident(NULL); } 796; 797 798select_config: 799 CONFIG conf root_spec sysparam_list 800 { addconf(&conf); } 801; 802 803select_no_config: 804 no CONFIG WORD { delconf($3, $1); } 805; 806 807select_no_pseudodev: 808 no PSEUDO_DEVICE WORD { delpseudo($3, $1); } 809; 810 811select_pseudodev: 812 PSEUDO_DEVICE WORD npseudo { addpseudo($2, $3); } 813; 814 815select_pseudoroot: 816 PSEUDO_ROOT device_instance { addpseudoroot($2); } 817; 818 819select_no_device_instance_attachment: 820 no device_instance AT attachment 821 { deldevi($2, $4, $1); } 822; 823 824select_no_device_attachment: 825 no DEVICE AT attachment { deldeva($4, $1); } 826; 827 828select_no_device_instance: 829 no device_instance { deldev($2, $1); } 830; 831 832select_device_instance: 833 device_instance AT attachment locators device_flags 834 { adddev($1, $3, $4, $5); } 835; 836 837/* list of filesystems */ 838fs_list: 839 fsoption 840 | fs_list ',' fsoption 841; 842 843/* one filesystem */ 844fsoption: 845 WORD { addfsoption($1); } 846; 847 848/* list of filesystems that had NO in front */ 849no_fs_list: 850 no_fsoption 851 | no_fs_list ',' no_fsoption 852; 853 854/* one filesystem that had NO in front */ 855no_fsoption: 856 WORD { delfsoption($1, nowarn); } 857; 858 859/* list of make options */ 860/* XXX why is this right-recursive? */ 861mkopt_list: 862 mkoption 863 | mkopt_list ',' mkoption 864; 865 866/* one make option */ 867mkoption: 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 */ 873no_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? */ 880no_mkoption: 881 WORD { delmkoption($1, nowarn); } 882; 883 884/* list of options */ 885opt_list: 886 option 887 | opt_list ',' option 888; 889 890/* one option */ 891option: 892 WORD { addoption($1, NULL); } 893 | WORD '=' value { addoption($1, $3); } 894; 895 896/* list of options that had NO in front */ 897no_opt_list: 898 no_option 899 | no_opt_list ',' no_option 900; 901 902/* one option that had NO in front */ 903no_option: 904 WORD { deloption($1, nowarn); } 905; 906 907/* the name in "config name root on ..." */ 908conf: 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 */ 919root_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 */ 925dev_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 */ 939major_minor: 940 MAJOR NUMBER MINOR NUMBER { $$ = (int64_t)makedev($2.val, $4.val); } 941; 942 943/* filesystem type for root fs specification */ 944fs_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 */ 950sysparam_list: 951 /* empty */ 952 | sysparam_list sysparam 953; 954 955/* one additional system parameter (there's only one: dumps) */ 956sysparam: 957 DUMPS on_opt dev_spec { setconf(&conf.cf_dump, "dumps", $3); } 958; 959 960/* number of pseudo devices to configure (which is optional) */ 961npseudo: 962 /* empty */ { $$ = 1; } 963 | int32 { $$ = $1; } 964; 965 966/* name of a device to configure */ 967device_instance: 968 WORD { $$ = $1; } 969 | WORD '*' { $$ = starref($1); } 970; 971 972/* name of a device to configure an attachment to */ 973attachment: 974 ROOT { $$ = NULL; } 975 | WORD { $$ = $1; } 976 | WORD '?' { $$ = wildref($1); } 977; 978 979/* zero or more locators */ 980locators: 981 /* empty */ { $$ = NULL; } 982 | locators locator { $$ = $2; app($2, $1); } 983; 984 985/* one locator */ 986locator: 987 WORD '?' { $$ = MK3(loc, $1, NULL, 0); } 988 | WORD values { $$ = namelocvals($1, $2); } 989; 990 991/* optional device flags */ 992device_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 */ 1011condexpr: 1012 cond_or_expr 1013; 1014 1015cond_or_expr: 1016 cond_and_expr 1017 | cond_or_expr '|' cond_and_expr { $$ = MKF2(cx, or, $1, $3); } 1018; 1019 1020cond_and_expr: 1021 cond_prefix_expr 1022 | cond_and_expr '&' cond_prefix_expr { $$ = MKF2(cx, and, $1, $3); } 1023; 1024 1025cond_prefix_expr: 1026 cond_base_expr 1027/* XXX notyet - need to strengthen downstream first */ 1028/* | '!' cond_prefix_expr { $$ = MKF1(cx, not, $2); } */ 1029; 1030 1031cond_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 */ 1038condatom: 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 */ 1049mkvarname: 1050 QSTRING { $$ = $1; } 1051 | WORD { $$ = $1; } 1052; 1053 1054/* optional file for an option */ 1055optfile_opt: 1056 /* empty */ { $$ = NULL; } 1057 | filename { $$ = $1; } 1058; 1059 1060/* filename. */ 1061filename: 1062 QSTRING { $$ = $1; } 1063 | PATHNAME { $$ = $1; } 1064; 1065 1066/* constant value */ 1067value: 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 */ 1080stringvalue: 1081 QSTRING { $$ = $1; } 1082 | WORD { $$ = $1; } 1083; 1084 1085/* comma-separated list of values */ 1086/* XXX why right-recursive? */ 1087values: 1088 value { $$ = MKF2(loc, val, $1, NULL); } 1089 | value ',' values { $$ = MKF2(loc, val, $1, $3); } 1090; 1091 1092/* possibly negative number */ 1093signed_number: 1094 NUMBER { $$ = $1; } 1095 | '-' NUMBER { $$.fmt = $2.fmt; $$.val = -$2.val; } 1096; 1097 1098/* optional ON keyword */ 1099on_opt: 1100 /* empty */ 1101 | ON 1102; 1103 1104%% 1105 1106void 1107yyerror(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 1122struct wrap_entry { 1123 void *ptr; 1124 unsigned typecode; 1125}; 1126 1127static struct wrap_entry wrapstack[MAX_WRAP]; 1128static unsigned wrap_depth; 1129 1130/* 1131 * Remember pointer PTR with type-code CODE. 1132 */ 1133static void 1134wrap_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 */ 1150static void 1151wrap_continue(void) 1152{ 1153 wrap_depth = 0; 1154} 1155 1156/* 1157 * We failed; destroy all the objects allocated. 1158 */ 1159static void 1160wrap_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 1235DEF_ALLOCWRAP(nvlist); 1236DEF_ALLOCWRAP(defoptlist); 1237DEF_ALLOCWRAP(loclist); 1238DEF_ALLOCWRAP(attrlist); 1239DEF_ALLOCWRAP(condexpr); 1240 1241/************************************************************/ 1242 1243/* 1244 * Data constructors 1245 * 1246 * (These are *beneath* the allocation wrappers.) 1247 */ 1248 1249static struct defoptlist * 1250mk_defoptlist(const char *name, const char *val, const char *lintval) 1251{ 1252 return defoptlist_create(name, val, lintval); 1253} 1254 1255static struct loclist * 1256mk_loc(const char *name, const char *str, long long num) 1257{ 1258 return loclist_create(name, str, num); 1259} 1260 1261static struct loclist * 1262mk_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 1271static struct attrlist * 1272mk_attrlist(struct attrlist *next, struct attr *a) 1273{ 1274 return attrlist_cons(next, a); 1275} 1276 1277static struct condexpr * 1278mk_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 1287static struct condexpr * 1288mk_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 1297static struct condexpr * 1298mk_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 1308static struct condexpr * 1309mk_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 1321static void 1322setmachine(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 1391static void 1392check_maxpart(void) 1393{ 1394 1395 if (maxpartitions <= 0 && ioconfname == NULL) { 1396 stop("cannot proceed without maxpartitions specifier"); 1397 } 1398} 1399 1400static void 1401check_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 */ 1415static struct loclist * 1416present_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 1425static void 1426app(struct loclist *p, struct loclist *q) 1427{ 1428 while (p->ll_next) 1429 p = p->ll_next; 1430 p->ll_next = q; 1431} 1432 1433static struct loclist * 1434locarray(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 1459static struct loclist * 1460namelocvals(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