summaryrefslogtreecommitdiff
path: root/usr.bin/config/defs.h
blob: ef8adc5c6874e64c2ce9473f852435365777c5ce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
/*	$NetBSD: defs.h,v 1.106 2020/04/03 19:53:41 joerg Exp $	*/

/*
 * Copyright (c) 1992, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This software was developed by the Computer Systems Engineering group
 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
 * contributed to Berkeley.
 *
 * All advertising materials mentioning features or use of this software
 * must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Lawrence Berkeley Laboratories.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	from: @(#)config.h	8.1 (Berkeley) 6/6/93
 */

/*
 * defs.h:  Global definitions for "config"
 */

#if HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif

#include <sys/types.h>
#include <sys/param.h>
#include <sys/queue.h>

#if !defined(MAKE_BOOTSTRAP) && defined(BSD)
#include <sys/cdefs.h>
#include <paths.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

/* These are really for MAKE_BOOTSTRAP but harmless. */
#ifndef __dead
#define __dead
#endif
#ifndef __printflike
#define __printflike(a, b)
#endif
#ifndef _PATH_DEVNULL
#define _PATH_DEVNULL "/dev/null"
#endif

#ifdef	MAKE_BOOTSTRAP
#undef	dev_t
#undef	devmajor_t
#undef	devminor_t
#undef	NODEV
#undef	NODEVMAJOR
#undef	major
#undef	minor
#undef	makedev
#define	dev_t		unsigned int	/* XXX: assumes int is 32 bits */
#define	NODEV		((dev_t)-1)
#define devmajor_t	int
#define devminor_t	int
#define NODEVMAJOR	(-1)
#define major(x)        ((devmajor_t)((((x) & 0x000fff00) >>  8)))
#define minor(x)        ((devminor_t)((((x) & 0xfff00000) >> 12) | \
			       (((x) & 0x000000ff) >>  0)))
#define makedev(x,y)    ((dev_t)((((dev_t)(x) <<  8) & 0x000fff00U) | \
                                 (((dev_t)(y) << 12) & 0xfff00000U) | \
                                 (((dev_t)(y) <<  0) & 0x000000ffU)))
#define __attribute__(x)
#endif	/* MAKE_BOOTSTRAP */

#undef setprogname
#undef getprogname
extern const char *progname;
#define	setprogname(s)	((void)(progname = (s)))
#define	getprogname()	(progname)

#define ARRCHR '#'

/*
 * The next two lines define the current version of the config(1) binary,
 * and the minimum version of the configuration files it supports.
 */
#define CONFIG_VERSION		20180827
#define CONFIG_MINVERSION	0

struct where {
	const char *w_srcfile;		/* file name where we are defined */
	u_short	w_srcline;		/* line number where we are defined */
};
/*
 * Name/value lists.  Values can be strings or pointers and/or can carry
 * integers.  The names can be NULL, resulting in simple value lists.
 */
struct nvlist {
	struct nvlist	*nv_next;
	const char	*nv_name;
	const char	*nv_str;
	void		*nv_ptr;
	long long	nv_num;
	int		nv_ifunit;		/* XXX XXX XXX */
	int		nv_flags;
#define	NV_DEPENDED	1
	struct where	nv_where;
};

/*
 * Kernel configurations.
 */
struct config {
	TAILQ_ENTRY(config) cf_next;
	const char *cf_name;		/* "netbsd" */
	const char *cf_fstype;		/* file system type */
	struct	nvlist *cf_root;	/* "root on ra0a" */
	struct	nvlist *cf_dump;	/* "dumps on ra0b" */
	struct where	cf_where;
};

/*
 * Option definition list
 */
struct defoptlist {
	struct defoptlist *dl_next;
	const char *dl_name;
	const char *dl_value;
	const char *dl_lintvalue;
	int dl_obsolete;
	struct nvlist *dl_depends;
	struct where	dl_where;
};

struct files;
TAILQ_HEAD(filelist, files);

struct module {
	const char		*m_name;
#if 1
	struct attrlist		*m_deps;
#else
	struct attrlist		*m_attrs;
	struct modulelist	*m_deps;
#endif
	int			m_expanding;
	struct filelist		m_files;
	int			m_weight;
};

