Commit | Line | Data |
---|---|---|
90b8dad5 CT |
1 | %{ |
2 | ||
3 | /* | |
ad787160 C |
4 | * Copyright (c) 1992, 1993 |
5 | * The Regents of the University of California. All rights reserved. | |
90b8dad5 CT |
6 | * |
7 | * This software was developed by the Computer Systems Engineering group | |
8 | * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and | |
9 | * contributed to Berkeley. | |
10 | * | |
11 | * All advertising materials mentioning features or use of this software | |
12 | * must display the following acknowledgement: | |
13 | * This product includes software developed by the University of | |
14 | * California, Lawrence Berkeley Laboratories. | |
15 | * | |
ad787160 C |
16 | * Redistribution and use in source and binary forms, with or without |
17 | * modification, are permitted provided that the following conditions | |
18 | * are met: | |
19 | * 1. Redistributions of source code must retain the above copyright | |
20 | * notice, this list of conditions and the following disclaimer. | |
21 | * 2. Redistributions in binary form must reproduce the above copyright | |
22 | * notice, this list of conditions and the following disclaimer in the | |
23 | * documentation and/or other materials provided with the distribution. | |
24 | * 3. All advertising materials mentioning features or use of this software | |
25 | * must display the following acknowledgement: | |
26 | * This product includes software developed by the University of | |
27 | * California, Berkeley and its contributors. | |
28 | * 4. Neither the name of the University nor the names of its contributors | |
29 | * may be used to endorse or promote products derived from this software | |
30 | * without specific prior written permission. | |
31 | * | |
32 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
33 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
34 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
35 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
36 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
40 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
41 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
42 | * SUCH DAMAGE. | |
90b8dad5 | 43 | * |
ad787160 | 44 | * @(#)gram.y 8.1 (Berkeley) 6/6/93 |
90b8dad5 CT |
45 | */ |
46 | ||
47 | #include <sys/param.h> | |
48 | #include <ctype.h> | |
49 | #include <stdio.h> | |
50 | #include <stdlib.h> | |
51 | #include "config.h" | |
52 | #include "sem.h" | |
53 | ||
54 | #define FORMAT(n) ((n) > -10 && (n) < 10 ? "%d" : "0x%x") | |
55 | ||
56 | #define stop(s) error(s), exit(1) | |
57 | ||
58 | int include __P((const char *, int)); | |
59 | void yyerror __P((const char *)); | |
60 | int yylex __P((void)); | |
61 | extern const char *lastfile; | |
62 | ||
63 | static struct config conf; /* at most one active at a time */ | |
64 | ||
65 | /* the following is used to recover nvlist space after errors */ | |
66 | static struct nvlist *alloc[1000]; | |
67 | static int adepth; | |
68 | #define new0(n,s,p,i) (alloc[adepth++] = newnv(n, s, p, i)) | |
69 | #define new_n(n) new0(n, NULL, NULL, 0) | |
70 | #define new_ns(n, s) new0(n, s, NULL, 0) | |
71 | #define new_si(s, i) new0(NULL, s, NULL, i) | |
72 | #define new_nsi(n,s,i) new0(n, s, NULL, i) | |
73 | #define new_np(n, p) new0(n, NULL, p, 0) | |
74 | #define new_s(s) new0(NULL, s, NULL, 0) | |
75 | #define new_p(p) new0(NULL, NULL, p, 0) | |
76 | ||
77 | static void cleanup __P((void)); | |
78 | static void setmachine __P((const char *)); | |
79 | ||
80 | %} | |
81 | ||
82 | %union { | |
83 | struct attr *attr; | |
84 | struct devbase *devb; | |
85 | struct nvlist *list; | |
86 | const char *str; | |
87 | int val; | |
88 | } | |
89 | ||
90 | %token AND AT COMPILE_WITH CONFIG DEFINE DEVICE DUMPS ENDFILE | |
91 | %token XFILE FLAGS INCLUDE XMACHINE MAJOR MAKEOPTIONS MAXUSERS MINOR | |
92 | %token ON OPTIONS PSEUDO_DEVICE ROOT SWAP VECTOR | |
93 | %token <val> FFLAG NUMBER | |
94 | %token <str> PATHNAME WORD | |
95 | ||
96 | %type <list> fopts | |
97 | %type <val> fflgs | |
98 | %type <str> rule | |
99 | %type <attr> attr | |
100 | %type <devb> devbase | |
101 | %type <list> atlist interface_opt | |
102 | %type <str> atname | |
103 | %type <list> loclist_opt loclist locdef | |
104 | %type <str> locdefault | |
105 | %type <list> veclist_opt veclist | |
106 | %type <list> attrs_opt attrs | |
107 | %type <list> locators locator | |
108 | %type <list> swapdev_list dev_spec | |
109 | %type <str> device_instance | |
110 | %type <str> attachment | |
111 | %type <str> value | |
112 | %type <val> major_minor signed_number npseudo | |
113 | %type <val> flags_opt | |
114 | ||
115 | %% | |
116 | ||
117 | /* | |
118 | * A configuration consists of a machine type, followed by the machine | |
119 | * definition files (via the include() mechanism), followed by the | |
120 | * configuration specification(s) proper. In effect, this is two | |
121 | * separate grammars, with some shared terminals and nonterminals. | |
122 | */ | |
123 | Configuration: | |
124 | hdrs machine_spec /* "machine foo" from machine descr. */ | |
125 | dev_defs dev_eof /* ../../conf/devices */ | |
126 | dev_defs dev_eof /* devices.foo */ | |
127 | specs; /* rest of machine description */ | |
128 | ||
129 | hdrs: | |
130 | hdrs hdr | | |
131 | /* empty */; | |
132 | ||
133 | hdr: | |
134 | include | | |
135 | '\n'; | |
136 | ||
137 | machine_spec: | |
138 | XMACHINE WORD = { setmachine($2); } | | |
139 | error = { stop("cannot proceed without machine specifier"); }; | |
140 | ||
141 | dev_eof: | |
142 | ENDFILE = { enddefs(lastfile); checkfiles(); }; | |
143 | ||
144 | ||
145 | ||
146 | /* | |
147 | * Various nonterminals shared between the grammars. | |
148 | */ | |
149 | file: | |
150 | XFILE PATHNAME fopts fflgs rule = { addfile($2, $3, $4, $5); }; | |
151 | ||
152 | /* order of options is important, must use right recursion */ | |
153 | fopts: | |
154 | WORD fopts = { ($$ = new_n($1))->nv_next = $2; } | | |
155 | /* empty */ = { $$ = NULL; }; | |
156 | ||
157 | fflgs: | |
158 | fflgs FFLAG = { $$ = $1 | $2; } | | |
159 | /* empty */ = { $$ = 0; }; | |
160 | ||
161 | rule: | |
162 | COMPILE_WITH WORD = { $$ = $2; } | | |
163 | /* empty */ = { $$ = NULL; }; | |
164 | ||
165 | include: | |
166 | INCLUDE WORD = { (void)include($2, '\n'); }; | |
167 | ||
168 | /* | |
169 | * The machine definitions grammar. | |
170 | */ | |
171 | dev_defs: | |
172 | dev_defs dev_def | | |
173 | /* empty */; | |
174 | ||
175 | dev_def: | |
176 | one_def '\n' = { adepth = 0; } | | |
177 | '\n' | | |
178 | error '\n' = { cleanup(); }; | |
179 | ||
180 | one_def: | |
181 | file | | |
182 | /* include | */ | |
183 | DEFINE WORD interface_opt = { (void)defattr($2, $3); } | | |
184 | DEVICE devbase AT atlist veclist_opt interface_opt attrs_opt | |
185 | = { defdev($2, 0, $4, $5, $6, $7); } | | |
186 | MAXUSERS NUMBER NUMBER NUMBER = { setdefmaxusers($2, $3, $4); } | | |
187 | PSEUDO_DEVICE devbase attrs_opt = { defdev($2,1,NULL,NULL,NULL,$3); } | | |
188 | MAJOR '{' majorlist '}'; | |
189 | ||
190 | atlist: | |
191 | atlist ',' atname = { ($$ = new_n($3))->nv_next = $1; } | | |
192 | atname = { $$ = new_n($1); }; | |
193 | ||
194 | atname: | |
195 | WORD = { $$ = $1; } | | |
196 | ROOT = { $$ = NULL; }; | |
197 | ||
198 | veclist_opt: | |
199 | VECTOR veclist = { $$ = $2; } | | |
200 | /* empty */ = { $$ = NULL; }; | |
201 | ||
202 | /* veclist order matters, must use right recursion */ | |
203 | veclist: | |
204 | WORD veclist = { ($$ = new_n($1))->nv_next = $2; } | | |
205 | WORD = { $$ = new_n($1); }; | |
206 | ||
207 | devbase: | |
208 | WORD = { $$ = getdevbase($1); }; | |
209 | ||
210 | interface_opt: | |
211 | '{' loclist_opt '}' = { ($$ = new_n(""))->nv_next = $2; } | | |
212 | /* empty */ = { $$ = NULL; }; | |
213 | ||
214 | loclist_opt: | |
215 | loclist = { $$ = $1; } | | |
216 | /* empty */ = { $$ = NULL; }; | |
217 | ||
218 | /* loclist order matters, must use right recursion */ | |
219 | loclist: | |
220 | locdef ',' loclist = { ($$ = $1)->nv_next = $3; } | | |
221 | locdef = { $$ = $1; }; | |
222 | ||
223 | /* "[ WORD locdefault ]" syntax may be unnecessary... */ | |
224 | locdef: | |
225 | WORD locdefault = { $$ = new_nsi($1, $2, 0); } | | |
226 | WORD = { $$ = new_nsi($1, NULL, 0); } | | |
227 | '[' WORD locdefault ']' = { $$ = new_nsi($2, $3, 1); }; | |
228 | ||
229 | locdefault: | |
230 | '=' value = { $$ = $2; }; | |
231 | ||
232 | value: | |
233 | WORD = { $$ = $1; } | | |
234 | signed_number = { char bf[40]; | |
235 | (void)sprintf(bf, FORMAT($1), $1); | |
236 | $$ = intern(bf); }; | |
237 | ||
238 | signed_number: | |
239 | NUMBER = { $$ = $1; } | | |
240 | '-' NUMBER = { $$ = -$2; }; | |
241 | ||
242 | attrs_opt: | |
243 | ':' attrs = { $$ = $2; } | | |
244 | /* empty */ = { $$ = NULL; }; | |
245 | ||
246 | attrs: | |
247 | attrs ',' attr = { ($$ = new_p($3))->nv_next = $1; } | | |
248 | attr = { $$ = new_p($1); }; | |
249 | ||
250 | attr: | |
251 | WORD = { $$ = getattr($1); }; | |
252 | ||
253 | majorlist: | |
254 | majorlist ',' majordef | | |
255 | majordef; | |
256 | ||
257 | majordef: | |
258 | devbase '=' NUMBER = { setmajor($1, $3); }; | |
259 | ||
260 | ||
261 | ||
262 | /* | |
263 | * The configuration grammar. | |
264 | */ | |
265 | specs: | |
266 | specs spec | | |
267 | /* empty */; | |
268 | ||
269 | spec: | |
270 | config_spec '\n' = { adepth = 0; } | | |
271 | '\n' | | |
272 | error '\n' = { cleanup(); }; | |
273 | ||
274 | config_spec: | |
275 | file | | |
276 | include | | |
277 | OPTIONS opt_list | | |
278 | MAKEOPTIONS mkopt_list | | |
279 | MAXUSERS NUMBER = { setmaxusers($2); } | | |
280 | CONFIG conf sysparam_list = { addconf(&conf); } | | |
281 | PSEUDO_DEVICE WORD npseudo = { addpseudo($2, $3); } | | |
282 | device_instance AT attachment locators flags_opt | |
283 | = { adddev($1, $3, $4, $5); }; | |
284 | ||
285 | mkopt_list: | |
286 | mkopt_list ',' mkoption | | |
287 | mkoption; | |
288 | ||
289 | mkoption: | |
290 | WORD '=' value = { addmkoption($1, $3); } | |
291 | ||
292 | opt_list: | |
293 | opt_list ',' option | | |
294 | option; | |
295 | ||
296 | option: | |
297 | WORD = { addoption($1, NULL); } | | |
298 | WORD '=' value = { addoption($1, $3); }; | |
299 | ||
300 | conf: | |
301 | WORD = { conf.cf_name = $1; | |
302 | conf.cf_lineno = currentline(); | |
303 | conf.cf_root = NULL; | |
304 | conf.cf_swap = NULL; | |
305 | conf.cf_dump = NULL; }; | |
306 | ||
307 | sysparam_list: | |
308 | sysparam_list sysparam | | |
309 | sysparam; | |
310 | ||
311 | sysparam: | |
312 | ROOT on_opt dev_spec = { setconf(&conf.cf_root, "root", $3); } | | |
313 | SWAP on_opt swapdev_list = { setconf(&conf.cf_swap, "swap", $3); } | | |
314 | DUMPS on_opt dev_spec = { setconf(&conf.cf_dump, "dumps", $3); }; | |
315 | ||
316 | swapdev_list: | |
317 | dev_spec AND swapdev_list = { ($$ = $1)->nv_next = $3; } | | |
318 | dev_spec = { $$ = $1; }; | |
319 | ||
320 | dev_spec: | |
321 | WORD = { $$ = new_si($1, NODEV); } | | |
322 | major_minor = { $$ = new_si(NULL, $1); }; | |
323 | ||
324 | major_minor: | |
325 | MAJOR NUMBER MINOR NUMBER = { $$ = makedev($2, $4); }; | |
326 | ||
327 | on_opt: | |
328 | ON | /* empty */; | |
329 | ||
330 | npseudo: | |
331 | NUMBER = { $$ = $1; } | | |
332 | /* empty */ = { $$ = 1; }; | |
333 | ||
334 | device_instance: | |
335 | WORD '*' = { $$ = starref($1); } | | |
336 | WORD = { $$ = $1; }; | |
337 | ||
338 | attachment: | |
339 | ROOT = { $$ = NULL; } | | |
340 | WORD '?' = { $$ = wildref($1); } | | |
341 | WORD '*' = { $$ = starref($1); } | | |
342 | WORD = { $$ = $1; }; | |
343 | ||
344 | locators: | |
345 | locators locator = { ($$ = $2)->nv_next = $1; } | | |
346 | /* empty */ = { $$ = NULL; }; | |
347 | ||
348 | locator: | |
349 | WORD value = { $$ = new_ns($1, $2); } | | |
350 | WORD '?' = { $$ = new_ns($1, NULL); }; | |
351 | ||
352 | flags_opt: | |
353 | FLAGS NUMBER = { $$ = $2; } | | |
354 | /* empty */ = { $$ = 0; }; | |
355 | ||
356 | %% | |
357 | ||
358 | void | |
359 | yyerror(s) | |
360 | const char *s; | |
361 | { | |
362 | ||
363 | error("%s", s); | |
364 | } | |
365 | ||
366 | /* | |
367 | * Cleanup procedure after syntax error: release any nvlists | |
368 | * allocated during parsing the current line. | |
369 | */ | |
370 | static void | |
371 | cleanup() | |
372 | { | |
373 | register struct nvlist **np; | |
374 | register int i; | |
375 | ||
376 | for (np = alloc, i = adepth; --i >= 0; np++) | |
377 | nvfree(*np); | |
378 | adepth = 0; | |
379 | } | |
380 | ||
381 | static void | |
382 | setmachine(mch) | |
383 | const char *mch; | |
384 | { | |
385 | char buf[MAXPATHLEN]; | |
386 | ||
387 | machine = mch; | |
388 | (void)sprintf(buf, "files.%s", mch); | |
43fbfd6c CT |
389 | if (include(buf, ENDFILE) || |
390 | include("../../conf/files.newconf", ENDFILE)) | |
90b8dad5 CT |
391 | exit(1); |
392 | } |