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