/*
 * Attributes.  These come in three flavors: "plain", "device class,"
 * and "interface".  Plain attributes (e.g., "ether") simply serve
 * to pull in files.  Device class attributes are like plain
 * attributes, but additionally specify a device class (e.g., the
 * "disk" device class attribute specifies that devices with the
 * attribute belong to the "DV_DISK" class) and are mutually exclusive.
 * Interface attributes (e.g., "scsi") carry three lists: locators,
 * child devices, and references.  The locators are those things
 * that must be specified in order to configure a device instance
 * using this attribute (e.g., "tg0 at scsi0").  The a_devs field
 * lists child devices that can connect here (e.g., "tg"s), while
 * the a_refs are parents that carry the attribute (e.g., actual
 * SCSI host adapter drivers such as the SPARC "esp").
 */
struct attr {
	/* XXX */
	struct module a_m;
#define	a_name		a_m.m_name
#define	a_deps		a_m.m_deps
#define	a_expanding	a_m.m_expanding
#define	a_files		a_m.m_files
#define	a_weight	a_m.m_weight

	/* "interface attribute" */
	uint8_t	a_iattr;		/* true => allows children */
	uint8_t a_deselected;		/* deselected */	
	struct	loclist *a_locs;	/* locators required */
	int	a_loclen;		/* length of above list */
	struct	nvlist *a_devs;		/* children */
	struct	nvlist *a_refs;		/* parents */

	/* "device class" */
	const char *a_devclass;		/* device class described */
	struct where a_where;
};

/*
 * List of attributes.
 */
struct attrlist {
	struct attrlist *al_next;
	struct attr *al_this;
};

/*
 * List of locators. (Either definitions or uses...)
 *
 * XXX it would be nice if someone could clarify wtf ll_string and ll_num
 * are actually holding. (This stuff was previously stored in a very ad
 * hoc fashion, and the code is far from clear.)
 */
struct loclist {
	const char *ll_name;
	const char *ll_string;
	long long ll_num;
	struct loclist *ll_next;
};

/*
 * Parent specification.  Multiple device instances may share a
 * given parent spec.  Parent specs are emitted only if there are
 * device instances which actually reference it.
 */
struct pspec {
	TAILQ_ENTRY(pspec) p_list;	/* link on parent spec list */
	struct	attr *p_iattr;		/* interface attribute of parent */
	struct	devbase *p_atdev;	/* optional parent device base */
	int	p_atunit;		/* optional parent device unit */
	struct	nvlist *p_devs;		/* children using it */
	int	p_inst;			/* parent spec instance */
	int	p_active;		/* parent spec is actively used */
	int	p_ref;			/* refcount */
};

/*
 * The "base" part (struct devbase) of a device ("uba", "sd"; but not
 * "uba2" or "sd0").  It may be found "at" one or more attributes,
 * including "at root" (this is represented by a NULL attribute), as
 * specified by the device attachments (struct deva).
 *
 * Each device may also export attributes.  If any provide an output
 * interface (e.g., "esp" provides "scsi"), other devices (e.g.,
 * "tg"s) can be found at instances of this one (e.g., "esp"s).
 * Such a connection must provide locators as specified by that
 * interface attribute (e.g., "target").  The base device can
 * export both output (aka `interface') attributes, as well as
 * import input (`plain') attributes.  Device attachments may
 * only import input attributes; it makes no sense to have a
 * specific attachment export a new interface to other devices.
 *
 * Each base carries a list of instances (via d_ihead).  Note that this
 * list "skips over" aliases; those must be found through the instances
 * themselves.  Each base also carries a list of possible attachments,
 * each of which specify a set of devices that the device can attach
 * to, as well as the device instances that are actually using that
 * attachment.
 */
struct devbase {
	const char *d_name;		/* e.g., "sd" */
	TAILQ_ENTRY(devbase) d_next;
	int 	d_level;
	struct devbase *d_levelparent;
	int	d_isdef;		/* set once properly defined */
	int	d_ispseudo;		/* is a pseudo-device */
	devmajor_t d_major;		/* used for "root on sd0", e.g. */
	struct	attrlist *d_attrs;	/* attributes, if any */
	int	d_umax;			/* highest unit number + 1 */
	struct	devi *d_ihead;		/* first instance, if any */
	struct	devi **d_ipp;		/* used for tacking on more instances */
	struct	deva *d_ahead;		/* first attachment, if any */
	struct	deva **d_app;		/* used for tacking on attachments */
	struct	attr *d_classattr;	/* device class attribute (if any) */
	struct	where d_where;
};

