1%{
2/*	$NetBSD: gram.y,v 1.23 2010/03/08 11:12:32 pooka 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
59static	struct	config conf;	/* at most one active at a time */
60
61/* the following is used to recover nvlist space after errors */
62static	struct	nvlist *alloc[1000];
63static	int	adepth;
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)
76#define	new_i(i)	new0(NULL, NULL, NULL, i, NULL)
77
78#define	fx_atom(s)	new0(s, NULL, NULL, FX_ATOM, NULL)
79#define	fx_not(e)	new0(NULL, NULL, NULL, FX_NOT, e)
80#define	fx_and(e1, e2)	new0(NULL, NULL, e1, FX_AND, e2)
81#define	fx_or(e1, e2)	new0(NULL, NULL, e1, FX_OR, e2)
82
83static	void	cleanup(void);
84static	void	setmachine(const char *, const char *, struct nvlist *, int);
85static	void	check_maxpart(void);
86
87static	void	app(struct nvlist *, struct nvlist *);
88
89static	struct nvlist *mk_nsis(const char *, int, struct nvlist *, int);
90static	struct nvlist *mk_ns(const char *, struct nvlist *);
91
92%}
93
94%union {
95	struct	attr *attr;
96	struct	devbase *devb;
97	struct	deva *deva;
98	struct	nvlist *list;
99	const char *str;
100	struct	numconst num;
101	int64_t	val;
102}
103
104%token	AND AT ATTACH
105%token	BLOCK BUILD
106%token	CHAR COLONEQ COMPILE_WITH CONFIG
107%token	DEFFS DEFINE DEFOPT DEFPARAM DEFFLAG DEFPSEUDO DEFPSEUDODEV
108%token	DEVICE DEVCLASS DUMPS DEVICE_MAJOR
109%token	ENDFILE
110%token	XFILE FILE_SYSTEM FLAGS
111%token	IDENT IOCONF
112%token	LINKZERO
113%token	XMACHINE MAJOR MAKEOPTIONS MAXUSERS MAXPARTITIONS MINOR
114%token	NEEDS_COUNT NEEDS_FLAG NO
115%token	XOBJECT OBSOLETE ON OPTIONS
116%token	PACKAGE PLUSEQ PREFIX PSEUDO_DEVICE PSEUDO_ROOT
117%token	ROOT
118%token	SINGLE SOURCE
119%token	TYPE
120%token	VECTOR VERSION
121%token	WITH
122%token	<num> NUMBER
123%token	<str> PATHNAME QSTRING WORD EMPTYSTRING
124%token	ENDDEFS
125
126%left '|'
127%left '&'
128
129%type	<list>	fopts fexpr fatom
130%type	<str>	fs_spec
131%type	<val>	fflgs fflag oflgs oflag
132%type	<str>	rule
133%type	<attr>	attr
134%type	<devb>	devbase
135%type	<deva>	devattach_opt
136%type	<list>	atlist interface_opt
137%type	<str>	atname
138%type	<list>	loclist_opt loclist locdef
139%type	<str>	locdefault
140%type	<list>	values locdefaults
141%type	<list>	attrs_opt attrs
142%type	<list>	locators locator
143%type	<list>	dev_spec
144%type	<str>	device_instance
145%type	<str>	attachment
146%type	<str>	value
147%type	<val>	major_minor npseudo
148%type	<num>	signed_number
149%type	<val>	flags_opt
150%type	<str>	deffs
151%type	<list>	deffses
152%type	<list>	defopt
153%type	<list>	defopts
154%type	<str>	optdep
155%type	<list>	optdeps
156%type	<list>	defoptdeps
157%type	<str>	optfile_opt
158%type	<list>	subarches_opt subarches
159%type	<str>	filename stringvalue locname mkvarname
160%type	<val>	device_major_block device_major_char
161%type	<list>	devnodes devnodetype devnodeflags devnode_dims
162
163%%
164
165/*
166 * A configuration consists of a machine type, followed by the machine
167 * definition files (via the include() mechanism), followed by the
168 * configuration specification(s) proper.  In effect, this is two
169 * separate grammars, with some shared terminals and nonterminals.
170 * Note that we do not have sufficient keywords to enforce any order
171 * between elements of "topthings" without introducing shift/reduce
172 * conflicts.  Instead, check order requirements in the C code.
173 */
174Configuration:
175	topthings			/* dirspecs, include "std.arch" */
176	machine_spec			/* "machine foo" from machine descr. */
177	dev_defs ENDDEFS		/* all machine definition files */
178					{ check_maxpart(); check_version(); }
179	specs;				/* rest of machine description */
180
181topthings:
182	topthings topthing |
183	/* empty */;
184
185topthing:
186	SOURCE filename '\n'		{ if (!srcdir) srcdir = $2; } |
187	BUILD  filename '\n'		{ if (!builddir) builddir = $2; } |
188	'\n';
189
190machine_spec:
191	XMACHINE WORD '\n'		{ setmachine($2,NULL,NULL,0); } |
192	XMACHINE WORD WORD subarches_opt '\n'	{ setmachine($2,$3,$4,0); } |
193	IOCONF WORD '\n'		{ setmachine($2,NULL,NULL,1); } |
194	error { stop("cannot proceed without machine or ioconf specifier"); };
195
196subarches_opt:
197	subarches			|
198	/* empty */			{ $$ = NULL; };
199
200subarches:
201	subarches WORD			{ $$ = new_nx($2, $1); } |
202	WORD				{ $$ = new_n($1); };
203
204/*
205 * Various nonterminals shared between the grammars.
206 */
207file:
208	XFILE filename fopts fflgs rule	{ addfile($2, $3, $4, $5); };
209
210object:
211	XOBJECT filename fopts oflgs	{ addobject($2, $3, $4); };
212
213device_major:
214	DEVICE_MAJOR WORD device_major_char device_major_block fopts devnodes
215					{ adddevm($2, $3, $4, $5, $6); };
216
217device_major_block:
218	BLOCK NUMBER			{ $$ = $2.val; } |
219	/* empty */			{ $$ = -1; };
220
221device_major_char:
222	CHAR NUMBER			{ $$ = $2.val; } |
223	/* empty */			{ $$ = -1; };
224
225/* order of options is important, must use right recursion */
226fopts:
227	fexpr				{ $$ = $1; } |
228	/* empty */			{ $$ = NULL; };
229
230fexpr:
231	fatom				{ $$ = $1; } |
232	'!' fatom			{ $$ = fx_not($2); } |
233	fexpr '&' fexpr			{ $$ = fx_and($1, $3); } |
234	fexpr '|' fexpr			{ $$ = fx_or($1, $3); } |
235	'(' fexpr ')'			{ $$ = $2; };
236
237fatom:
238	WORD				{ $$ = fx_atom($1); };
239
240fflgs:
241	fflgs fflag			{ $$ = $1 | $2; } |
242	/* empty */			{ $$ = 0; };
243
244fflag:
245	NEEDS_COUNT			{ $$ = FI_NEEDSCOUNT; } |
246	NEEDS_FLAG			{ $$ = FI_NEEDSFLAG; };
247
248devnodes:
249	devnodetype ',' devnodeflags	{ $$ = nvcat($1, $3); } |
250	devnodetype			{ $$ = $1; } |
251	/* empty */			{ $$ = new_s("DEVNODE_DONTBOTHER"); };
252
253devnodetype:
254	SINGLE				{ $$ = new_s("DEVNODE_SINGLE"); } |
255	VECTOR '=' devnode_dims		{ $$ = nvcat(new_s("DEVNODE_VECTOR"), $3); };
256
257devnode_dims:
258	NUMBER ':' NUMBER		{ struct nvlist *__nv1, *__nv2;
259					  __nv1 = new_i($1.val);
260					  __nv2 = new_i($3.val);
261					  $$ = nvcat(__nv1, __nv2); } |
262	NUMBER				{ $$ = new_i($1.val); }
263
264devnodeflags:
265	LINKZERO			{ $$ = new_s("DEVNODE_FLAG_LINKZERO");};
266
267oflgs:
268	oflgs oflag			{ $$ = $1 | $2; } |
269	/* empty */			{ $$ = 0; };
270
271oflag:
272	NEEDS_FLAG			{ $$ = OI_NEEDSFLAG; };
273
274rule:
275	COMPILE_WITH stringvalue	{ $$ = $2; } |
276	/* empty */			{ $$ = NULL; };
277
278prefix:
279	PREFIX filename			{ prefix_push($2); } |
280	PREFIX				{ prefix_pop(); };
281
282/*
283 * The machine definitions grammar.
284 */
285dev_defs:
286	dev_defs dev_def |
287	dev_defs ENDFILE		{ enddefs(); checkfiles(); } |
288	/* empty */;
289
290dev_def:
291	one_def '\n'			{ adepth = 0; } |
292	'\n' |
293	error '\n'			{ cleanup(); };
294
295one_def:
296	file |
297	object |
298	device_major			{ do_devsw = 1; } |
299	prefix |
300	DEVCLASS WORD			{ (void)defattr($2, NULL, NULL, 1); } |
301	DEFFS deffses defoptdeps	{ deffilesystem($2, $3); } |
302	DEFINE WORD interface_opt attrs_opt
303					{ (void)defattr($2, $3, $4, 0); } |
304	DEFOPT optfile_opt defopts defoptdeps
305					{ defoption($2, $3, $4); } |
306	DEFFLAG optfile_opt defopts defoptdeps
307					{ defflag($2, $3, $4, 0); } |
308	OBSOLETE DEFFLAG optfile_opt defopts
309					{ defflag($3, $4, NULL, 1); } |
310	DEFPARAM optfile_opt defopts defoptdeps
311					{ defparam($2, $3, $4, 0); } |
312	OBSOLETE DEFPARAM optfile_opt defopts
313					{ defparam($3, $4, NULL, 1); } |
314	DEVICE devbase interface_opt attrs_opt
315					{ defdev($2, $3, $4, 0); } |
316	ATTACH devbase AT atlist devattach_opt attrs_opt
317					{ defdevattach($5, $2, $4, $6); } |
318	MAXPARTITIONS NUMBER		{ maxpartitions = $2.val; } |
319	MAXUSERS NUMBER NUMBER NUMBER	{ setdefmaxusers($2.val, $3.val, $4.val); } |
320	MAKEOPTIONS condmkopt_list |
321	/* interface_opt in DEFPSEUDO is for backwards compatibility */
322	DEFPSEUDO devbase interface_opt attrs_opt
323					{ defdev($2, $3, $4, 1); } |
324	DEFPSEUDODEV devbase interface_opt attrs_opt
325					{ defdev($2, $3, $4, 2); } |
326	MAJOR '{' majorlist '}' |
327	VERSION NUMBER			{ setversion($2.val); };
328
329atlist:
330	atlist ',' atname		{ $$ = new_nx($3, $1); } |
331	atname				{ $$ = new_n($1); };
332
333atname:
334	WORD				{ $$ = $1; } |
335	ROOT				{ $$ = NULL; };
336
337deffses:
338	deffses deffs			{ $$ = new_nx($2, $1); } |
339	deffs				{ $$ = new_n($1); };
340
341deffs:
342	WORD				{ $$ = $1; };
343
344defoptdeps:
345	':' optdeps			{ $$ = $2; } |
346	/* empty */			{ $$ = NULL; };
347
348optdeps:
349	optdeps ',' optdep		{ $$ = new_nx($3, $1); } |
350	optdep				{ $$ = new_n($1); };
351
352optdep:
353	WORD				{ $$ = $1; };
354
355defopts:
356	defopts defopt			{ $$ = nvcat($2, $1); } |
357	defopt				{ $$ = $1; };
358
359defopt:
360	WORD				{ $$ = new_n($1); } |
361	WORD '=' value			{ $$ = new_ns($1, $3); } |
362	WORD COLONEQ value		{
363						struct nvlist *__nv =
364						    new_n($1);
365						$$ = new_nsx("", $3, __nv);
366					} |
367	WORD '=' value COLONEQ value	{
368						struct nvlist *__nv =
369						    new_n($1);
370						$$ = new_nsx("", $5, __nv);
371					};
372
373devbase:
374	WORD				{ $$ = getdevbase($1); };
375
376devattach_opt:
377	WITH WORD			{ $$ = getdevattach($2); } |
378	/* empty */			{ $$ = NULL; };
379
380interface_opt:
381	'{' loclist_opt '}'		{ $$ = new_nx("", $2); } |
382	/* empty */			{ $$ = NULL; };
383
384loclist_opt:
385	loclist				{ $$ = $1; } |
386	/* empty */			{ $$ = NULL; };
387
388/* loclist order matters, must use right recursion */
389loclist:
390	locdef ',' loclist		{ $$ = $1; app($1, $3); } |
391	locdef				{ $$ = $1; };
392
393/* "[ WORD locdefault ]" syntax may be unnecessary... */
394locdef:
395	locname locdefault 		{ $$ = new_nsi($1, $2, 0); } |
396	locname				{ $$ = new_nsi($1, NULL, 0); } |
397	'[' locname locdefault ']'	{ $$ = new_nsi($2, $3, 1); } |
398	locname '[' NUMBER ']'		{ $$ = mk_nsis($1, $3.val, NULL, 0); } |
399	locname '[' NUMBER ']' locdefaults
400					{ $$ = mk_nsis($1, $3.val, $5, 0); } |
401	'[' locname '[' NUMBER ']' locdefaults ']'
402					{ $$ = mk_nsis($2, $4.val, $6, 1); };
403
404locname:
405	WORD				{ $$ = $1; } |
406	QSTRING				{ $$ = $1; };
407
408locdefault:
409	'=' value			{ $$ = $2; };
410
411locdefaults:
412	'=' '{' values '}'		{ $$ = $3; };
413
414optfile_opt:
415	filename			{ $$ = $1; } |
416	/* empty */			{ $$ = NULL; };
417
418filename:
419	QSTRING				{ $$ = $1; } |
420	PATHNAME			{ $$ = $1; };
421
422value:
423	QSTRING				{ $$ = $1; } |
424	WORD				{ $$ = $1; } |
425	EMPTYSTRING			{ $$ = $1; } |
426	signed_number			{ char bf[40];
427					  (void)snprintf(bf, sizeof(bf),
428					      FORMAT($1), (long long)$1.val);
429					  $$ = intern(bf); };
430
431stringvalue:
432	QSTRING				{ $$ = $1; } |
433	WORD				{ $$ = $1; };
434
435values:
436	value ',' values		{ $$ = new_sx($1, $3); } |
437	value				{ $$ = new_s($1); };
438
439signed_number:
440	NUMBER				{ $$ = $1; } |
441	'-' NUMBER			{ $$.fmt = $2.fmt; $$.val = -$2.val; };
442
443attrs_opt:
444	':' attrs			{ $$ = $2; } |
445	/* empty */			{ $$ = NULL; };
446
447attrs:
448	attrs ',' attr			{ $$ = new_px($3, $1); } |
449	attr				{ $$ = new_p($1); };
450
451attr:
452	WORD				{ $$ = getattr($1); };
453
454majorlist:
455	majorlist ',' majordef |
456	majordef;
457
458majordef:
459	devbase '=' NUMBER		{ setmajor($1, $3.val); };
460
461
462/*
463 * The configuration grammar.
464 */
465specs:
466	specs spec |
467	/* empty */;
468
469spec:
470	config_spec '\n'		{ adepth = 0; } |
471	'\n' |
472	error '\n'			{ cleanup(); };
473
474config_spec:
475	one_def |
476	NO FILE_SYSTEM no_fs_list |
477	FILE_SYSTEM fs_list |
478	NO MAKEOPTIONS no_mkopt_list |
479	MAKEOPTIONS mkopt_list |
480	NO OPTIONS no_opt_list |
481	OPTIONS opt_list |
482	MAXUSERS NUMBER			{ setmaxusers($2.val); } |
483	IDENT stringvalue		{ setident($2); } |
484	CONFIG conf root_spec sysparam_list
485					{ addconf(&conf); } |
486	NO CONFIG WORD			{ delconf($3); } |
487	NO PSEUDO_DEVICE WORD		{ delpseudo($3); } |
488	PSEUDO_DEVICE WORD npseudo	{ addpseudo($2, $3); } |
489	PSEUDO_ROOT device_instance	{ addpseudoroot($2); } |
490	NO device_instance AT attachment
491					{ deldevi($2, $4); } |
492	NO DEVICE AT attachment		{ deldeva($4); } |
493	NO device_instance		{ deldev($2); } |
494	device_instance AT attachment locators flags_opt
495					{ adddev($1, $3, $4, $5); };
496
497fs_list:
498	fs_list ',' fsoption |
499	fsoption;
500
501fsoption:
502	WORD				{ addfsoption($1); };
503
504no_fs_list:
505	no_fs_list ',' no_fsoption |
506	no_fsoption;
507
508no_fsoption:
509	WORD				{ delfsoption($1); };
510
511mkopt_list:
512	mkopt_list ',' mkoption |
513	mkoption;
514
515mkvarname:
516	QSTRING				{ $$ = $1; } |
517	WORD				{ $$ = $1; };
518
519mkoption:
520	mkvarname '=' value		{ addmkoption($1, $3); } |
521	mkvarname PLUSEQ value		{ appendmkoption($1, $3); };
522
523condmkopt_list:
524	condmkopt_list ',' condmkoption |
525	condmkoption;
526
527condmkoption:
528	fexpr mkvarname PLUSEQ value	{ appendcondmkoption($1, $2, $4); };
529
530no_mkopt_list:
531	no_mkopt_list ',' no_mkoption |
532	no_mkoption;
533
534no_mkoption:
535	WORD				{ delmkoption($1); }
536
537opt_list:
538	opt_list ',' option |
539	option;
540
541option:
542	WORD				{ addoption($1, NULL); } |
543	WORD '=' value			{ addoption($1, $3); };
544
545no_opt_list:
546	no_opt_list ',' no_option |
547	no_option;
548
549no_option:
550	WORD				{ deloption($1); };
551
552conf:
553	WORD				{ conf.cf_name = $1;
554					    conf.cf_lineno = currentline();
555					    conf.cf_fstype = NULL;
556					    conf.cf_root = NULL;
557					    conf.cf_dump = NULL; };
558
559root_spec:
560	ROOT on_opt dev_spec fs_spec_opt
561				{ setconf(&conf.cf_root, "root", $3); };
562
563fs_spec_opt:
564	TYPE fs_spec		{ setfstype(&conf.cf_fstype, $2); } |
565	/* empty */;
566
567fs_spec:
568	'?'				{ $$ = intern("?"); } |
569	WORD				{ $$ = $1; };
570
571sysparam_list:
572	sysparam_list sysparam |
573	/* empty */;
574
575sysparam:
576	DUMPS on_opt dev_spec	 { setconf(&conf.cf_dump, "dumps", $3); };
577
578dev_spec:
579	'?'				{ $$ = new_si(intern("?"), NODEV); } |
580	WORD				{ $$ = new_si($1, NODEV); } |
581	major_minor			{ $$ = new_si(NULL, $1); };
582
583major_minor:
584	MAJOR NUMBER MINOR NUMBER	{ $$ = makedev($2.val, $4.val); };
585
586on_opt:
587	ON | /* empty */;
588
589npseudo:
590	NUMBER				{ $$ = $1.val; } |
591	/* empty */			{ $$ = 1; };
592
593device_instance:
594	WORD '*'			{ $$ = starref($1); } |
595	WORD				{ $$ = $1; };
596
597attachment:
598	ROOT				{ $$ = NULL; } |
599	WORD '?'			{ $$ = wildref($1); } |
600	WORD				{ $$ = $1; };
601
602locators:
603	locators locator		{ $$ = $2; app($2, $1); } |
604	/* empty */			{ $$ = NULL; };
605
606locator:
607	WORD values			{ $$ = mk_ns($1, $2); } |
608	WORD '?'			{ $$ = new_ns($1, NULL); };
609
610flags_opt:
611	FLAGS NUMBER			{ $$ = $2.val; } |
612	/* empty */			{ $$ = 0; };
613
614%%
615
616void
617yyerror(const char *s)
618{
619
620	cfgerror("%s", s);
621}
622
623/*
624 * Cleanup procedure after syntax error: release any nvlists
625 * allocated during parsing the current line.
626 */
627static void
628cleanup(void)
629{
630	struct nvlist **np;
631	int i;
632
633	for (np = alloc, i = adepth; --i >= 0; np++)
634		nvfree(*np);
635	adepth = 0;
636}
637
638static void
639setmachine(const char *mch, const char *mcharch, struct nvlist *mchsubarches,
640	int isioconf)
641{
642	char buf[MAXPATHLEN];
643	struct nvlist *nv;
644
645	if (isioconf) {
646		fprintf(stderr, "WARNING: ioconf is an experimental feature\n");
647		if (include(_PATH_DEVNULL, ENDDEFS, 0, 0) != 0)
648			exit(1);
649		ioconfname = mch;
650		return;
651	}
652
653	machine = mch;
654	machinearch = mcharch;
655	machinesubarches = mchsubarches;
656
657	/*
658	 * Define attributes for all the given names
659	 */
660	if (defattr(machine, NULL, NULL, 0) != 0 ||
661	    (machinearch != NULL &&
662	     defattr(machinearch, NULL, NULL, 0) != 0))
663		exit(1);
664	for (nv = machinesubarches; nv != NULL; nv = nv->nv_next) {
665		if (defattr(nv->nv_name, NULL, NULL, 0) != 0)
666			exit(1);
667	}
668
669	/*
670	 * Set up the file inclusion stack.  This empty include tells
671	 * the parser there are no more device definitions coming.
672	 */
673	if (include(_PATH_DEVNULL, ENDDEFS, 0, 0) != 0)
674		exit(1);
675
676	/* Include arch/${MACHINE}/conf/files.${MACHINE} */
677	(void)snprintf(buf, sizeof(buf), "arch/%s/conf/files.%s",
678	    machine, machine);
679	if (include(buf, ENDFILE, 0, 0) != 0)
680		exit(1);
681
682	/* Include any arch/${MACHINE_SUBARCH}/conf/files.${MACHINE_SUBARCH} */
683	for (nv = machinesubarches; nv != NULL; nv = nv->nv_next) {
684		(void)snprintf(buf, sizeof(buf), "arch/%s/conf/files.%s",
685		    nv->nv_name, nv->nv_name);
686		if (include(buf, ENDFILE, 0, 0) != 0)
687			exit(1);
688	}
689
690	/* Include any arch/${MACHINE_ARCH}/conf/files.${MACHINE_ARCH} */
691	if (machinearch != NULL)
692		(void)snprintf(buf, sizeof(buf), "arch/%s/conf/files.%s",
693		    machinearch, machinearch);
694	else
695		strlcpy(buf, _PATH_DEVNULL, sizeof(buf));
696	if (include(buf, ENDFILE, 0, 0) != 0)
697		exit(1);
698
699	/*
700	 * Include the global conf/files.  As the last thing
701	 * pushed on the stack, it will be processed first.
702	 */
703	if (include("conf/files", ENDFILE, 0, 0) != 0)
704		exit(1);
705
706	oktopackage = 1;
707}
708
709static void
710check_maxpart(void)
711{
712
713	if (maxpartitions <= 0 && ioconfname == NULL) {
714		stop("cannot proceed without maxpartitions specifier");
715	}
716}
717
718static void
719check_version(void)
720{
721	/*
722	 * In essence, version is 0 and is not supported anymore
723	 */
724	if (version < CONFIG_MINVERSION)
725		stop("your sources are out of date -- please update.");
726}
727
728static void
729app(struct nvlist *p, struct nvlist *q)
730{
731	while (p->nv_next)
732		p = p->nv_next;
733	p->nv_next = q;
734}
735
736static struct nvlist *
737mk_nsis(const char *name, int count, struct nvlist *adefs, int opt)
738{
739	struct nvlist *defs = adefs;
740	struct nvlist **p;
741	char buf[200];
742	int i;
743
744	if (count <= 0) {
745		fprintf(stderr, "config: array with <= 0 size: %s\n", name);
746		exit(1);
747	}
748	p = &defs;
749	for(i = 0; i < count; i++) {
750		if (*p == NULL)
751			*p = new_s("0");
752		snprintf(buf, sizeof(buf), "%s%c%d", name, ARRCHR, i);
753		(*p)->nv_name = i == 0 ? name : intern(buf);
754		(*p)->nv_num = i > 0 || opt;
755		p = &(*p)->nv_next;
756	}
757	*p = 0;
758	return defs;
759}
760
761
762static struct nvlist *
763mk_ns(const char *name, struct nvlist *vals)
764{
765	struct nvlist *p;
766	char buf[200];
767	int i;
768
769	for(i = 0, p = vals; p; i++, p = p->nv_next) {
770		snprintf(buf, sizeof(buf), "%s%c%d", name, ARRCHR, i);
771		p->nv_name = i == 0 ? name : intern(buf);
772	}
773	return vals;
774}
775
776