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