struct deva {
	const char *d_name;		/* name of attachment, e.g. "com_isa" */
	TAILQ_ENTRY(deva) d_next;	/* list of all instances */
	struct	deva *d_bsame;		/* list on same base */
	int	d_isdef;		/* set once properly defined */
	struct	devbase *d_devbase;	/* the base device */
	struct	nvlist *d_atlist;	/* e.g., "at tg" (attr list) */
	struct	attrlist *d_attrs;	/* attributes, if any */
	struct	devi *d_ihead;		/* first instance, if any */
	struct	devi **d_ipp;		/* used for tacking on more instances */
	struct	where d_where;
};

/*
 * An "instance" of a device.  The same instance may be listed more
 * than once, e.g., "xx0 at isa? port FOO" + "xx0 at isa? port BAR".
 *
 * After everything has been read in and verified, the devi's are
 * "packed" to collect all the information needed to generate ioconf.c.
 * In particular, we try to collapse multiple aliases into a single entry.
 * We then assign each "primary" (non-collapsed) instance a cfdata index.
 * Note that there may still be aliases among these.
 */
struct devi {
	/* created while parsing config file */
	const char *i_name;	/* e.g., "sd0" */
	int	i_unit;		/* unit from name, e.g., 0 */
	struct	devbase *i_base;/* e.g., pointer to "sd" base */
	TAILQ_ENTRY(devi) i_next; /* list of all instances */
	struct	devi *i_bsame;	/* list on same base */
	struct	devi *i_asame;	/* list on same base attachment */
	struct	devi *i_alias;	/* other aliases of this instance */
	const char *i_at;	/* where this is "at" (NULL if at root) */
	struct	pspec *i_pspec;	/* parent spec (NULL if at root) */
	struct	deva *i_atdeva;
	const char **i_locs;	/* locators (as given by pspec's iattr) */
	int	i_cfflags;	/* flags from config line */
	int	i_level;	/* position between negated instances */
	int	i_active;
#define	DEVI_ORPHAN	0	/* instance has no active parent */
#define	DEVI_ACTIVE	1	/* instance has an active parent */
#define	DEVI_IGNORED	2	/* instance's parent has been removed */
#define DEVI_BROKEN	3	/* instance is broken (syntax error) */
	int	i_pseudoroot;	/* instance is pseudoroot */

	/* created during packing or ioconf.c generation */
	short	i_collapsed;	/* set => this alias no longer needed */
	u_short	i_cfindex;	/* our index in cfdata */
	int	i_locoff;	/* offset in locators.vec */
	struct	where i_where;
};
/* special units */
#define	STAR	(-1)		/* unit number for, e.g., "sd*" */
#define	WILD	(-2)		/* unit number for, e.g., "sd?" */

/*
 * Files (*.c, *.S, or *.o).  This structure defines the common fields
 * between the two.
 */
struct files {
	TAILQ_ENTRY(files) fi_next;
	TAILQ_ENTRY(files) fi_snext;	/* per-suffix list */
	struct	where fi_where;
	u_char fi_flags;	/* as below */
	const char *fi_tail;	/* name, i.e., strrchr(fi_path, '/') + 1 */
	const char *fi_base;	/* tail minus ".c" (or whatever) */
	const char *fi_dir;	/* path to file */
	const char *fi_path;	/* full file path */
	const char *fi_prefix;	/* any file prefix */
	const char *fi_buildprefix;	/* prefix in builddir */
	int fi_suffix;		/* single char suffix */
	size_t fi_len;		/* path string length */
	struct condexpr *fi_optx; /* options expression */
	struct nvlist *fi_optf; /* flattened version of above, if needed */
	const char *fi_mkrule;	/* special make rule, if any */
	struct attr *fi_attr;	/* owner attr */
	int fi_order;		/* score of order in ${ALLFILES} */
	TAILQ_ENTRY(files) fi_anext;	/* next file in attr */
};

/* flags */
#define	FI_SEL		0x01	/* selected */
#define	FI_NEEDSCOUNT	0x02	/* needs-count */
#define	FI_NEEDSFLAG	0x04	/* needs-flag */
#define	FI_HIDDEN	0x08	/* obscured by other(s), base names overlap */

