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