2 /* $NetBSD: gram.y,v 1.18 2008/12/28 01:23:46 christos Exp $ */
5 * Copyright (c) 1992, 1993
6 * The Regents of the University of California. All rights reserved.
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.
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.
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
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.
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
41 * from: @(#)gram.y 8.1 (Berkeley) 6/6/93
44 #include <sys/types.h>
45 #include <sys/param.h>
54 #define FORMAT(n) (((n).fmt == 8 && (n).val != 0) ? "0%llo" : \
55 ((n
).fmt
== 16) ?
"0x%llx" : "%lld")
57 #define stop(s) cfgerror(s), exit(1)
59 static struct config conf
; /* at most one active at a time */
61 /* the following is used to recover nvlist space after errors */
62 static struct nvlist
*alloc
[1000];
64 #define new0(n,s,p,i,x) (alloc[adepth++] = newnv(n, s, p, i, x))
65 #define new_n(n) new0(n, NULL, NULL, 0, NULL)
66 #define new_nx(n, x) new0(n, NULL, NULL, 0, x)
67 #define new_ns(n, s) new0(n, s, NULL, 0, NULL)
68 #define new_si(s, i) new0(NULL, s, NULL, i, NULL)
69 #define new_nsi(n,s,i) new0(n, s, NULL, i, NULL)
70 #define new_np(n, p) new0(n, NULL, p, 0, NULL)
71 #define new_s(s) new0(NULL, s, NULL, 0, NULL)
72 #define new_p(p) new0(NULL, NULL, p, 0, NULL)
73 #define new_px(p, x) new0(NULL, NULL, p, 0, x)
74 #define new_sx(s, x) new0(NULL, s, NULL, 0, x)
75 #define new_nsx(n,s,x) new0(n, s, NULL, 0, x)
77 #define fx_atom(s) new0(s, NULL, NULL, FX_ATOM, NULL)
78 #define fx_not(e) new0(NULL, NULL, NULL, FX_NOT, e)
79 #define fx_and(e1, e2) new0(NULL, NULL, e1, FX_AND, e2)
80 #define fx_or(e1, e2) new0(NULL, NULL, e1, FX_OR, e2)
82 static void cleanup
(void);
83 static void setmachine
(const char *, const char *, struct nvlist
*);
84 static void check_maxpart
(void);
86 static void app
(struct nvlist
*, struct nvlist
*);
88 static struct nvlist
*mk_nsis
(const char *, int, struct nvlist
*, int);
89 static struct nvlist
*mk_ns
(const char *, struct nvlist
*);
105 %token CHAR COLONEQ COMPILE_WITH CONFIG
106 %token DEFFS DEFINE DEFOPT DEFPARAM DEFFLAG DEFPSEUDO DEFPSEUDODEV
107 %token DEVICE DEVCLASS DUMPS DEVICE_MAJOR
109 %token XFILE FILE_SYSTEM FLAGS
111 %token XMACHINE MAJOR MAKEOPTIONS MAXUSERS MAXPARTITIONS MINOR
112 %token NEEDS_COUNT NEEDS_FLAG NO
113 %token XOBJECT OBSOLETE ON OPTIONS
114 %token PACKAGE PLUSEQ PREFIX PSEUDO_DEVICE
121 %token
<str
> PATHNAME QSTRING WORD EMPTYSTRING
127 %type
<list
> fopts fexpr fatom
129 %type
<val
> fflgs fflag oflgs oflag
133 %type
<deva
> devattach_opt
134 %type
<list
> atlist interface_opt
136 %type
<list
> loclist_opt loclist locdef
137 %type
<str
> locdefault
138 %type
<list
> values locdefaults
139 %type
<list
> attrs_opt attrs
140 %type
<list
> locators locator
141 %type
<list
> dev_spec
142 %type
<str
> device_instance
143 %type
<str
> attachment
145 %type
<val
> major_minor npseudo
146 %type
<num
> signed_number
147 %type
<val
> flags_opt
150 %type
<str
> fsoptfile_opt
155 %type
<list
> defoptdeps
156 %type
<str
> optfile_opt
157 %type
<list
> subarches_opt subarches
158 %type
<str
> filename stringvalue locname mkvarname
159 %type
<val
> device_major_block device_major_char
164 * A configuration consists of a machine type, followed by the machine
165 * definition files (via the include() mechanism), followed by the
166 * configuration specification(s) proper. In effect, this is two
167 * separate grammars, with some shared terminals and nonterminals.
168 * Note that we do not have sufficient keywords to enforce any order
169 * between elements of "topthings" without introducing shift/reduce
170 * conflicts. Instead, check order requirements in the C code.
173 topthings
/* dirspecs, include "std.arch" */
174 machine_spec
/* "machine foo" from machine descr. */
175 dev_defs ENDDEFS
/* all machine definition files */
176 { check_maxpart
(); check_version
(); }
177 specs
; /* rest of machine description */
184 SOURCE filename
'\n' { if
(!srcdir
) srcdir
= $2; } |
185 BUILD filename
'\n' { if
(!builddir
) builddir
= $2; } |
189 XMACHINE WORD
'\n' { setmachine
($2,NULL
,NULL
); } |
190 XMACHINE WORD WORD subarches_opt
'\n' { setmachine
($2,$3,$4); } |
191 error { stop
("cannot proceed without machine specifier"); };
195 /* empty */ { $$
= NULL
; };
198 subarches WORD
{ $$
= new_nx
($2, $1); } |
199 WORD
{ $$
= new_n
($1); };
202 * Various nonterminals shared between the grammars.
205 XFILE filename fopts fflgs rule
{ addfile
($2, $3, $4, $5); };
208 XOBJECT filename fopts oflgs
{ addobject
($2, $3, $4); };
211 DEVICE_MAJOR WORD device_major_char device_major_block fopts
212 { adddevm
($2, $3, $4, $5); };
215 BLOCK NUMBER
{ $$
= $2.val
; } |
216 /* empty */ { $$
= -1; };
219 CHAR NUMBER
{ $$
= $2.val
; } |
220 /* empty */ { $$
= -1; };
222 /* order of options is important, must use right recursion */
225 /* empty */ { $$
= NULL
; };
229 '!' fatom
{ $$
= fx_not
($2); } |
230 fexpr
'&' fexpr
{ $$
= fx_and
($1, $3); } |
231 fexpr
'|' fexpr
{ $$
= fx_or
($1, $3); } |
232 '(' fexpr
')' { $$
= $2; };
235 WORD
{ $$
= fx_atom
($1); };
238 fflgs fflag
{ $$
= $1 |
$2; } |
239 /* empty */ { $$
= 0; };
242 NEEDS_COUNT
{ $$
= FI_NEEDSCOUNT
; } |
243 NEEDS_FLAG
{ $$
= FI_NEEDSFLAG
; };
246 oflgs oflag
{ $$
= $1 |
$2; } |
247 /* empty */ { $$
= 0; };
250 NEEDS_FLAG
{ $$
= OI_NEEDSFLAG
; };
253 COMPILE_WITH stringvalue
{ $$
= $2; } |
254 /* empty */ { $$
= NULL
; };
257 PREFIX filename
{ prefix_push
($2); } |
258 PREFIX
{ prefix_pop
(); };
261 * The machine definitions grammar.
265 dev_defs ENDFILE
{ enddefs
(); checkfiles
(); } |
269 one_def
'\n' { adepth
= 0; } |
271 error '\n' { cleanup
(); };
276 device_major
{ do_devsw
= 1; } |
278 DEVCLASS WORD
{ (void)defattr
($2, NULL
, NULL
, 1); } |
279 DEFFS fsoptfile_opt deffses defoptdeps
280 { deffilesystem
($2, $3, $4); } |
281 DEFINE WORD interface_opt attrs_opt
282 { (void)defattr
($2, $3, $4, 0); } |
283 DEFOPT optfile_opt defopts defoptdeps
284 { defoption
($2, $3, $4); } |
285 DEFFLAG optfile_opt defopts defoptdeps
286 { defflag
($2, $3, $4, 0); } |
287 OBSOLETE DEFFLAG optfile_opt defopts
288 { defflag
($3, $4, NULL
, 1); } |
289 DEFPARAM optfile_opt defopts defoptdeps
290 { defparam
($2, $3, $4, 0); } |
291 OBSOLETE DEFPARAM optfile_opt defopts
292 { defparam
($3, $4, NULL
, 1); } |
293 DEVICE devbase interface_opt attrs_opt
294 { defdev
($2, $3, $4, 0); } |
295 ATTACH devbase AT atlist devattach_opt attrs_opt
296 { defdevattach
($5, $2, $4, $6); } |
297 MAXPARTITIONS NUMBER
{ maxpartitions
= $2.val
; } |
298 MAXUSERS NUMBER NUMBER NUMBER
{ setdefmaxusers
($2.val
, $3.val
, $4.val
); } |
299 MAKEOPTIONS condmkopt_list |
300 /* interface_opt in DEFPSEUDO is for backwards compatibility */
301 DEFPSEUDO devbase interface_opt attrs_opt
302 { defdev
($2, $3, $4, 1); } |
303 DEFPSEUDODEV devbase interface_opt attrs_opt
304 { defdev
($2, $3, $4, 2); } |
305 MAJOR
'{' majorlist
'}' |
306 VERSION NUMBER
{ setversion
($2.val
); };
309 atlist
',' atname
{ $$
= new_nx
($3, $1); } |
310 atname
{ $$
= new_n
($1); };
317 deffses deffs
{ $$
= new_nx
($2, $1); } |
318 deffs
{ $$
= new_n
($1); };
324 ':' optdeps
{ $$
= $2; } |
325 /* empty */ { $$
= NULL
; };
328 optdeps
',' optdep
{ $$
= new_nx
($3, $1); } |
329 optdep
{ $$
= new_n
($1); };
335 defopts defopt
{ $$
= nvcat
($2, $1); } |
339 WORD
{ $$
= new_n
($1); } |
340 WORD
'=' value
{ $$
= new_ns
($1, $3); } |
342 struct nvlist
*__nv
=
344 $$
= new_nsx
("", $3, __nv
);
346 WORD
'=' value COLONEQ value
{
347 struct nvlist
*__nv
=
349 $$
= new_nsx
("", $5, __nv
);
353 WORD
{ $$
= getdevbase
($1); };
356 WITH WORD
{ $$
= getdevattach
($2); } |
357 /* empty */ { $$
= NULL
; };
360 '{' loclist_opt
'}' { $$
= new_nx
("", $2); } |
361 /* empty */ { $$
= NULL
; };
364 loclist
{ $$
= $1; } |
365 /* empty */ { $$
= NULL
; };
367 /* loclist order matters, must use right recursion */
369 locdef
',' loclist
{ $$
= $1; app
($1, $3); } |
372 /* "[ WORD locdefault ]" syntax may be unnecessary... */
374 locname locdefault
{ $$
= new_nsi
($1, $2, 0); } |
375 locname
{ $$
= new_nsi
($1, NULL
, 0); } |
376 '[' locname locdefault
']' { $$
= new_nsi
($2, $3, 1); } |
377 locname
'[' NUMBER
']' { $$
= mk_nsis
($1, $3.val
, NULL
, 0); } |
378 locname
'[' NUMBER
']' locdefaults
379 { $$
= mk_nsis
($1, $3.val
, $5, 0); } |
380 '[' locname
'[' NUMBER
']' locdefaults
']'
381 { $$
= mk_nsis
($2, $4.val
, $6, 1); };
385 QSTRING
{ $$
= $1; };
388 '=' value
{ $$
= $2; };
391 '=' '{' values
'}' { $$
= $3; };
394 filename
{ $$
= $1; } |
395 /* empty */ { $$
= NULL
; };
398 filename
{ $$
= $1; } |
399 /* empty */ { $$
= NULL
; };
402 QSTRING
{ $$
= $1; } |
403 PATHNAME
{ $$
= $1; };
406 QSTRING
{ $$
= $1; } |
408 EMPTYSTRING
{ $$
= $1; } |
409 signed_number
{ char bf
[40];
410 (void)snprintf
(bf
, sizeof
(bf
),
411 FORMAT
($1), (long long)$1.val
);
415 QSTRING
{ $$
= $1; } |
419 value
',' values
{ $$
= new_sx
($1, $3); } |
420 value
{ $$
= new_s
($1); };
423 NUMBER
{ $$
= $1; } |
424 '-' NUMBER
{ $$.fmt
= $2.fmt
; $$.val
= -$2.val
; };
427 ':' attrs
{ $$
= $2; } |
428 /* empty */ { $$
= NULL
; };
431 attrs
',' attr
{ $$
= new_px
($3, $1); } |
432 attr
{ $$
= new_p
($1); };
435 WORD
{ $$
= getattr
($1); };
438 majorlist
',' majordef |
442 devbase
'=' NUMBER
{ setmajor
($1, $3.val
); };
446 * The configuration grammar.
453 config_spec
'\n' { adepth
= 0; } |
455 error '\n' { cleanup
(); };
459 NO FILE_SYSTEM no_fs_list |
460 FILE_SYSTEM fs_list |
461 NO MAKEOPTIONS no_mkopt_list |
462 MAKEOPTIONS mkopt_list |
463 NO OPTIONS no_opt_list |
465 MAXUSERS NUMBER
{ setmaxusers
($2.val
); } |
466 IDENT stringvalue
{ setident
($2); } |
467 CONFIG conf root_spec sysparam_list
468 { addconf
(&conf
); } |
469 NO CONFIG WORD
{ delconf
($3); } |
470 NO PSEUDO_DEVICE WORD
{ delpseudo
($3); } |
471 PSEUDO_DEVICE WORD npseudo
{ addpseudo
($2, $3); } |
472 NO device_instance AT attachment
473 { deldevi
($2, $4); } |
474 NO DEVICE AT attachment
{ deldeva
($4); } |
475 NO device_instance
{ deldev
($2); } |
476 device_instance AT attachment locators flags_opt
477 { adddev
($1, $3, $4, $5); };
480 fs_list
',' fsoption |
484 WORD
{ addfsoption
($1); };
487 no_fs_list
',' no_fsoption |
491 WORD
{ delfsoption
($1); };
494 mkopt_list
',' mkoption |
498 QSTRING
{ $$
= $1; } |
502 mkvarname
'=' value
{ addmkoption
($1, $3); } |
503 mkvarname PLUSEQ value
{ appendmkoption
($1, $3); };
506 condmkopt_list
',' condmkoption |
510 fexpr mkvarname PLUSEQ value
{ appendcondmkoption
($1, $2, $4); };
513 no_mkopt_list
',' no_mkoption |
517 WORD
{ delmkoption
($1); }
520 opt_list
',' option |
524 WORD
{ addoption
($1, NULL
); } |
525 WORD
'=' value
{ addoption
($1, $3); };
528 no_opt_list
',' no_option |
532 WORD
{ deloption
($1); };
535 WORD
{ conf.cf_name
= $1;
536 conf.cf_lineno
= currentline
();
537 conf.cf_fstype
= NULL
;
539 conf.cf_dump
= NULL
; };
542 ROOT on_opt dev_spec fs_spec_opt
543 { setconf
(&conf.cf_root
, "root", $3); };
546 TYPE fs_spec
{ setfstype
(&conf.cf_fstype
, $2); } |
550 '?' { $$
= intern
("?"); } |
554 sysparam_list sysparam |
558 DUMPS on_opt dev_spec
{ setconf
(&conf.cf_dump
, "dumps", $3); };
561 '?' { $$
= new_si
(intern
("?"), NODEV
); } |
562 WORD
{ $$
= new_si
($1, NODEV
); } |
563 major_minor
{ $$
= new_si
(NULL
, $1); };
566 MAJOR NUMBER MINOR NUMBER
{ $$
= makedev
($2.val
, $4.val
); };
572 NUMBER
{ $$
= $1.val
; } |
573 /* empty */ { $$
= 1; };
576 WORD
'*' { $$
= starref
($1); } |
580 ROOT
{ $$
= NULL
; } |
581 WORD
'?' { $$
= wildref
($1); } |
585 locators locator
{ $$
= $2; app
($2, $1); } |
586 /* empty */ { $$
= NULL
; };
589 WORD values
{ $$
= mk_ns
($1, $2); } |
590 WORD
'?' { $$
= new_ns
($1, NULL
); };
593 FLAGS NUMBER
{ $$
= $2.val
; } |
594 /* empty */ { $$
= 0; };
599 yyerror(const char *s
)
606 * Cleanup procedure after syntax error: release any nvlists
607 * allocated during parsing the current line.
615 for
(np
= alloc
, i
= adepth
; --i
>= 0; np
++)
621 setmachine
(const char *mch
, const char *mcharch
, struct nvlist
*mchsubarches
)
623 char buf
[MAXPATHLEN
];
627 machinearch
= mcharch
;
628 machinesubarches
= mchsubarches
;
631 * Define attributes for all the given names
633 if
(defattr
(machine
, NULL
, NULL
, 0) != 0 ||
634 (machinearch
!= NULL
&&
635 defattr
(machinearch
, NULL
, NULL
, 0) != 0))
637 for
(nv
= machinesubarches
; nv
!= NULL
; nv
= nv
->nv_next
) {
638 if
(defattr
(nv
->nv_name
, NULL
, NULL
, 0) != 0)
643 * Set up the file inclusion stack. This empty include tells
644 * the parser there are no more device definitions coming.
646 strlcpy
(buf
, _PATH_DEVNULL
, sizeof
(buf
));
647 if
(include
(buf
, ENDDEFS
, 0, 0) != 0)
650 /* Include arch/${MACHINE}/conf/files.${MACHINE} */
651 (void)snprintf
(buf
, sizeof
(buf
), "arch/%s/conf/files.%s",
653 if
(include
(buf
, ENDFILE
, 0, 0) != 0)
656 /* Include any arch/${MACHINE_SUBARCH}/conf/files.${MACHINE_SUBARCH} */
657 for
(nv
= machinesubarches
; nv
!= NULL
; nv
= nv
->nv_next
) {
658 (void)snprintf
(buf
, sizeof
(buf
), "arch/%s/conf/files.%s",
659 nv
->nv_name
, nv
->nv_name
);
660 if
(include
(buf
, ENDFILE
, 0, 0) != 0)
664 /* Include any arch/${MACHINE_ARCH}/conf/files.${MACHINE_ARCH} */
665 if
(machinearch
!= NULL
)
666 (void)snprintf
(buf
, sizeof
(buf
), "arch/%s/conf/files.%s",
667 machinearch
, machinearch
);
669 strlcpy
(buf
, _PATH_DEVNULL
, sizeof
(buf
));
670 if
(include
(buf
, ENDFILE
, 0, 0) != 0)
674 * Include the global conf/files. As the last thing
675 * pushed on the stack, it will be processed first.
677 if
(include
("conf/files", ENDFILE
, 0, 0) != 0)
687 if
(maxpartitions
<= 0) {
688 stop
("cannot proceed without maxpartitions specifier");
696 * In essence, version is 0 and is not supported anymore
698 if
(version
< CONFIG_MINVERSION
)
699 stop
("your sources are out of date -- please update.");
703 app
(struct nvlist
*p
, struct nvlist
*q
)
710 static struct nvlist
*
711 mk_nsis
(const char *name
, int count
, struct nvlist
*adefs
, int opt
)
713 struct nvlist
*defs
= adefs
;
719 fprintf
(stderr
, "config: array with <= 0 size: %s\n", name
);
723 for
(i
= 0; i
< count
; i
++) {
726 snprintf
(buf
, sizeof
(buf
), "%s%c%d", name
, ARRCHR
, i
);
727 (*p
)->nv_name
= i
== 0 ? name
: intern
(buf
);
728 (*p
)->nv_num
= i
> 0 || opt
;
736 static struct nvlist
*
737 mk_ns
(const char *name
, struct nvlist
*vals
)
743 for
(i
= 0, p
= vals
; p
; i
++, p
= p
->nv_next
) {
744 snprintf
(buf
, sizeof
(buf
), "%s%c%d", name
, ARRCHR
, i
);
745 p
->nv_name
= i
== 0 ? name
: intern
(buf
);