extern size_t nselfiles;
extern struct files **selfiles;

/*
 * Condition expressions.
 */

enum condexpr_types {
	CX_ATOM,
	CX_NOT,
	CX_AND,
	CX_OR,
};
struct condexpr {
	enum condexpr_types cx_type;
	union {
		const char *atom;
		struct condexpr *not;
		struct {
			struct condexpr *left;
			struct condexpr *right;
		} and, or;
	} cx_u;
};
#define cx_atom	cx_u.atom
#define cx_not	cx_u.not
#define cx_and	cx_u.and
#define cx_or	cx_u.or

/*
 * File/object prefixes.  These are arranged in a stack, and affect
 * the behavior of the source path.
 */

struct prefix;
SLIST_HEAD(prefixlist, prefix);

struct prefix {
	SLIST_ENTRY(prefix)	pf_next;	/* next prefix in stack */
	const char		*pf_prefix;	/* the actual prefix */
};

/*
 * Device major informations.
 */
struct devm {
	TAILQ_ENTRY(devm) dm_next;
	const char	*dm_name;	/* [bc]devsw name */
	devmajor_t	dm_cmajor;	/* character major */
	devmajor_t	dm_bmajor;	/* block major */
	struct condexpr	*dm_opts;	/* options */
	struct nvlist	*dm_devnodes;	/* information on /dev nodes */
	struct where dm_where;
};

/*
 * Hash tables look up name=value pairs.  The pointer value of the name
 * is assumed to be constant forever; this can be arranged by interning
 * the name.  (This is fairly convenient since our lexer does this for
 * all identifier-like strings---it has to save them anyway, lest yacc's
 * look-ahead wipe out the current one.)
 */
struct hashtab;

extern int lkmmode;
extern const char *conffile;		/* source file, e.g., "GENERIC.sparc" */
extern const char *machine;		/* machine type, e.g., "sparc" or "sun3" */
extern const char *machinearch;	/* machine arch, e.g., "sparc" or "m68k" */
extern struct	nvlist *machinesubarches;
				/* machine subarches, e.g., "sun68k" or "hpc" */
extern const char *ioconfname;		/* ioconf name, mutually exclusive to machine */
extern const char *srcdir;		/* path to source directory (rel. to build) */
extern const char *builddir;		/* path to build directory */
extern const char *defbuilddir;	/* default build directory */
extern const char *ident;		/* kernel "ident"ification string */
extern int	errors;			/* counts calls to error() */
extern int	minmaxusers;		/* minimum "maxusers" parameter */
extern int	defmaxusers;		/* default "maxusers" parameter */
extern int	maxmaxusers;		/* default "maxusers" parameter */
extern int	maxusers;		/* configuration's "maxusers" parameter */
extern int	maxpartitions;		/* configuration's "maxpartitions" parameter */
extern int	version;		/* version of the configuration file */
extern struct	nvlist *options;	/* options */
extern struct	nvlist *fsoptions;	/* filesystems */
extern struct	nvlist *mkoptions;	/* makeoptions */
extern struct	nvlist *appmkoptions;	/* appending mkoptions */
extern struct	nvlist *condmkoptions;	/* conditional makeoption table */
extern struct	hashtab *devbasetab;	/* devbase lookup */
extern struct	hashtab *devroottab;	/* attach at root lookup */
extern struct	hashtab *devatab;	/* devbase attachment lookup */
extern struct	hashtab *devitab;	/* device instance lookup */
extern struct	hashtab *deaddevitab;	/* removed instances lookup */
extern struct	hashtab *selecttab;	/* selects things that are "optional foo" */
extern struct	hashtab *needcnttab;	/* retains names marked "needs-count" */
extern struct	hashtab *opttab;	/* table of configured options */
extern struct	hashtab *fsopttab;	/* table of configured file systems */
extern struct	dlhash *defopttab;	/* options that have been "defopt"'d */
extern struct	dlhash *defflagtab;	/* options that have been "defflag"'d */
extern struct	dlhash *defparamtab;	/* options that have been "defparam"'d */
extern struct	dlhash *defoptlint;	/* lint values for options */
extern struct	nvhash *deffstab;	/* defined file systems */
extern struct	dlhash *optfiletab;	/* "defopt"'d option .h files */
extern struct	hashtab *attrtab;	/* attributes (locators, etc.) */
extern struct	hashtab *attrdeptab;	/* attribute dependencies */
extern struct	hashtab *bdevmtab;	/* block devm lookup */
extern struct	hashtab *cdevmtab;	/* character devm lookup */

