1 %{
2
3 /*
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
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 *
16 * %sccs.include.redist.c%
17 *
18 * @(#)gram.y 8.1 (Berkeley) 06/06/93
19 */
20
21 #include <sys/param.h>
22 #include <ctype.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include "config.h"
26 #include "sem.h"
27
28 #define FORMAT(n) ((n) > -10 && (n) < 10 ? "%d" : "0x%x")
29
30 #define stop(s) error(s), exit(1)
31
32 int include __P((const char *, int));
33 void yyerror __P((const char *));
34 int yylex __P((void));
35 extern const char *lastfile;
36
37 static struct config conf; /* at most one active at a time */
38
39 /* the following is used to recover nvlist space after errors */
40 static struct nvlist *alloc[1000];
41 static int adepth;
42 #define new0(n,s,p,i) (alloc[adepth++] = newnv(n, s, p, i))
43 #define new_n(n) new0(n, NULL, NULL, 0)
44 #define new_ns(n, s) new0(n, s, NULL, 0)
45 #define new_si(s, i) new0(NULL, s, NULL, i)
46 #define new_nsi(n,s,i) new0(n, s, NULL, i)
47 #define new_np(n, p) new0(n, NULL, p, 0)
48 #define new_s(s) new0(NULL, s, NULL, 0)
49 #define new_p(p) new0(NULL, NULL, p, 0)
50
51 static void cleanup __P((void));
52 static void setmachine __P((const char *));
53
54 %}
55
56 %union {
57 struct attr *attr;
58 struct devbase *devb;
59 struct nvlist *list;
60 const char *str;
61 int val;
62 }
63
64 %token AND AT COMPILE_WITH CONFIG DEFINE DEVICE DUMPS ENDFILE
65 %token XFILE FLAGS INCLUDE XMACHINE MAJOR MAKEOPTIONS MAXUSERS MINOR
66 %token ON OPTIONS PSEUDO_DEVICE ROOT SWAP VECTOR
67 %token <val> FFLAG NUMBER
68 %token <str> PATHNAME WORD
69
70 %type <list> fopts
71 %type <val> fflgs
72 %type <str> rule
73 %type <attr> attr
74 %type <devb> devbase
75 %type <list> atlist interface_opt
76 %type <str> atname
77 %type <list> loclist_opt loclist locdef
78 %type <str> locdefault
79 %type <list> veclist_opt veclist
80 %type <list> attrs_opt attrs
81 %type <list> locators locator
82 %type <list> swapdev_list dev_spec
83 %type <str> device_instance
84 %type <str> attachment
85 %type <str> value
86 %type <val> major_minor signed_number npseudo
87 %type <val> flags_opt
88
89 %%
90
91 /*
92 * A configuration consists of a machine type, followed by the machine
93 * definition files (via the include() mechanism), followed by the
94 * configuration specification(s) proper. In effect, this is two
95 * separate grammars, with some shared terminals and nonterminals.
96 */
97 Configuration:
98 hdrs machine_spec /* "machine foo" from machine descr. */
99 dev_defs dev_eof /* ../../conf/devices */
100 dev_defs dev_eof /* devices.foo */
101 specs; /* rest of machine description */
102
103 hdrs:
104 hdrs hdr |
105 /* empty */;
106
107 hdr:
108 include |
109 '\n';
110
111 machine_spec:
112 XMACHINE WORD = { setmachine($2); } |
113 error = { stop("cannot proceed without machine specifier"); };
114
115 dev_eof:
116 ENDFILE = { enddefs(lastfile); checkfiles(); };
117
118
119
120 /*
121 * Various nonterminals shared between the grammars.
122 */
123 file:
124 XFILE PATHNAME fopts fflgs rule = { addfile($2, $3, $4, $5); };
125
126 /* order of options is important, must use right recursion */
127 fopts:
128 WORD fopts = { ($$ = new_n($1))->nv_next = $2; } |
129 /* empty */ = { $$ = NULL; };
130
131 fflgs:
132 fflgs FFLAG = { $$ = $1 | $2; } |
133 /* empty */ = { $$ = 0; };
134
135 rule:
136 COMPILE_WITH WORD = { $$ = $2; } |
137 /* empty */ = { $$ = NULL; };
138
139 include:
140 INCLUDE WORD = { (void)include($2, '\n'); };
141
142 /*
143 * The machine definitions grammar.
144 */
145 dev_defs:
146 dev_defs dev_def |
147 /* empty */;
148
149 dev_def:
150 one_def '\n' = { adepth = 0; } |
151 '\n' |
152 error '\n' = { cleanup(); };
153
154 one_def:
155 file |
156 /* include | */
157 DEFINE WORD interface_opt = { (void)defattr($2, $3); } |
158 DEVICE devbase AT atlist veclist_opt interface_opt attrs_opt
159 = { defdev($2, 0, $4, $5, $6, $7); } |
160 MAXUSERS NUMBER NUMBER NUMBER = { setdefmaxusers($2, $3, $4); } |
161 PSEUDO_DEVICE devbase attrs_opt = { defdev($2,1,NULL,NULL,NULL,$3); } |
162 MAJOR '{' majorlist '}';
163
164 atlist:
165 atlist ',' atname = { ($$ = new_n($3))->nv_next = $1; } |
166 atname = { $$ = new_n($1); };
167
168 atname:
169 WORD = { $$ = $1; } |
170 ROOT = { $$ = NULL; };
171
172 veclist_opt:
173 VECTOR veclist = { $$ = $2; } |
174 /* empty */ = { $$ = NULL; };
175
176 /* veclist order matters, must use right recursion */
177 veclist:
178 WORD veclist = { ($$ = new_n($1))->nv_next = $2; } |
179 WORD = { $$ = new_n($1); };
180
181 devbase:
182 WORD = { $$ = getdevbase($1); };
183
184 interface_opt:
185 '{' loclist_opt '}' = { ($$ = new_n(""))->nv_next = $2; } |
186 /* empty */ = { $$ = NULL; };
187
188 loclist_opt:
189 loclist = { $$ = $1; } |
190 /* empty */ = { $$ = NULL; };
191
192 /* loclist order matters, must use right recursion */
193 loclist:
194 locdef ',' loclist = { ($$ = $1)->nv_next = $3; } |
195 locdef = { $$ = $1; };
196
197 /* "[ WORD locdefault ]" syntax may be unnecessary... */
198 locdef:
199 WORD locdefault = { $$ = new_nsi($1, $2, 0); } |
200 WORD = { $$ = new_nsi($1, NULL, 0); } |
201 '[' WORD locdefault ']' = { $$ = new_nsi($2, $3, 1); };
202
203 locdefault:
204 '=' value = { $$ = $2; };
205
206 value:
207 WORD = { $$ = $1; } |
208 signed_number = { char bf[40];
209 (void)sprintf(bf, FORMAT($1), $1);
210 $$ = intern(bf); };
211
212 signed_number:
213 NUMBER = { $$ = $1; } |
214 '-' NUMBER = { $$ = -$2; };
215
216 attrs_opt:
217 ':' attrs = { $$ = $2; } |
218 /* empty */ = { $$ = NULL; };
219
220 attrs:
221 attrs ',' attr = { ($$ = new_p($3))->nv_next = $1; } |
222 attr = { $$ = new_p($1); };
223
224 attr:
225 WORD = { $$ = getattr($1); };
226
227 majorlist:
228 majorlist ',' majordef |
229 majordef;
230
231 majordef:
232 devbase '=' NUMBER = { setmajor($1, $3); };
233
234
235
236 /*
237 * The configuration grammar.
238 */
239 specs:
240 specs spec |
241 /* empty */;
242
243 spec:
244 config_spec '\n' = { adepth = 0; } |
245 '\n' |
246 error '\n' = { cleanup(); };
247
248 config_spec:
249 file |
250 include |
251 OPTIONS opt_list |
252 MAKEOPTIONS mkopt_list |
253 MAXUSERS NUMBER = { setmaxusers($2); } |
254 CONFIG conf sysparam_list = { addconf(&conf); } |
255 PSEUDO_DEVICE WORD npseudo = { addpseudo($2, $3); } |
256 device_instance AT attachment locators flags_opt
257 = { adddev($1, $3, $4, $5); };
258
259 mkopt_list:
260 mkopt_list ',' mkoption |
261 mkoption;
262
263 mkoption:
264 WORD '=' value = { addmkoption($1, $3); }
265
266 opt_list:
267 opt_list ',' option |
268 option;
269
270 option:
271 WORD = { addoption($1, NULL); } |
272 WORD '=' value = { addoption($1, $3); };
273
274 conf:
275 WORD = { conf.cf_name = $1;
276 conf.cf_lineno = currentline();
277 conf.cf_root = NULL;
278 conf.cf_swap = NULL;
279 conf.cf_dump = NULL; };
280
281 sysparam_list:
282 sysparam_list sysparam |
283 sysparam;
284
285 sysparam:
286 ROOT on_opt dev_spec = { setconf(&conf.cf_root, "root", $3); } |
287 SWAP on_opt swapdev_list = { setconf(&conf.cf_swap, "swap", $3); } |
288 DUMPS on_opt dev_spec = { setconf(&conf.cf_dump, "dumps", $3); };
289
290 swapdev_list:
291 dev_spec AND swapdev_list = { ($$ = $1)->nv_next = $3; } |
292 dev_spec = { $$ = $1; };
293
294 dev_spec:
295 WORD = { $$ = new_si($1, NODEV); } |
296 major_minor = { $$ = new_si(NULL, $1); };
297
298 major_minor:
299 MAJOR NUMBER MINOR NUMBER = { $$ = makedev($2, $4); };
300
301 on_opt:
302 ON | /* empty */;
303
304 npseudo:
305 NUMBER = { $$ = $1; } |
306 /* empty */ = { $$ = 1; };
307
308 device_instance:
309 WORD '*' = { $$ = starref($1); } |
310 WORD = { $$ = $1; };
311
312 attachment:
313 ROOT = { $$ = NULL; } |
314 WORD '?' = { $$ = wildref($1); } |
315 WORD '*' = { $$ = starref($1); } |
316 WORD = { $$ = $1; };
317
318 locators:
319 locators locator = { ($$ = $2)->nv_next = $1; } |
320 /* empty */ = { $$ = NULL; };
321
322 locator:
323 WORD value = { $$ = new_ns($1, $2); } |
324 WORD '?' = { $$ = new_ns($1, NULL); };
325
326 flags_opt:
327 FLAGS NUMBER = { $$ = $2; } |
328 /* empty */ = { $$ = 0; };
329
330 %%
331
332 void
yyerror(s)333 yyerror(s)
334 const char *s;
335 {
336
337 error("%s", s);
338 }
339
340 /*
341 * Cleanup procedure after syntax error: release any nvlists
342 * allocated during parsing the current line.
343 */
344 static void
cleanup()345 cleanup()
346 {
347 register struct nvlist **np;
348 register int i;
349
350 for (np = alloc, i = adepth; --i >= 0; np++)
351 nvfree(*np);
352 adepth = 0;
353 }
354
355 static void
setmachine(mch)356 setmachine(mch)
357 const char *mch;
358 {
359 char buf[MAXPATHLEN];
360
361 machine = mch;
362 (void)sprintf(buf, "files.%s", mch);
363 if (include(buf, ENDFILE) ||
364 include("../../conf/files.newconf", ENDFILE))
365 exit(1);
366 }
367