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