TAILQ_HEAD(devbasetq, devbase);
TAILQ_HEAD(devatq, deva);
TAILQ_HEAD(conftq, config);
TAILQ_HEAD(devitq, devi);
TAILQ_HEAD(devmtq, devm);
TAILQ_HEAD(pspectq, pspec);

extern struct devbasetq allbases;	/* list of all devbase structures */
extern struct devatq alldevas;		/* list of all devbase attachments */
extern struct conftq allcf;		/* list of configured kernels */
extern struct devitq alldevi,		/* list of all instances */
		     allpseudo;		/* list of all pseudo-devices */
extern struct devmtq alldevms;		/* list of all device-majors */
extern struct pspectq allpspecs;	/* list of all parent specs */
extern int	ndevi;			/* number of devi's (before packing) */
extern int	npspecs;		/* number of parent specs */
extern devmajor_t maxbdevm;		/* max number of block major */
extern devmajor_t maxcdevm;		/* max number of character major */
extern int	do_devsw;		/* 0 if pre-devsw config */
extern int	oktopackage;		/* 0 before setmachine() */
extern int	devilevel;		/* used for devi->i_level */

extern struct filelist		allfiles;	/* list of all kernel source files */
extern struct filelist		allcfiles;	/* list of all .c files */
extern struct filelist		allsfiles;	/* list of all .S files */
extern struct filelist		allofiles;	/* list of all .o files */

extern struct prefixlist	prefixes,	/* prefix stack */
				allprefixes;	/* all prefixes used
						 * (after popped) */
extern struct prefixlist	buildprefixes,	/* build prefix stack */
				allbuildprefixes;/* all build prefixes used
						  * (after popped) */

extern struct attr allattr;
extern struct devi **packed;	/* arrayified table for packed devi's */
extern size_t npacked;		/* size of packed table, <= ndevi */

extern struct locators {			/* loc[] table for config */
	const char **vec;
	int	used;
} locators;

struct numconst {
	int64_t	val;
	int fmt;
};

/* files.c */
void	initfiles(void);
void	checkfiles(void);
int	fixfiles(void);		/* finalize */
int	fixdevsw(void);
void	addfile(const char *, struct condexpr *, u_char, const char *);
int	expr_eval(struct condexpr *, int (*)(const char *, void *), void *);

/* hash.c */
struct	hashtab *ht_new(void);
void	ht_free(struct hashtab *);
int	ht_insrep2(struct hashtab *, const char *, const char *, void *, int);
int	ht_insrep(struct hashtab *, const char *, void *, int);
#define	ht_insert2(ht, nam1, nam2, val) ht_insrep2(ht, nam1, nam2, val, 0)
#define	ht_insert(ht, nam, val) ht_insrep(ht, nam, val, 0)
#define	ht_replace(ht, nam, val) ht_insrep(ht, nam, val, 1)
int	ht_remove2(struct hashtab *, const char *, const char *);
int	ht_remove(struct hashtab *, const char *);
void	*ht_lookup2(struct hashtab *, const char *, const char *);
void	*ht_lookup(struct hashtab *, const char *);
void	initintern(void);
const char *intern(const char *);
typedef int (*ht_callback2)(const char *, const char *, void *, void *);
typedef int (*ht_callback)(const char *, void *, void *);
int	ht_enumerate2(struct hashtab *, ht_callback2, void *);
int	ht_enumerate(struct hashtab *, ht_callback, void *);

/* typed hash, named struct HT, whose type is string -> struct VT */
#define DECLHASH(HT, VT) \
	struct HT;							\
	struct HT *HT##_create(void);					\
	int HT##_insert(struct HT *, const char *, struct VT *);	\
	int HT##_replace(struct HT *, const char *, struct VT *);	\
	int HT##_remove(struct HT *, const char *);			\
	struct VT *HT##_lookup(struct HT *, const char *);		\
	int HT##_enumerate(struct HT *,					\
			int (*)(const char *, struct VT *, void *),	\
			void *)
DECLHASH(nvhash, nvlist);
DECLHASH(dlhash, defoptlist);

