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