/* lint.c */
void	emit_instances(void);
void	emit_options(void);
void	emit_params(void);

/* main.c */
extern	int Mflag;
extern	int Sflag;
void	addoption(const char *, const char *);
void	addfsoption(const char *);
void	addmkoption(const char *, const char *);
void	appendmkoption(const char *, const char *);
void	appendcondmkoption(struct condexpr *, const char *, const char *);
void	deffilesystem(struct nvlist *, struct nvlist *);
void	defoption(const char *, struct defoptlist *, struct nvlist *);
void	defflag(const char *, struct defoptlist *, struct nvlist *, int);
void	defparam(const char *, struct defoptlist *, struct nvlist *, int);
void	deloption(const char *, int);
void	delfsoption(const char *, int);
void	delmkoption(const char *, int);
int	devbase_has_instances(struct devbase *, int);
struct where *find_declared_option(const char *);
int	deva_has_instances(struct deva *, int);
void	setupdirs(void);
void	fixmaxusers(void);
void	fixmkoption(void);
const char *strtolower(const char *);

/* tests on option types */
#define OPT_FSOPT(n)	(nvhash_lookup(deffstab, (n)) != NULL)
#define OPT_DEFOPT(n)	(dlhash_lookup(defopttab, (n)) != NULL)
#define OPT_DEFFLAG(n)	(dlhash_lookup(defflagtab, (n)) != NULL)
#define OPT_DEFPARAM(n)	(dlhash_lookup(defparamtab, (n)) != NULL)
#define OPT_OBSOLETE(n)	(dlhash_lookup(obsopttab, (n)) != NULL)
#define DEFINED_OPTION(n) (find_declared_option((n)))

/* main.c */
void	logconfig_include(FILE *, const char *);

/* mkdevsw.c */
int	mkdevsw(void);

/* mkheaders.c */
int	mkheaders(void);
int	moveifchanged(const char *, const char *);
int	emitlocs(void);
int	emitioconfh(void);

/* mkioconf.c */
int	mkioconf(void);

/* mkmakefile.c */
int	mkmakefile(void);

/* mkswap.c */
int	mkswap(void);

/* pack.c */
void	pack(void);

/* scan.l */
u_short	currentline(void);
int	firstfile(const char *);
void	package(const char *);
int	include(const char *, int, int, int);
extern int includedepth;

/* sem.c, other than for yacc actions */
void	initsem(void);
int	onlist(struct nvlist *, void *);

/* util.c */
void	prefix_push(const char *);
void	prefix_pop(void);
void	buildprefix_push(const char *);
void	buildprefix_pop(void);
char	*sourcepath(const char *);
extern	int dflag;
#define	CFGDBG(n, ...) \
	do { if ((dflag) >= (n)) cfgdbg(__VA_ARGS__); } while (0)
void	cfgdbg(const char *, ...)			/* debug info */
     __printflike(1, 2);
void	cfgwarn(const char *, ...)			/* immediate warns */
     __printflike(1, 2);
void	cfgxwarn(const char *, int, const char *, ...)	/* delayed warns */
     __printflike(3, 4);
void	cfgerror(const char *, ...)			/* immediate errs */
     __printflike(1, 2);
void	cfgxerror(const char *, int, const char *, ...)	/* delayed errs */
     __printflike(3, 4);
__dead void panic(const char *, ...)
     __printflike(1, 2);
struct nvlist *newnv(const char *, const char *, void *, long long, struct nvlist *);
void	nvfree(struct nvlist *);
void	nvfreel(struct nvlist *);
struct nvlist *nvcat(struct nvlist *, struct nvlist *);
void	autogen_comment(FILE *, const char *);
struct defoptlist *defoptlist_create(const char *, const char *, const char *);
void defoptlist_destroy(struct defoptlist *);
struct defoptlist *defoptlist_append(struct defoptlist *, struct defoptlist *);
struct attrlist *attrlist_create(void);
struct attrlist *attrlist_cons(struct attrlist *, struct attr *);
void attrlist_destroy(struct attrlist *);
void attrlist_destroyall(struct attrlist *);
struct loclist *loclist_create(const char *, const char *, long long);
void loclist_destroy(struct loclist *);
struct condexpr *condexpr_create(enum condexpr_types);
void condexpr_destroy(struct condexpr *);

/* liby */
void	yyerror(const char *);
int	yylex(void);