moved into config.

This commit is contained in:
cgd 1995-04-28 06:54:10 +00:00
parent d64248e551
commit 8aec5a0ab6
16 changed files with 0 additions and 5056 deletions

View File

@ -1,16 +0,0 @@
# from: @(#)Makefile 8.2 (Berkeley) 4/19/94
# $Id: Makefile,v 1.11 1994/12/22 11:33:48 cgd Exp $
PROG= config.new
BINDIR= /usr/sbin
SRCS= files.c gram.y hash.c main.c mkheaders.c mkioconf.c mkmakefile.c \
mkswap.c pack.c scan.l sem.c util.c
CFLAGS+=-I${.CURDIR} -I.
LDADD+= -ll
DPADD+= ${LIBL}
CLEANFILES=gram.c scan.c y.tab.h
MAN= config.new.8
.include <bsd.prog.mk>
.depend: gram.c scan.c

View File

@ -1,284 +0,0 @@
/*
* 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. 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, Berkeley and its contributors.
* 4. 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
* $Id: config.h,v 1.6 1995/01/25 20:44:39 cgd Exp $
*/
/*
* 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;
union {
const char *un_str;
void *un_ptr;
} nv_un;
#define nv_str nv_un.un_str
#define nv_ptr nv_un.un_ptr
int nv_int;
};
/*
* Kernel configurations.
*/
struct config {
struct config *cf_next; /* linked list */
const char *cf_name; /* "vmunix" */
int cf_lineno; /* source line */
struct nvlist *cf_root; /* "root on ra0a" */
struct nvlist *cf_swap; /* "swap on ra0b and ra1b" */
struct nvlist *cf_dump; /* "dumps on ra0b" */
};
/*
* Attributes. These come in two flavors: "plain" and "interface".
* Plain attributes (e.g., "ether") simply serve to pull in files.
* 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 {
const char *a_name; /* name of this attribute */
int a_iattr; /* true => allows children */
struct nvlist *a_locs; /* locators required */
int a_loclen; /* length of above list */
struct nvlist *a_devs; /* children */
struct nvlist *a_refs; /* parents */
};
/*
* The "base" part 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).
*
* 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").
*
* 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.
*/
struct devbase {
const char *d_name; /* e.g., "sd" */
struct devbase *d_next; /* linked list */
int d_isdef; /* set once properly defined */
int d_ispseudo; /* is a pseudo-device */
int d_major; /* used for "root on sd0", e.g. */
struct nvlist *d_atlist; /* e.g., "at tg" (attr list) */
struct nvlist *d_vectors; /* interrupt vectors, if any */
struct nvlist *d_attrs; /* attributes, if any */
struct devi *d_ihead; /* first instance, if any */
struct devi **d_ipp; /* used for tacking on more instances */
int d_umax; /* highest unit number + 1 */
};
/*
* 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 */
struct devi *i_next; /* list of all instances */
struct devi *i_bsame; /* list on same base */
struct devi *i_alias; /* other aliases of this instance */
const char *i_at; /* where this is "at" (NULL if at root) */
struct attr *i_atattr; /* attr that allowed attach */
struct devbase *i_atdev;/* dev if "at <devname><unit>", else NULL */
const char **i_locs; /* locators (as given by i_atattr) */
int i_atunit; /* unit from "at" */
int i_cfflags; /* flags from config line */
int i_lineno; /* line # in config, for later errors */
/* created during packing or ioconf.c generation */
/* i_loclen via i_atattr->a_loclen */
short i_collapsed; /* set => this alias no longer needed */
short i_cfindex; /* our index in cfdata */
short i_pvlen; /* number of parents */
short i_pvoff; /* offset in parents.vec */
short i_locoff; /* offset in locators.vec */
short i_ivoff; /* offset in interrupt vectors, if any */
struct devi **i_parents;/* the parents themselves */
};
/* special units */
#define STAR (-1) /* unit number for, e.g., "sd*" */
#define WILD (-2) /* unit number for, e.g., "sd?" */
/*
* Files. Each file is either standard (always included) or optional,
* depending on whether it has names on which to *be* optional.
*/
struct files {
struct files *fi_next; /* linked list */
const char *fi_srcfile; /* the name of the "files" file that got us */
u_short fi_srcline; /* and the line number */
u_char fi_flags; /* as below */
char fi_lastc; /* last char from path */
const char *fi_path; /* full file path */
const char *fi_tail; /* name, i.e., rindex(fi_path, '/') + 1 */
const char *fi_base; /* tail minus ".c" (or whatever) */
struct nvlist *fi_opt; /* optional on ... */
const char *fi_mkrule; /* special make rule, if any */
};
/* flags */
#define FI_SEL 0x01 /* selected */
#define FI_CONFIGDEP 0x02 /* config-dependent */
#define FI_DRIVER 0x04 /* device-driver */
#define FI_NEEDSCOUNT 0x08 /* needs-count */
#define FI_NEEDSFLAG 0x10 /* needs-flag */
#define FI_HIDDEN 0x20 /* obscured by other(s), base names overlap */
/*
* 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;
const char *conffile; /* source file, e.g., "GENERIC.sparc" */
const char *confdirbase; /* basename of compile directory, usu. same */
const char *machine; /* machine type, e.g., "sparc" or "sun3" */
const char *machinearch; /* machine arch, e.g., "sparc" or "m68k" */
int errors; /* counts calls to error() */
int minmaxusers; /* minimum "maxusers" parameter */
int defmaxusers; /* default "maxusers" parameter */
int maxmaxusers; /* default "maxusers" parameter */
int maxusers; /* configuration's "maxusers" parameter */
int maxpartitions; /* configuration's "maxpartitions" parameter */
struct nvlist *options; /* options */
struct nvlist *mkoptions; /* makeoptions */
struct hashtab *devbasetab; /* devbase lookup */
struct hashtab *selecttab; /* selects things that are "optional foo" */
struct hashtab *needcnttab; /* retains names marked "needs-count" */
struct devbase *allbases; /* list of all devbase structures */
struct config *allcf; /* list of configured kernels */
struct devi *alldevi; /* list of all instances */
struct devi *allpseudo; /* list of all pseudo-devices */
int ndevi; /* number of devi's (before packing) */
int npseudo; /* number of pseudo's */
struct files *allfiles; /* list of all kernel source files */
struct devi **packed; /* arrayified table for packed devi's */
int npacked; /* size of packed table, <= ndevi */
struct { /* pv[] table for config */
short *vec;
int used;
} parents;
struct { /* loc[] table for config */
const char **vec;
int used;
} locators;
/* files.c */
void initfiles __P((void));
void checkfiles __P((void));
int fixfiles __P((void)); /* finalize */
void addfile __P((const char *, struct nvlist *, int, const char *));
/* hash.c */
struct hashtab *ht_new __P((void));
int ht_insrep __P((struct hashtab *, const char *, void *, int));
#define ht_insert(ht, nam, val) ht_insrep(ht, nam, val, 0)
#define ht_replace(ht, nam, val) ht_insrep(ht, nam, val, 1)
void *ht_lookup __P((struct hashtab *, const char *));
void initintern __P((void));
const char *intern __P((const char *));
/* main.c */
void addoption __P((const char *name, const char *value));
void addmkoption __P((const char *name, const char *value));
/* mkheaders.c */
int mkheaders __P((void));
/* mkioconf.c */
int mkioconf __P((void));
/* mkmakefile.c */
int mkmakefile __P((void));
/* mkswap.c */
int mkswap __P((void));
/* pack.c */
void pack __P((void));
/* scan.l */
int currentline __P((void));
/* sem.c, other than for yacc actions */
void initsem __P((void));
/* util.c */
void *emalloc __P((size_t));
void *erealloc __P((void *, size_t));
char *path __P((const char *));
void error __P((const char *, ...)); /* immediate errs */
void xerror __P((const char *, int, const char *, ...)); /* delayed errs */
__dead void panic __P((const char *, ...));
struct nvlist *newnv __P((const char *, const char *, void *, int));
void nvfree __P((struct nvlist *));
void nvfreel __P((struct nvlist *));

View File

@ -1,168 +0,0 @@
.\" Copyright (c) 1980, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" 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. 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, Berkeley and its contributors.
.\" 4. 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.8 8.2 (Berkeley) 4/19/94
.\" $Id: config.new.8,v 1.4 1994/06/22 10:44:07 pk Exp $
.\"
.Dd April 19, 1994
.Dt CONFIG.NEW 8
.Os BSD 4
.Sh NAME
.Nm config.new
.Nd build kernel compilation directories
.Sh SYNOPSIS
.Nm config.new
.Op Fl p
.Ar system-name
.Sh DESCRIPTION
.Pp
This is the new version of the
.Nm config
program.
.\"It understands the more modern autoconfiguration scheme
.\"used on the SPARC and i386 platforms.
.\"The old version of config is still used with the
.\"HP300, DECstation, and derivative platforms.
.\"Only the version of
.\".Nm config
.\"applicable to the architecture that you are running
.\"will be installed on your machine.
.Pp
.Nm Config.new
builds a set of configuration files from the file
.Ar system-name ,
which describes
the system to configure.
.Pp
.Nm Config.new
should run from the
.Pa conf
subdirectory of the top-level machine-specific directory
of the system source (usually
.Pa /sys/arch/MACHINE/conf ,
where
.Pa MACHINE
is one of
.Pa vax ,
.Pa tahoe ,
.Pa hp300 ,
and so forth).
.Nm Config.new
assumes the directory
.Pa ../compile
exists; it places all output files in a subdirectory there,
creating the subdirectory if necessary.
The subdirectory name is taken from the
.Ar system-name ;
thus, configuring with
.Dq Li config.new PICKLE
will use the directory
.Pa ../compile/PICKLE .
.Pp
If the
.Fl p
option is supplied,
.Pa .PROF
is appended to the compilation directory name, and
.Nm config.new
acts as if the lines
.Dq Li makeoptions PROF="-pg"
and
.Dq Li options GPROF
appeared in the configuration file.
This will build a system that includes profiling code; see
.Xr kgmon 8
and
.Xr gprof 1 .
The
.Fl p
flag is expected to be used for
.Dq one-shot
profiles of existing systems;
for regular profiling,
it is probably wiser to make a separate configuration
containing the
.Li makeoptions
line.
.Pp
The old undocumented
.Fl g
flag is no longer supported.
Instead, use
.Dq Li makeoptions DEBUG="-g"
and (typically)
.Dq Li options KGDB .
.Pp
The output of
.Nm config.new
consists of a number of files, principally
.Pa ioconf.c ,
a description of I/O devices that may be attached to the system; and a
.Pa Makefile ,
used by
.Xr make 1
in building the kernel.
.Pp
After running
.Nm config.new ,
it is wise to run
.Dq Li make depend
in the directory where the new makefile
was created.
.Nm Config.new
prints a reminder of this when it completes.
.Pp
If
.Nm config.new
stops due to errors, the problems reported should be corrected and
.Nm config.new
should be run again.
.Nm Config.new
attempts to avoid changing the compilation directory
if there are configuration errors,
but this code is not well-tested,
and some problems (such as running out of disk space)
are unrecoverable.
.Sh SEE ALSO
The SYNOPSIS portion of each device in section 4.
.Rs
.%T "Building 4.4 BSD Systems with Config"
.\" .%T "Device Support in 4.4BSD"
.Re
.sp
.Xr config 8
.Sh HISTORY
The
.Nm config
command appeared in
.Bx 4.1 .
It was completely revised in
.Bx 4.4 .

View File

@ -1,263 +0,0 @@
/*
* 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. 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, Berkeley and its contributors.
* 4. 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: @(#)files.c 8.1 (Berkeley) 6/6/93
* $Id: files.c,v 1.3 1994/06/22 10:44:08 pk Exp $
*/
#include <sys/param.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
extern const char *yyfile;
/*
* We check that each full path name is unique. File base names
* should generally also be unique, e.g., having both a net/xx.c and
* a kern/xx.c (or, worse, a net/xx.c and a new/xx.c++) is probably
* wrong, but is permitted under some conditions.
*/
static struct hashtab *basetab; /* file base names */
static struct hashtab *pathtab; /* full path names */
static struct files **nextfile;
static struct files **unchecked;
void
initfiles()
{
basetab = ht_new();
pathtab = ht_new();
nextfile = &allfiles;
unchecked = &allfiles;
}
static void
showprev(pref, fi)
const char *pref;
register struct files *fi;
{
xerror(fi->fi_srcfile, fi->fi_srcline,
"%sfile %s ...", pref, fi->fi_path);
errors--;
}
void
addfile(path, opts, flags, rule)
const char *path;
struct nvlist *opts;
int flags;
const char *rule;
{
struct files *fi;
const char *base, *dotp, *tail;
size_t baselen;
int needc, needf;
char buf[200];
/* check various errors */
needc = flags & FI_NEEDSCOUNT;
needf = flags & FI_NEEDSFLAG;
if (needc && needf) {
error("cannot mix needs-count and needs-flag");
goto bad;
}
if (opts == NULL && (needc || needf)) {
error("nothing to %s for %s", needc ? "count" : "flag", path);
goto bad;
}
if ((fi = ht_lookup(pathtab, path)) != NULL) {
showprev("", fi);
error("file %s listed again", path);
goto bad;
}
/* find last part of pathname, and same without trailing suffix */
tail = rindex(path, '/');
if (tail == NULL)
tail = path;
else
tail++;
dotp = rindex(tail, '.');
if (dotp == NULL || dotp[1] == 0 ||
(baselen = dotp - tail) >= sizeof(buf)) {
error("invalid pathname `%s'", path);
goto bad;
}
/*
* Make a copy of the path without the .c/.s/whatever suffix.
* This must be unique per "files" file (e.g., a specific
* file can override a standard file, but no standard file
* can override another standard file). This is not perfect
* but should catch any major errors.
*/
bcopy(tail, buf, baselen);
buf[baselen] = 0;
base = intern(buf);
if ((fi = ht_lookup(basetab, base)) != NULL) {
if (fi->fi_srcfile != yyfile) {
showprev("note: ", fi);
error("is overriden by %s", path);
errors--; /* take it away */
fi->fi_flags |= FI_HIDDEN;
} else {
showprev("", fi);
error("collides with %s (both make %s.o)",
path, base);
goto bad;
}
}
/*
* Commit this file to memory.
*/
fi = emalloc(sizeof *fi);
fi->fi_next = NULL;
fi->fi_srcfile = yyfile;
fi->fi_srcline = currentline();
fi->fi_flags = flags;
fi->fi_lastc = dotp[strlen(dotp) - 1];
fi->fi_path = path;
fi->fi_tail = tail;
fi->fi_base = base;
fi->fi_opt = opts;
fi->fi_mkrule = rule;
if (ht_insert(pathtab, path, fi))
panic("addfile: ht_insert(%s)", path);
(void)ht_replace(basetab, base, fi);
*nextfile = fi;
nextfile = &fi->fi_next;
return;
bad:
nvfreel(opts);
}
/*
* We have finished reading some "files" file, either ../../conf/files
* or ./files.$machine. Make sure that everything that is flagged as
* needing a count is reasonable. (This prevents ../../conf/files from
* depending on some machine-specific device.)
*/
void
checkfiles()
{
register struct files *fi, *last;
register struct nvlist *nv;
last = NULL;
for (fi = *unchecked; fi != NULL; last = fi, fi = fi->fi_next) {
if ((fi->fi_flags & FI_NEEDSCOUNT) == 0)
continue;
for (nv = fi->fi_opt; nv != NULL; nv = nv->nv_next)
if (ht_lookup(devbasetab, nv->nv_name) == NULL) {
xerror(fi->fi_srcfile, fi->fi_srcline,
"`%s' is not a countable device",
nv->nv_name);
/* keep fixfiles() from complaining again */
fi->fi_flags |= FI_HIDDEN;
}
}
if (last != NULL)
unchecked = &last->fi_next;
}
/*
* We have finished reading everything. Tack the files down: calculate
* selection and counts as needed.
*/
int
fixfiles()
{
register struct files *fi;
register struct nvlist *nv;
register struct devbase *dev;
int sel, err;
err = 0;
for (fi = allfiles; fi != NULL; fi = fi->fi_next) {
if (fi->fi_flags & FI_HIDDEN)
continue;
if ((nv = fi->fi_opt) == NULL) { /* standard */
fi->fi_flags |= FI_SEL;
continue;
}
/* figure out whether it is selected */
sel = 0;
if (fi->fi_flags & FI_NEEDSCOUNT) {
/* ... and compute counts too */
do {
dev = ht_lookup(devbasetab, nv->nv_name);
if (dev == NULL) {
xerror(fi->fi_srcfile, fi->fi_srcline,
"`%s' is not a countable device",
nv->nv_name);
err = 1;
} else {
if (dev->d_umax)
sel = 1;
nv->nv_int = dev->d_umax;
(void)ht_insert(needcnttab,
nv->nv_name, nv);
}
} while ((nv = nv->nv_next) != NULL);
} else {
do {
if (ht_lookup(selecttab, nv->nv_name)) {
sel = 1;
break;
}
} while ((nv = nv->nv_next) != NULL);
if (fi->fi_flags & FI_NEEDSFLAG)
for (nv = fi->fi_opt; nv; nv = nv->nv_next)
nv->nv_int = sel;
}
/* if selected, we are go */
if (sel)
fi->fi_flags |= FI_SEL;
}
return (err);
}

View File

@ -1,421 +0,0 @@
%{
/*
* 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. 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, Berkeley and its contributors.
* 4. 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: @(#)gram.y 8.1 (Berkeley) 6/6/93
* $Id: gram.y,v 1.7 1995/04/17 06:59:11 cgd Exp $
*/
#include <sys/param.h>
#include <ctype.h>
#include <paths.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "sem.h"
#define FORMAT(n) ((n) > -10 && (n) < 10 ? "%d" : "0x%x")
#define stop(s) error(s), exit(1)
int include __P((const char *, int));
void yyerror __P((const char *));
int yylex __P((void));
extern const char *lastfile;
static struct config conf; /* at most one active at a time */
/* the following is used to recover nvlist space after errors */
static struct nvlist *alloc[1000];
static int adepth;
#define new0(n,s,p,i) (alloc[adepth++] = newnv(n, s, p, i))
#define new_n(n) new0(n, NULL, NULL, 0)
#define new_ns(n, s) new0(n, s, NULL, 0)
#define new_si(s, i) new0(NULL, s, NULL, i)
#define new_nsi(n,s,i) new0(n, s, NULL, i)
#define new_np(n, p) new0(n, NULL, p, 0)
#define new_s(s) new0(NULL, s, NULL, 0)
#define new_p(p) new0(NULL, NULL, p, 0)
static void cleanup __P((void));
static void setmachine __P((const char *, const char *));
static void setmaxpartitions __P((int));
%}
%union {
struct attr *attr;
struct devbase *devb;
struct nvlist *list;
const char *str;
int val;
}
%token AND AT COMPILE_WITH CONFIG DEFINE DEVICE DUMPS ENDFILE
%token XFILE FLAGS INCLUDE XMACHINE MAJOR MAKEOPTIONS MAXUSERS MAXPARTITIONS
%token MINOR ON OPTIONS PSEUDO_DEVICE ROOT SWAP VECTOR
%token <val> FFLAG NUMBER
%token <str> PATHNAME WORD
%type <list> fopts
%type <val> fflgs
%type <str> rule
%type <attr> attr
%type <devb> devbase
%type <list> atlist interface_opt
%type <str> atname
%type <list> loclist_opt loclist locdef
%type <str> locdefault
%type <list> veclist_opt veclist
%type <list> attrs_opt attrs
%type <list> locators locator
%type <list> swapdev_list dev_spec
%type <str> device_instance
%type <str> attachment
%type <str> value
%type <val> major_minor signed_number npseudo
%type <val> flags_opt
%%
/*
* A configuration consists of a machine type, followed by the machine
* definition files (via the include() mechanism), followed by the
* configuration specification(s) proper. In effect, this is two
* separate grammars, with some shared terminals and nonterminals.
*/
Configuration:
hdrs machine_spec /* "machine foo" from machine descr. */
dev_defs dev_eof /* ../../conf/devices */
dev_defs dev_eof /* devices.foo */
maxpart_spec dev_defs dev_eof /* ../../conf/devices */
specs; /* rest of machine description */
hdrs:
hdrs hdr |
/* empty */;
hdr:
include |
'\n';
machine_spec:
XMACHINE WORD = { setmachine($2,NULL); } |
XMACHINE WORD WORD = { setmachine($2,$3); } |
error = { stop("cannot proceed without machine specifier"); };
dev_eof:
ENDFILE = { enddefs(lastfile); checkfiles(); };
maxpart_blanks:
maxpart_blanks '\n' |
/* empty */;
maxpart_spec:
maxpart_blanks MAXPARTITIONS NUMBER = { setmaxpartitions($3); } |
error = { stop("cannot proceed without maxpartitions specifier"); };
/*
* Various nonterminals shared between the grammars.
*/
file:
XFILE PATHNAME fopts fflgs rule = { addfile($2, $3, $4, $5); };
/* order of options is important, must use right recursion */
fopts:
WORD fopts = { ($$ = new_n($1))->nv_next = $2; } |
/* empty */ = { $$ = NULL; };
fflgs:
fflgs FFLAG = { $$ = $1 | $2; } |
/* empty */ = { $$ = 0; };
rule:
COMPILE_WITH WORD = { $$ = $2; } |
/* empty */ = { $$ = NULL; };
include:
INCLUDE WORD = { (void)include($2, '\n'); };
/*
* The machine definitions grammar.
*/
dev_defs:
dev_defs dev_def |
/* empty */;
dev_def:
one_def '\n' = { adepth = 0; } |
'\n' |
error '\n' = { cleanup(); };
one_def:
file |
include |
DEFINE WORD interface_opt = { (void)defattr($2, $3); } |
DEVICE devbase AT atlist veclist_opt interface_opt attrs_opt
= { defdev($2, 0, $4, $5, $6, $7); } |
MAXUSERS NUMBER NUMBER NUMBER = { setdefmaxusers($2, $3, $4); } |
PSEUDO_DEVICE devbase attrs_opt = { defdev($2,1,NULL,NULL,NULL,$3); } |
MAJOR '{' majorlist '}';
atlist:
atlist ',' atname = { ($$ = new_n($3))->nv_next = $1; } |
atname = { $$ = new_n($1); };
atname:
WORD = { $$ = $1; } |
ROOT = { $$ = NULL; };
veclist_opt:
VECTOR veclist = { $$ = $2; } |
/* empty */ = { $$ = NULL; };
/* veclist order matters, must use right recursion */
veclist:
WORD veclist = { ($$ = new_n($1))->nv_next = $2; } |
WORD = { $$ = new_n($1); };
devbase:
WORD = { $$ = getdevbase($1); };
interface_opt:
'{' loclist_opt '}' = { ($$ = new_n(""))->nv_next = $2; } |
/* empty */ = { $$ = NULL; };
loclist_opt:
loclist = { $$ = $1; } |
/* empty */ = { $$ = NULL; };
/* loclist order matters, must use right recursion */
loclist:
locdef ',' loclist = { ($$ = $1)->nv_next = $3; } |
locdef = { $$ = $1; };
/* "[ WORD locdefault ]" syntax may be unnecessary... */
locdef:
WORD locdefault = { $$ = new_nsi($1, $2, 0); } |
WORD = { $$ = new_nsi($1, NULL, 0); } |
'[' WORD locdefault ']' = { $$ = new_nsi($2, $3, 1); };
locdefault:
'=' value = { $$ = $2; };
value:
WORD = { $$ = $1; } |
signed_number = { char bf[40];
(void)sprintf(bf, FORMAT($1), $1);
$$ = intern(bf); };
signed_number:
NUMBER = { $$ = $1; } |
'-' NUMBER = { $$ = -$2; };
attrs_opt:
':' attrs = { $$ = $2; } |
/* empty */ = { $$ = NULL; };
attrs:
attrs ',' attr = { ($$ = new_p($3))->nv_next = $1; } |
attr = { $$ = new_p($1); };
attr:
WORD = { $$ = getattr($1); };
majorlist:
majorlist ',' majordef |
majordef;
majordef:
devbase '=' NUMBER = { setmajor($1, $3); };
/*
* The configuration grammar.
*/
specs:
specs spec |
/* empty */;
spec:
config_spec '\n' = { adepth = 0; } |
'\n' |
error '\n' = { cleanup(); };
config_spec:
file |
include |
OPTIONS opt_list |
MAKEOPTIONS mkopt_list |
MAXUSERS NUMBER = { setmaxusers($2); } |
CONFIG conf sysparam_list = { addconf(&conf); } |
PSEUDO_DEVICE WORD npseudo = { addpseudo($2, $3); } |
device_instance AT attachment locators flags_opt
= { adddev($1, $3, $4, $5); };
mkopt_list:
mkopt_list ',' mkoption |
mkoption;
mkoption:
WORD '=' value = { addmkoption($1, $3); }
opt_list:
opt_list ',' option |
option;
option:
WORD = { addoption($1, NULL); } |
WORD '=' value = { addoption($1, $3); };
conf:
WORD = { conf.cf_name = $1;
conf.cf_lineno = currentline();
conf.cf_root = NULL;
conf.cf_swap = NULL;
conf.cf_dump = NULL; };
sysparam_list:
sysparam_list sysparam |
sysparam;
sysparam:
ROOT on_opt dev_spec = { setconf(&conf.cf_root, "root", $3); } |
SWAP on_opt swapdev_list = { setconf(&conf.cf_swap, "swap", $3); } |
DUMPS on_opt dev_spec = { setconf(&conf.cf_dump, "dumps", $3); };
swapdev_list:
dev_spec AND swapdev_list = { ($$ = $1)->nv_next = $3; } |
dev_spec = { $$ = $1; };
dev_spec:
WORD = { $$ = new_si($1, NODEV); } |
major_minor = { $$ = new_si(NULL, $1); };
major_minor:
MAJOR NUMBER MINOR NUMBER = { $$ = makedev($2, $4); };
on_opt:
ON | /* empty */;
npseudo:
NUMBER = { $$ = $1; } |
/* empty */ = { $$ = 1; };
device_instance:
WORD '*' = { $$ = starref($1); } |
WORD = { $$ = $1; };
attachment:
ROOT = { $$ = NULL; } |
WORD '?' = { $$ = wildref($1); } |
WORD '*' = { $$ = starref($1); } |
WORD = { $$ = $1; };
locators:
locators locator = { ($$ = $2)->nv_next = $1; } |
/* empty */ = { $$ = NULL; };
locator:
WORD value = { $$ = new_ns($1, $2); } |
WORD '?' = { $$ = new_ns($1, NULL); };
flags_opt:
FLAGS NUMBER = { $$ = $2; } |
/* empty */ = { $$ = 0; };
%%
void
yyerror(s)
const char *s;
{
error("%s", s);
}
/*
* Cleanup procedure after syntax error: release any nvlists
* allocated during parsing the current line.
*/
static void
cleanup()
{
register struct nvlist **np;
register int i;
for (np = alloc, i = adepth; --i >= 0; np++)
nvfree(*np);
adepth = 0;
}
static void
setmachine(mch, mcharch)
const char *mch;
const char *mcharch;
{
char buf[MAXPATHLEN], archbuf[MAXPATHLEN];
machine = mch;
machinearch = mcharch;
if (machinearch != NULL)
(void)sprintf(archbuf, "../../%s/conf/files.%s.newconf",
machinearch, machinearch);
else
strncpy(archbuf, _PATH_DEVNULL, MAXPATHLEN);
(void)sprintf(buf, "files.%s.newconf", machine);
if (include(buf, ENDFILE) ||
include(archbuf, ENDFILE) ||
include("../../../conf/files.newconf", ENDFILE))
exit(1);
}
static void
setmaxpartitions(n)
int n;
{
maxpartitions = n;
}

View File

@ -1,280 +0,0 @@
/*
* 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. 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, Berkeley and its contributors.
* 4. 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: @(#)hash.c 8.1 (Berkeley) 6/6/93
* $Id: hash.c,v 1.5 1994/06/22 10:44:10 pk Exp $
*/
#include <sys/param.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
/*
* Interned strings are kept in a hash table. By making each string
* unique, the program can compare strings by comparing pointers.
*/
struct hashent {
struct hashent *h_next; /* hash buckets are chained */
const char *h_name; /* the string */
u_int h_hash; /* its hash value */
void *h_value; /* other values (for name=value) */
};
struct hashtab {
size_t ht_size; /* size (power of 2) */
u_int ht_mask; /* == ht_size - 1 */
u_int ht_used; /* number of entries used */
u_int ht_lim; /* when to expand */
struct hashent **ht_tab; /* base of table */
};
static struct hashtab strings;
/*
* HASHFRACTION controls ht_lim, which in turn controls the average chain
* length. We allow a few entries, on average, as comparing them is usually
* cheap (the h_hash values prevent a strcmp).
*/
#define HASHFRACTION(sz) ((sz) * 3 / 2)
/* round up to next multiple of y, where y is a power of 2 */
#define ROUND(x, y) (((x) + (y) - 1) & ~((y) - 1))
/*
* Allocate space that will never be freed.
*/
static void *
poolalloc(size)
size_t size;
{
register char *p;
register size_t alloc;
static char *pool;
static size_t nleft;
if (nleft < size) {
/*
* Compute a `good' size to allocate via malloc.
* 16384 is a guess at a good page size for malloc;
* 32 is a guess at malloc's overhead.
*/
alloc = ROUND(size + 32, 16384) - 32;
p = emalloc(alloc);
nleft = alloc - size;
} else {
p = pool;
nleft -= size;
}
pool = p + size;
return (p);
}
/*
* Initialize a new hash table. The size must be a power of 2.
*/
static void
ht_init(ht, sz)
register struct hashtab *ht;
size_t sz;
{
register struct hashent **h;
register u_int n;
h = emalloc(sz * sizeof *h);
ht->ht_tab = h;
ht->ht_size = sz;
ht->ht_mask = sz - 1;
for (n = 0; n < sz; n++)
*h++ = NULL;
ht->ht_used = 0;
ht->ht_lim = HASHFRACTION(sz);
}
/*
* Expand an existing hash table.
*/
static void
ht_expand(ht)
register struct hashtab *ht;
{
register struct hashent *p, **h, **oldh, *q;
register u_int n, i;
n = ht->ht_size * 2;
h = emalloc(n * sizeof *h);
for (i = 0; i < n; i++)
h[i] = NULL;
oldh = ht->ht_tab;
n--;
for (i = ht->ht_size; i != 0; i--) {
for (p = *oldh++; p != NULL; p = q) {
q = p->h_next;
p->h_next = h[p->h_hash & n];
h[p->h_hash & n] = p;
}
}
free(ht->ht_tab);
ht->ht_tab = h;
ht->ht_mask = n;
ht->ht_size = ++n;
ht->ht_lim = HASHFRACTION(n);
}
/*
* Make a new hash entry, setting its h_next to NULL.
*/
static inline struct hashent *
newhashent(name, h)
const char *name;
u_int h;
{
register struct hashent *hp;
register char *m;
m = poolalloc(sizeof(*hp) + ALIGNBYTES);
hp = (struct hashent *)ALIGN(m);
hp->h_name = name;
hp->h_hash = h;
hp->h_next = NULL;
return (hp);
}
/*
* Hash a string.
*/
static inline u_int
hash(str)
register const char *str;
{
register u_int h;
for (h = 0; *str;)
h = (h << 5) + h + *str++;
return (h);
}
void
initintern()
{
ht_init(&strings, 128);
}
/*
* Generate a single unique copy of the given string. We expect this
* function to be used frequently, so it should be fast.
*/
const char *
intern(s)
register const char *s;
{
register struct hashtab *ht;
register struct hashent *hp, **hpp;
register u_int h;
register char *p;
register size_t l;
ht = &strings;
h = hash(s);
hpp = &ht->ht_tab[h & ht->ht_mask];
for (; (hp = *hpp) != NULL; hpp = &hp->h_next)
if (hp->h_hash == h && strcmp(hp->h_name, s) == 0)
return (hp->h_name);
l = strlen(s) + 1;
p = poolalloc(l);
bcopy(s, p, l);
*hpp = newhashent(p, h);
if (++ht->ht_used > ht->ht_lim)
ht_expand(ht);
return (p);
}
struct hashtab *
ht_new()
{
register struct hashtab *ht;
ht = emalloc(sizeof *ht);
ht_init(ht, 8);
return (ht);
}
/*
* Insert and/or replace.
*/
int
ht_insrep(ht, nam, val, replace)
register struct hashtab *ht;
register const char *nam;
void *val;
int replace;
{
register struct hashent *hp, **hpp;
register u_int h;
h = hash(nam);
hpp = &ht->ht_tab[h & ht->ht_mask];
for (; (hp = *hpp) != NULL; hpp = &hp->h_next) {
if (hp->h_name == nam) {
if (replace)
hp->h_value = val;
return (1);
}
}
*hpp = hp = newhashent(nam, h);
hp->h_value = val;
return (0);
}
void *
ht_lookup(ht, nam)
register struct hashtab *ht;
register const char *nam;
{
register struct hashent *hp, **hpp;
register u_int h;
h = hash(nam);
hpp = &ht->ht_tab[h & ht->ht_mask];
for (; (hp = *hpp) != NULL; hpp = &hp->h_next)
if (hp->h_name == nam)
return (hp->h_value);
return (NULL);
}

View File

@ -1,490 +0,0 @@
/*
* 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. 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, Berkeley and its contributors.
* 4. 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: @(#)main.c 8.1 (Berkeley) 6/6/93
* $Id: main.c,v 1.7 1995/01/25 20:44:42 cgd Exp $
*/
#ifndef lint
static char copyright[] =
"@(#) Copyright (c) 1992, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "config.h"
int firstfile __P((const char *));
int yyparse __P((void));
extern char *optarg;
extern int optind;
static struct hashtab *opttab;
static struct hashtab *mkopttab;
static struct nvlist **nextopt;
static struct nvlist **nextmkopt;
static __dead void stop __P((void));
static int do_option __P((struct hashtab *, struct nvlist ***,
const char *, const char *, const char *));
static int crosscheck __P((void));
static int badstar __P((void));
static int mksymlinks __P((void));
static int has_instances __P((struct devbase *, int));
static int hasparent __P((struct devi *));
static int cfcrosscheck __P((struct config *, const char *, struct nvlist *));
int
main(argc, argv)
int argc;
char **argv;
{
register char *p;
int pflag, ch;
struct stat st;
pflag = 0;
while ((ch = getopt(argc, argv, "gp")) != EOF) {
switch (ch) {
case 'g':
/*
* In addition to DEBUG, you probably wanted to
* set "options KGDB" and maybe others. We could
* do that for you, but you really should just
* put them in the config file.
*/
(void)fputs(
"-g is obsolete (use makeoptions DEBUG=\"-g\")\n",
stderr);
goto usage;
case 'p':
/*
* Essentially the same as makeoptions PROF="-pg",
* but also changes the path from ../../compile/FOO
* to ../../compile/FOO.prof; i.e., compile a
* profiling kernel based on a typical "regular"
* kernel.
*
* Note that if you always want profiling, you
* can (and should) use a "makeoptions" line.
*/
pflag = 1;
break;
case '?':
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc != 1) {
usage:
(void)fputs("usage: config [-p] sysname\n", stderr);
exit(1);
}
conffile = argv[0];
if (firstfile(conffile)) {
(void)fprintf(stderr, "config: cannot read %s: %s\n",
conffile, strerror(errno));
exit(2);
}
/*
* Init variables.
*/
minmaxusers = 1;
maxmaxusers = 10000;
initintern();
initfiles();
initsem();
devbasetab = ht_new();
selecttab = ht_new();
needcnttab = ht_new();
opttab = ht_new();
mkopttab = ht_new();
nextopt = &options;
nextmkopt = &mkoptions;
/*
* Handle profiling (must do this before we try to create any
* files).
*/
if (pflag) {
char *s;
s = emalloc(strlen(conffile) + sizeof(".PROF"));
(void)sprintf(s, "%s.PROF", conffile);
confdirbase = s;
(void)addmkoption(intern("PROF"), "-pg");
(void)addoption(intern("GPROF"), NULL);
} else
confdirbase = conffile;
/*
* Verify, creating if necessary, the compilation directory.
*/
p = path(NULL);
if (stat(p, &st)) {
if (mkdir(p, 0777)) {
(void)fprintf(stderr, "config: cannot create %s: %s\n",
p, strerror(errno));
exit(2);
}
} else if (!S_ISDIR(st.st_mode)) {
(void)fprintf(stderr, "config: %s is not a directory\n", p);
exit(2);
}
/*
* Parse config file (including machine definitions).
*/
if (yyparse())
stop();
/*
* Fix (as in `set firmly in place') files.
*/
if (fixfiles())
stop();
/*
* Perform cross-checking.
*/
if (maxusers == 0) {
if (defmaxusers) {
(void)printf("maxusers not specified; %d assumed\n",
defmaxusers);
maxusers = defmaxusers;
} else {
(void)fprintf(stderr,
"config: need \"maxusers\" line\n");
errors++;
}
}
if (crosscheck() || errors)
stop();
/*
* Squeeze things down and finish cross-checks (STAR checks must
* run after packing).
*/
pack();
if (badstar())
stop();
/*
* Ready to go. Build all the various files.
*/
if (mksymlinks() || mkmakefile() || mkheaders() || mkswap() ||
mkioconf())
stop();
(void)printf("Don't forget to run \"make depend\"\n");
exit(0);
}
/*
* Make a symlink for "machine" so that "#include <machine/foo.h>" works,
* and for the machine's CPU architecture, so that works as well.
*/
static int
mksymlinks()
{
int ret;
char *p, buf[200];
p = path("machine");
(void)sprintf(buf, "../../include", machine);
(void)unlink(p);
ret = symlink(buf, p);
if (ret)
(void)fprintf(stderr, "config: symlink(%s -> %s): %s\n",
p, buf, strerror(errno));
free(p);
if (machinearch != NULL) {
p = path(machinearch);
(void)sprintf(buf, "../../../%s/include", machinearch);
} else {
p = path(machine);
(void)sprintf(buf, "machine");
}
(void)unlink(p);
ret = symlink(buf, p);
if (ret)
(void)fprintf(stderr, "config: symlink(%s -> %s): %s\n",
p, buf, strerror(errno));
free(p);
return (ret);
}
static __dead void
stop()
{
(void)fprintf(stderr, "*** Stop.\n");
exit(1);
}
/*
* Add an option from "options FOO". Note that this selects things that
* are "optional foo".
*/
void
addoption(name, value)
const char *name, *value;
{
register const char *n;
register char *p, c;
char low[500];
if (do_option(opttab, &nextopt, name, value, "options"))
return;
/* make lowercase, then add to select table */
for (n = name, p = low; (c = *n) != '\0'; n++)
*p++ = isupper(c) ? tolower(c) : c;
*p = 0;
n = intern(low);
(void)ht_insert(selecttab, n, (void *)n);
}
/*
* Add a "make" option.
*/
void
addmkoption(name, value)
const char *name, *value;
{
(void)do_option(mkopttab, &nextmkopt, name, value, "mkoptions");
}
/*
* Add a name=value pair to an option list. The value may be NULL.
*/
static int
do_option(ht, nppp, name, value, type)
struct hashtab *ht;
struct nvlist ***nppp;
const char *name, *value, *type;
{
register struct nvlist *nv;
/* assume it will work */
nv = newnv(name, value, NULL, 0);
if (ht_insert(ht, name, nv) == 0) {
**nppp = nv;
*nppp = &nv->nv_next;
return (0);
}
/* oops, already got that option */
nvfree(nv);
if ((nv = ht_lookup(ht, name)) == NULL)
panic("do_option");
if (nv->nv_str != NULL)
error("already have %s `%s=%s'", type, name, nv->nv_str);
else
error("already have %s `%s'", type, name);
return (1);
}
/*
* Return true if there is at least one instance of the given unit
* on the given base (or any units, if unit == WILD).
*/
static int
has_instances(dev, unit)
register struct devbase *dev;
int unit;
{
register struct devi *i;
if (unit == WILD)
return (dev->d_ihead != NULL);
for (i = dev->d_ihead; i != NULL; i = i->i_bsame)
if (unit == i->i_unit)
return (1);
return (0);
}
static int
hasparent(i)
register struct devi *i;
{
register struct nvlist *nv;
int atunit = i->i_atunit;
if (i->i_atdev != NULL && has_instances(i->i_atdev, atunit))
return (1);
if (i->i_atattr != NULL)
for (nv = i->i_atattr->a_refs; nv != NULL; nv = nv->nv_next)
if (has_instances(nv->nv_ptr, atunit))
return (1);
return (0);
}
static int
cfcrosscheck(cf, what, nv)
register struct config *cf;
const char *what;
register struct nvlist *nv;
{
register struct devbase *dev;
register struct devi *pd;
int errs;
for (errs = 0; nv != NULL; nv = nv->nv_next) {
if (nv->nv_name == NULL)
continue;
dev = ht_lookup(devbasetab, nv->nv_name);
if (dev == NULL)
panic("cfcrosscheck(%s)", nv->nv_name);
if (has_instances(dev, STAR) ||
has_instances(dev, minor(nv->nv_int) / maxpartitions))
continue;
for (pd = allpseudo; pd != NULL; pd = pd->i_next)
if (pd->i_base == dev &&
(minor(nv->nv_int) / maxpartitions) < dev->d_umax &&
(minor(nv->nv_int) / maxpartitions) >= 0)
goto loop;
(void)fprintf(stderr,
"%s%d: %s says %s on %s, but there's no %s\n",
conffile, cf->cf_lineno,
cf->cf_name, what, nv->nv_str, nv->nv_str);
errs++;
loop:
}
return (errs);
}
/*
* Cross-check the configuration: make sure that each target device
* or attribute (`at foo[0*?]') names at least one real device. Also
* see that the root, swap, and dump devices for all configurations
* are there.
*/
int
crosscheck()
{
register struct devi *i;
register struct config *cf;
int errs;
errs = 0;
for (i = alldevi; i != NULL; i = i->i_next) {
if (i->i_at == NULL || hasparent(i))
continue;
xerror(conffile, i->i_lineno,
"%s at %s is orphaned", i->i_name, i->i_at);
if (i->i_atunit == WILD)
(void)fprintf(stderr, " (no %s's declared)\n",
i->i_base->d_name);
else
(void)fprintf(stderr, " (no %s declared)\n", i->i_at);
errs++;
}
if (allcf == NULL) {
(void)fprintf(stderr, "%s has no configurations!\n",
conffile);
errs++;
}
for (cf = allcf; cf != NULL; cf = cf->cf_next) {
if (cf->cf_root != NULL) { /* i.e., not swap generic */
errs += cfcrosscheck(cf, "root", cf->cf_root);
errs += cfcrosscheck(cf, "swap", cf->cf_swap);
errs += cfcrosscheck(cf, "dumps", cf->cf_dump);
}
}
return (errs);
}
/*
* Check to see if there is more than one *'d unit for any device,
* or a *'d unit with a needs-count file.
*/
int
badstar()
{
register struct devbase *d;
register struct devi *i;
register int errs, n;
errs = 0;
for (d = allbases; d != NULL; d = d->d_next) {
for (i = d->d_ihead; i != NULL; i = i->i_bsame)
if (i->i_unit == STAR)
goto foundstar;
continue;
foundstar:
if (ht_lookup(needcnttab, d->d_name)) {
(void)fprintf(stderr,
"config: %s's cannot be *'d until its driver is fixed\n",
d->d_name);
errs++;
continue;
}
for (n = 0; i != NULL; i = i->i_alias)
if (!i->i_collapsed)
n++;
if (n < 1)
panic("badstar() n<1");
if (n == 1)
continue;
(void)fprintf(stderr,
"config: %d %s*'s in configuration; can only have 1\n",
n, d->d_name);
errs++;
}
return (errs);
}

View File

@ -1,149 +0,0 @@
/*
* 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. 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, Berkeley and its contributors.
* 4. 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: @(#)mkheaders.c 8.1 (Berkeley) 6/6/93
* $Id: mkheaders.c,v 1.3 1994/06/22 10:44:14 pk Exp $
*/
#include <sys/param.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
static int emitcnt __P((struct nvlist *));
static int err __P((const char *, char *, FILE *));
static char *cntname __P((const char *));
/*
* Make headers containing counts, as needed.
*/
int
mkheaders()
{
register struct files *fi;
for (fi = allfiles; fi != NULL; fi = fi->fi_next) {
if (fi->fi_flags & FI_HIDDEN)
continue;
if (fi->fi_flags & (FI_NEEDSCOUNT | FI_NEEDSFLAG) &&
emitcnt(fi->fi_opt))
return (1);
}
return (0);
}
static int
emitcnt(head)
register struct nvlist *head;
{
register struct nvlist *nv;
register FILE *fp;
register char *fname;
int cnt;
char nam[100];
char buf[BUFSIZ];
(void)sprintf(buf, "%s.h", head->nv_name);
fname = path(buf);
if ((fp = fopen(fname, "r")) == NULL)
goto writeit;
nv = head;
while (fgets(buf, sizeof(buf), fp) != NULL) {
if (nv == NULL)
goto writeit;
if (sscanf(buf, "#define %s %d", nam, &cnt) != 2 ||
strcmp(nam, cntname(nv->nv_name)) != 0 ||
cnt != nv->nv_int)
goto writeit;
nv = nv->nv_next;
}
if (ferror(fp))
return (err("read", fname, fp));
(void)fclose(fp);
if (nv == NULL)
return (0);
writeit:
if ((fp = fopen(fname, "w")) == NULL) {
(void)fprintf(stderr, "config: cannot write %s: %s\n",
fname, strerror(errno));
return (1);
}
for (nv = head; nv != NULL; nv = nv->nv_next)
if (fprintf(fp, "#define\t%s\t%d\n",
cntname(nv->nv_name), nv->nv_int) < 0)
return (err("writ", fname, fp));
if (fclose(fp))
return (err("writ", fname, NULL));
return (0);
}
static int
err(what, fname, fp)
const char *what;
char *fname;
FILE *fp;
{
(void)fprintf(stderr, "config: error %sing %s: %s\n",
what, fname, strerror(errno));
if (fp)
(void)fclose(fp);
free(fname);
return (1);
}
static char *
cntname(src)
register const char *src;
{
register char *dst, c;
static char buf[100];
dst = buf;
*dst++ = 'N';
while ((c = *src++) != 0)
*dst++ = islower(c) ? toupper(c) : c;
*dst = 0;
return (buf);
}

View File

@ -1,396 +0,0 @@
/*
* 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. 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, Berkeley and its contributors.
* 4. 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: @(#)mkioconf.c 8.1 (Berkeley) 6/6/93
* $Id: mkioconf.c,v 1.3 1994/06/22 10:44:16 pk Exp $
*/
#include <sys/param.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
/*
* Make ioconf.c.
*/
static int cforder __P((const void *, const void *));
static int emitcfdata __P((FILE *));
static int emitexterns __P((FILE *));
static int emithdr __P((FILE *));
static int emitloc __P((FILE *));
static int emitpseudo __P((FILE *));
static int emitpv __P((FILE *));
static int emitroots __P((FILE *));
static int emitvec __P((FILE *));
static char *vecname __P((char *, const char *, int));
static const char *s_i386;
#define SEP(pos, max) (((u_int)(pos) % (max)) == 0 ? "\n\t" : " ")
/*
* NEWLINE can only be used in the emitXXX functions.
* In most cases it can be subsumed into an fprintf.
*/
#define NEWLINE if (putc('\n', fp) < 0) return (1)
int
mkioconf()
{
register FILE *fp;
register char *fname;
int v;
s_i386 = intern("i386");
fname = path("ioconf.c");
qsort(packed, npacked, sizeof *packed, cforder);
if ((fp = fopen(fname, "w")) == NULL) {
(void)fprintf(stderr, "config: cannot write %s: %s\n",
fname, strerror(errno));
return (1);
}
v = emithdr(fp);
if (v != 0 || emitvec(fp) || emitexterns(fp) || emitloc(fp) ||
emitpv(fp) || emitcfdata(fp) || emitroots(fp) || emitpseudo(fp)) {
if (v >= 0)
(void)fprintf(stderr,
"config: error writing %s: %s\n",
fname, strerror(errno));
(void)fclose(fp);
/* (void)unlink(fname); */
free(fname);
return (1);
}
(void)fclose(fp);
free(fname);
return (0);
}
static int
cforder(a, b)
const void *a, *b;
{
register int n1, n2;
n1 = (*(struct devi **)a)->i_cfindex;
n2 = (*(struct devi **)b)->i_cfindex;
return (n1 - n2);
}
static int
emithdr(ofp)
register FILE *ofp;
{
register FILE *ifp;
register int n;
char ifn[200], buf[BUFSIZ];
if (fprintf(ofp, "\
/*\n\
* MACHINE GENERATED: DO NOT EDIT\n\
*\n\
* ioconf.c, from \"%s\"\n\
*/\n\n", conffile) < 0)
return (1);
(void)sprintf(ifn, "ioconf.incl.%s", machine);
if ((ifp = fopen(ifn, "r")) != NULL) {
while ((n = fread(buf, 1, sizeof(buf), ifp)) > 0)
if (fwrite(buf, 1, n, ofp) != n)
return (1);
if (ferror(ifp)) {
(void)fprintf(stderr, "config: error reading %s: %s\n",
ifn, strerror(errno));
(void)fclose(ifp);
return (-1);
}
(void)fclose(ifp);
} else {
if (fputs("\
#include <sys/param.h>\n\
#include <sys/device.h>\n", ofp) < 0)
return (1);
}
return (0);
}
static int
emitexterns(fp)
register FILE *fp;
{
register struct devbase *d;
NEWLINE;
for (d = allbases; d != NULL; d = d->d_next) {
if (d->d_ihead == NULL)
continue;
if (fprintf(fp, "extern struct cfdriver %scd;\n",
d->d_name) < 0)
return (1);
}
NEWLINE;
return (0);
}
static int
emitloc(fp)
register FILE *fp;
{
register int i;
if (fprintf(fp, "\n/* locators */\n\
static int loc[%d] = {", locators.used) < 0)
return (1);
for (i = 0; i < locators.used; i++)
if (fprintf(fp, "%s%s,", SEP(i, 8), locators.vec[i]) < 0)
return (1);
return (fprintf(fp, "\n};\n") < 0);
}
/*
* Emit global parents-vector.
*/
static int
emitpv(fp)
register FILE *fp;
{
register int i;
if (fprintf(fp, "\n/* parent vectors */\n\
static short pv[%d] = {", parents.used) < 0)
return (1);
for (i = 0; i < parents.used; i++)
if (fprintf(fp, "%s%d,", SEP(i, 16), parents.vec[i]) < 0)
return (1);
return (fprintf(fp, "\n};\n") < 0);
}
/*
* Emit the cfdata array.
*/
static int
emitcfdata(fp)
register FILE *fp;
{
register struct devi **p, *i, **par;
register int unit, v;
register const char *vs, *state, *basename;
register struct nvlist *nv;
register struct attr *a;
char *loc;
char locbuf[20];
if (fprintf(fp, "\n\
#define NORM FSTATE_NOTFOUND\n\
#define STAR FSTATE_STAR\n\
\n\
struct cfdata cfdata[] = {\n\
\t/* driver unit state loc flags parents ivstubs */\n") < 0)
return (1);
for (p = packed; (i = *p) != NULL; p++) {
/* the description */
if (fprintf(fp, "/*%3d: %s at ", i->i_cfindex, i->i_name) < 0)
return (1);
par = i->i_parents;
for (v = 0; v < i->i_pvlen; v++)
if (fprintf(fp, "%s%s", v == 0 ? "" : "|",
i->i_parents[v]->i_name) < 0)
return (1);
if (v == 0 && fputs("root", fp) < 0)
return (1);
a = i->i_atattr;
nv = a->a_locs;
for (nv = a->a_locs, v = 0; nv != NULL; nv = nv->nv_next, v++)
if (fprintf(fp, " %s %s",
nv->nv_name, i->i_locs[v]) < 0)
return (1);
if (fputs(" */\n", fp) < 0)
return (-1);
/* then the actual defining line */
basename = i->i_base->d_name;
if (i->i_unit == STAR) {
unit = i->i_base->d_umax;
state = "STAR";
} else {
unit = i->i_unit;
state = "NORM";
}
if (i->i_ivoff < 0) {
vs = "";
v = 0;
} else {
vs = "vec+";
v = i->i_ivoff;
}
if (i->i_locoff >= 0) {
(void)sprintf(locbuf, "loc+%3d", i->i_locoff);
loc = locbuf;
} else
loc = "loc";
if (fprintf(fp, "\
\t{&%scd,%s%2d, %s, %7s, %#6x, pv+%2d, %s%d},\n",
basename, strlen(basename) < 3 ? "\t\t" : "\t", unit,
state, loc, i->i_cfflags, i->i_pvoff, vs, v) < 0)
return (1);
}
return (fputs("\t{0}\n};\n", fp) < 0);
}
/*
* Emit the table of potential roots.
*/
static int
emitroots(fp)
register FILE *fp;
{
register struct devi **p, *i;
if (fputs("\nshort cfroots[] = {\n", fp) < 0)
return (1);
for (p = packed; (i = *p) != NULL; p++) {
if (i->i_at != NULL)
continue;
if (i->i_unit != 0 &&
(i->i_unit != STAR || i->i_base->d_umax != 0))
(void)fprintf(stderr,
"config: warning: `%s at root' is not unit 0\n",
i->i_name);
if (fprintf(fp, "\t%2d /* %s */,\n",
i->i_cfindex, i->i_name) < 0)
return (1);
}
return (fputs("\t-1\n};\n", fp) < 0);
}
/*
* Emit pseudo-device initialization.
*/
static int
emitpseudo(fp)
register FILE *fp;
{
register struct devi *i;
register struct devbase *d;
if (fputs("\n/* pseudo-devices */\n", fp) < 0)
return (1);
for (i = allpseudo; i != NULL; i = i->i_next)
if (fprintf(fp, "extern void %sattach __P((int));\n",
i->i_base->d_name) < 0)
return (1);
if (fputs("\nstruct pdevinit pdevinit[] = {\n", fp) < 0)
return (1);
for (i = allpseudo; i != NULL; i = i->i_next) {
d = i->i_base;
if (fprintf(fp, "\t{ %sattach, %d },\n",
d->d_name, d->d_umax) < 0)
return (1);
}
return (fputs("\t{ 0, 0 }\n};\n", fp) < 0);
}
/*
* Emit interrupt vector declarations, and calculate offsets.
*/
static int
emitvec(fp)
register FILE *fp;
{
register struct nvlist *head, *nv;
register struct devi **p, *i;
register int j, nvec, unit;
char buf[200];
nvec = 0;
for (p = packed; (i = *p) != NULL; p++) {
if ((head = i->i_base->d_vectors) == NULL)
continue;
if ((unit = i->i_unit) == STAR)
panic("emitvec unit==STAR");
if (nvec == 0)
NEWLINE;
for (j = 0, nv = head; nv != NULL; j++, nv = nv->nv_next)
if (fprintf(fp,
"/* IVEC %s %d */ extern void %s();\n",
nv->nv_name, unit,
vecname(buf, nv->nv_name, unit)) < 0)
return (1);
nvec += j + 1;
}
if (nvec == 0)
return (0);
if (fprintf(fp, "\nstatic void (*vec[%d]) __P((void)) = {", nvec) < 0)
return (1);
nvec = 0;
for (p = packed; (i = *p) != NULL; p++) {
if ((head = i->i_base->d_vectors) == NULL)
continue;
i->i_ivoff = nvec;
unit = i->i_unit;
for (nv = head; nv != NULL; nv = nv->nv_next)
if (fprintf(fp, "%s%s,",
SEP(nvec++, 4),
vecname(buf, nv->nv_name, unit)) < 0)
return (1);
if (fprintf(fp, "%s0,", SEP(nvec++, 4)) < 0)
return (1);
}
return (fputs("\n};\n", fp) < 0);
}
static char *
vecname(buf, name, unit)
char *buf;
const char *name;
int unit;
{
/* @#%* 386 uses a different name format */
if (machine == s_i386) {
(void)sprintf(buf, "V%s%d", name, unit);
return (buf);
}
(void)sprintf(buf, "X%s%d", name, unit);
return (buf);
}

View File

@ -1,368 +0,0 @@
/*
* 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. 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, Berkeley and its contributors.
* 4. 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: @(#)mkmakefile.c 8.1 (Berkeley) 6/6/93
* $Id: mkmakefile.c,v 1.6 1994/06/22 11:39:05 pk Exp $
*/
#include <sys/param.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "sem.h"
/*
* Make the Makefile.
*/
static int emitdefs __P((FILE *));
static int emitobjs __P((FILE *));
static int emitcfiles __P((FILE *));
static int emitsfiles __P((FILE *));
static int emitfiles __P((FILE *, int));
static int emitrules __P((FILE *));
static int emitload __P((FILE *));
int
mkmakefile()
{
register FILE *ifp, *ofp;
register int lineno;
register int (*fn) __P((FILE *));
register char *ofname;
char line[BUFSIZ], ifname[200];
(void)sprintf(ifname, "Makefile.%s", machine);
if ((ifp = fopen(ifname, "r")) == NULL) {
(void)fprintf(stderr, "config: cannot read %s: %s\n",
ifname, strerror(errno));
return (1);
}
ofname = path("Makefile");
if ((ofp = fopen(ofname, "w")) == NULL) {
(void)fprintf(stderr, "config: cannot write %s: %s\n",
ofname, strerror(errno));
free(ofname);
return (1);
}
if (emitdefs(ofp) != 0)
goto wrerror;
lineno = 0;
while (fgets(line, sizeof(line), ifp) != NULL) {
lineno++;
if (line[0] != '%') {
if (fputs(line, ofp) < 0)
goto wrerror;
continue;
}
if (strcmp(line, "%OBJS\n") == 0)
fn = emitobjs;
else if (strcmp(line, "%CFILES\n") == 0)
fn = emitcfiles;
else if (strcmp(line, "%SFILES\n") == 0)
fn = emitsfiles;
else if (strcmp(line, "%RULES\n") == 0)
fn = emitrules;
else if (strcmp(line, "%LOAD\n") == 0)
fn = emitload;
else {
xerror(ifname, lineno,
"unknown %% construct ignored: %s", line);
continue;
}
if ((*fn)(ofp))
goto wrerror;
}
if (ferror(ifp)) {
(void)fprintf(stderr,
"config: error reading %s (at line %d): %s\n",
ifname, lineno, strerror(errno));
goto bad;
/* (void)unlink(ofname); */
free(ofname);
return (1);
}
if (fclose(ofp)) {
ofp = NULL;
goto wrerror;
}
(void)fclose(ifp);
free(ofname);
return (0);
wrerror:
(void)fprintf(stderr, "config: error writing %s: %s\n",
ofname, strerror(errno));
bad:
if (ofp != NULL)
(void)fclose(ofp);
/* (void)unlink(ofname); */
free(ofname);
return (1);
}
static int
emitdefs(fp)
register FILE *fp;
{
register struct nvlist *nv;
register char *sp;
if (fputs("IDENT=", fp) < 0)
return (1);
sp = "";
for (nv = options; nv != NULL; nv = nv->nv_next) {
if (fprintf(fp, "%s-D%s", sp, nv->nv_name) < 0)
return 1;
if (nv->nv_str)
if (fprintf(fp, "=\"%s\"", nv->nv_str) < 0)
return 1;
sp = " ";
}
if (putc('\n', fp) < 0)
return (1);
if (fprintf(fp, "PARAM=-DMAXUSERS=%d\n", maxusers) < 0)
return (1);
for (nv = mkoptions; nv != NULL; nv = nv->nv_next)
if (fprintf(fp, "%s=%s\n", nv->nv_name, nv->nv_str) < 0)
return (1);
return (0);
}
static int
emitobjs(fp)
register FILE *fp;
{
register struct files *fi;
register int lpos, len, sp;
if (fputs("OBJS=", fp) < 0)
return (1);
sp = '\t';
lpos = 7;
for (fi = allfiles; fi != NULL; fi = fi->fi_next) {
if ((fi->fi_flags & FI_SEL) == 0)
continue;
len = strlen(fi->fi_base) + 2;
if (lpos + len > 72) {
if (fputs(" \\\n", fp) < 0)
return (1);
sp = '\t';
lpos = 7;
}
if (fprintf(fp, "%c%s.o", sp, fi->fi_base) < 0)
return (1);
lpos += len + 1;
sp = ' ';
}
if (lpos != 7 && putc('\n', fp) < 0)
return (1);
return (0);
}
static int
emitcfiles(fp)
FILE *fp;
{
return (emitfiles(fp, 'c'));
}
static int
emitsfiles(fp)
FILE *fp;
{
return (emitfiles(fp, 's'));
}
static int
emitfiles(fp, suffix)
register FILE *fp;
int suffix;
{
register struct files *fi;
register struct config *cf;
register int lpos, len, sp;
char swapname[100];
if (fprintf(fp, "%cFILES=", toupper(suffix)) < 0)
return (1);
sp = '\t';
lpos = 7;
for (fi = allfiles; fi != NULL; fi = fi->fi_next) {
if ((fi->fi_flags & FI_SEL) == 0)
continue;
len = strlen(fi->fi_path);
if (fi->fi_path[len - 1] != suffix)
continue;
if (*fi->fi_path != '/')
len += 3; /* "$S/" */
if (lpos + len > 72) {
if (fputs(" \\\n", fp) < 0)
return (1);
sp = '\t';
lpos = 7;
}
if (fprintf(fp, "%c%s%s", sp, *fi->fi_path != '/' ? "$S/" : "",
fi->fi_path) < 0)
return (1);
lpos += len + 1;
sp = ' ';
}
/*
* The allfiles list does not include the configuration-specific
* C source files. These files should be eliminated someday, but
* for now, we have to add them to ${CFILES} (and only ${CFILES}).
*/
if (suffix == 'c') {
for (cf = allcf; cf != NULL; cf = cf->cf_next) {
if (cf->cf_root == NULL)
(void)sprintf(swapname,
"$S/arch/%s/%s/swapgeneric.c",
machine, machine);
else
(void)sprintf(swapname, "swap%s.c",
cf->cf_name);
len = strlen(swapname);
if (lpos + len > 72) {
if (fputs(" \\\n", fp) < 0)
return (1);
sp = '\t';
lpos = 7;
}
if (fprintf(fp, "%c%s", sp, swapname) < 0)
return (1);
lpos += len + 1;
sp = ' ';
}
}
if (lpos != 7 && putc('\n', fp) < 0)
return (1);
return (0);
}
/*
* Emit the make-rules.
*/
static int
emitrules(fp)
register FILE *fp;
{
register struct files *fi;
register const char *cp;
int ch;
char buf[200];
for (fi = allfiles; fi != NULL; fi = fi->fi_next) {
if ((fi->fi_flags & FI_SEL) == 0)
continue;
if (fprintf(fp, "%s.o: %s%s\n", fi->fi_base,
*fi->fi_path != '/' ? "$S/" : "", fi->fi_path) < 0)
return (1);
if ((cp = fi->fi_mkrule) == NULL) {
cp = fi->fi_flags & FI_DRIVER ? "DRIVER" : "NORMAL";
ch = fi->fi_lastc;
if (islower(ch))
ch = toupper(ch);
(void)sprintf(buf, "${%s_%c%s}", cp, ch,
fi->fi_flags & FI_CONFIGDEP ? "_C" : "");
cp = buf;
}
if (fprintf(fp, "\t%s\n\n", cp) < 0)
return (1);
}
return (0);
}
/*
* Emit the load commands.
*
* This function is not to be called `spurt'.
*/
static int
emitload(fp)
register FILE *fp;
{
register struct config *cf;
register const char *nm, *swname;
int first;
if (fputs("all:", fp) < 0)
return (1);
for (cf = allcf; cf != NULL; cf = cf->cf_next) {
if (fprintf(fp, " %s", cf->cf_name) < 0)
return (1);
}
if (fputs("\n\n", fp) < 0)
return (1);
for (first = 1, cf = allcf; cf != NULL; cf = cf->cf_next) {
nm = cf->cf_name;
swname =
cf->cf_root != NULL ? cf->cf_name : "generic";
if (fprintf(fp, "%s: ${SYSTEM_DEP} swap%s.o", nm, swname) < 0)
return (1);
if (first) {
if (fputs(" newvers", fp) < 0)
return (1);
first = 0;
}
if (fprintf(fp, "\n\
\t${SYSTEM_LD_HEAD}\n\
\t${SYSTEM_LD} swap%s.o\n\
\t${SYSTEM_LD_TAIL}\n\
\n\
swap%s.o: ", swname, swname) < 0)
return (1);
if (cf->cf_root != NULL) {
if (fprintf(fp, "swap%s.c\n", nm) < 0)
return (1);
} else {
if (fprintf(fp, "$S/arch/%s/%s/swapgeneric.c\n",
machine, machine) < 0)
return (1);
}
if (fputs("\t${NORMAL_C}\n\n", fp) < 0)
return (1);
}
return (0);
}

View File

@ -1,141 +0,0 @@
/*
* 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. 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, Berkeley and its contributors.
* 4. 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: @(#)mkswap.c 8.1 (Berkeley) 6/6/93
* $Id: mkswap.c,v 1.7 1994/07/01 09:15:49 pk Exp $
*/
#include <sys/param.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "sem.h"
static int mkoneswap __P((struct config *));
/*
* Make the various swap*.c files. Nothing to do for generic swap.
*/
int
mkswap()
{
register struct config *cf;
for (cf = allcf; cf != NULL; cf = cf->cf_next)
if (cf->cf_root != NULL && mkoneswap(cf))
return (1);
return (0);
}
static char *
mkdevstr(d)
dev_t d;
{
static char buf[32];
if (d == NODEV)
(void)sprintf(buf, "NODEV");
else
(void)sprintf(buf, "makedev(%d, %d)", major(d), minor(d));
return buf;
}
static int
mkoneswap(cf)
register struct config *cf;
{
register struct nvlist *nv;
register FILE *fp;
register char *fname;
char buf[200];
char *mountroot;
(void)sprintf(buf, "swap%s.c", cf->cf_name);
fname = path(buf);
if ((fp = fopen(fname, "w")) == NULL) {
(void)fprintf(stderr, "config: cannot write %s: %s\n",
fname, strerror(errno));
return (1);
}
if (fputs("\
#include <sys/param.h>\n\
#include <sys/conf.h>\n\n", fp) < 0)
goto wrerror;
nv = cf->cf_root;
if (fprintf(fp, "dev_t\trootdev = %s;\t/* %s */\n",
mkdevstr(nv->nv_int), nv->nv_str) < 0)
goto wrerror;
nv = cf->cf_dump;
if (fprintf(fp, "dev_t\tdumpdev = %s;\t/* %s */\n",
mkdevstr(nv->nv_int), nv->nv_str) < 0)
goto wrerror;
if (fputs("\nstruct\tswdevt swdevt[] = {\n", fp) < 0)
goto wrerror;
for (nv = cf->cf_swap; nv != NULL; nv = nv->nv_next)
if (fprintf(fp, "\t{ %s,\t0,\t0 },\t/* %s */\n",
mkdevstr(nv->nv_int), nv->nv_str) < 0)
goto wrerror;
if (fputs("\t{ NODEV, 0, 0 }\n};\n\n", fp) < 0)
goto wrerror;
mountroot =
cf->cf_root->nv_str == s_nfs ? "nfs_mountroot" : "ffs_mountroot";
if (fprintf(fp, "extern int %s();\n", mountroot) < 0)
goto wrerror;
if (fprintf(fp, "int (*mountroot)() = %s;\n", mountroot) < 0)
goto wrerror;
if (fclose(fp)) {
fp = NULL;
goto wrerror;
}
free(fname);
return (0);
wrerror:
(void)fprintf(stderr, "config: error writing %s: %s\n",
fname, strerror(errno));
if (fp != NULL)
(void)fclose(fp);
/* (void)unlink(fname); */
free(fname);
return (1);
}

View File

@ -1,521 +0,0 @@
/*
* 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. 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, Berkeley and its contributors.
* 4. 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: @(#)pack.c 8.1 (Berkeley) 6/6/93
* $Id: pack.c,v 1.4 1994/12/23 16:25:43 cgd Exp $
*/
#include <sys/param.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
/*
* Packing. We have three separate kinds of packing here.
*
* First, we pack device instances, to collapse things like
*
* uba0 at sbi0 nexus ?
* uba0 at bi0 nexus ?
*
* into a single instance that is "at sbi0 or bi0".
*
* Second, we pack locators. Given something like
*
* hp0 at mba0 drive 0
* hp* at mba* drive ?
* ht0 at mba0 drive 0
* tu0 at ht0 slave 0
* ht* at mba* drive ?
* tu* at ht* slave ?
*
* (where the default drive and slave numbers are -1), we have three
* locators whose value is 0 and three whose value is -1. Rather than
* emitting six integers, we emit just two.
*
* Finally, we pack parent vectors. This is very much like packing
* locators. Unlike locators, however, parent vectors are always
* terminated by -1 (rather like the way C strings always end with
* a NUL).
*
* When packing locators, we would like to find sequences such as
* {1 2 3} {2 3 4} {3} {4 5}
* and turn this into the flat sequence {1 2 3 4 5}, with each subsequence
* given by the appropriate offset (here 0, 1, 2, and 3 respectively).
* When we pack parent vectors, overlap of this sort is impossible.
* Non-overlapping packing is much easier, and so we use that here
* and miss out on the chance to squeeze the locator sequence optimally.
* (So it goes.)
*/
typedef int (*vec_cmp_func) __P((const void *, int, int));
#define TAILHSIZE 128
#define PVHASH(i) ((i) & (TAILHSIZE - 1))
#define LOCHASH(l) (((long)(l) >> 2) & (TAILHSIZE - 1))
struct tails {
struct tails *t_next;
int t_ends_at;
};
static struct tails *tails[TAILHSIZE];
static int locspace;
static int pvecspace;
static int longest_pvec;
static void packdevi __P((void));
static void packlocs __P((void));
static void packpvec __P((void));
static void addparents __P((struct devi *src, struct devi *dst));
static int nparents __P((struct devi **, struct devbase *, int));
static int sameas __P((struct devi *, struct devi *));
static int findvec __P((const void *, int, int, vec_cmp_func, int));
static int samelocs __P((const void *, int, int));
static int addlocs __P((const char **, int));
static int loclencmp __P((const void *, const void *));
static int samepv __P((const void *, int, int));
static int addpv __P((short *, int));
static int pvlencmp __P((const void *, const void *));
static void resettails __P((void));
void
pack()
{
register struct devi *i;
register int n;
/* Pack instances and make parent vectors. */
packdevi();
/*
* Now that we know what we have, find upper limits on space
* needed for the loc[] and pv[] tables, and find the longest
* single pvec. The loc and pv table sizes are bounded by
* what we would get if no packing occurred.
*/
locspace = pvecspace = 0;
for (i = alldevi; i != NULL; i = i->i_next) {
if (i->i_collapsed)
continue;
locspace += i->i_atattr->a_loclen;
n = i->i_pvlen + 1;
if (n > longest_pvec)
longest_pvec = n;
pvecspace += n;
}
/* Allocate and pack loc[]. */
locators.vec = emalloc(locspace * sizeof(*locators.vec));
locators.used = 0;
packlocs();
/* Allocate and pack pv[]. */
parents.vec = emalloc(pvecspace * sizeof(*parents.vec));
parents.used = 0;
packpvec();
}
/*
* Pack instances together wherever possible. When everything is
* packed, go back and set up the parents for each. We must do this
* on a second pass because during the first one, we do not know which,
* if any, of the parents will collapse during packing.
*/
void
packdevi()
{
register struct devi *i, *l, *p;
register struct devbase *d;
register int j, m, n;
packed = emalloc((ndevi + 1) * sizeof *packed);
n = 0;
for (d = allbases; d != NULL; d = d->d_next) {
/*
* For each instance of each device, add or collapse
* all its aliases.
*/
for (i = d->d_ihead; i != NULL; i = i->i_bsame) {
m = n;
for (l = i; l != NULL; l = l->i_alias) {
l->i_pvlen = 0;
l->i_pvoff = -1;
l->i_locoff = -1;
l->i_ivoff = -1;
/* try to find an equivalent for l */
for (j = m; j < n; j++) {
p = packed[j];
if (sameas(l, p)) {
l->i_collapsed = 1;
l->i_cfindex = p->i_cfindex;
goto nextalias;
}
}
/* could not find a suitable alias */
l->i_collapsed = 0;
l->i_cfindex = n;
l->i_parents = emalloc(sizeof(*l->i_parents));
l->i_parents[0] = NULL;
packed[n++] = l;
nextalias:;
}
}
}
npacked = n;
packed[n] = NULL;
for (i = alldevi; i != NULL; i = i->i_next)
addparents(i, packed[i->i_cfindex]);
}
/*
* Return true if two aliases are "the same". In this case, they need
* to have the same config flags and the same locators.
*/
static int
sameas(i1, i2)
register struct devi *i1, *i2;
{
register const char **p1, **p2;
if (i1->i_cfflags != i2->i_cfflags)
return (0);
for (p1 = i1->i_locs, p2 = i2->i_locs; *p1 == *p2; p2++)
if (*p1++ == 0)
return (1);
return 0;
}
/*
* Add the parents associated with "src" to the (presumably uncollapsed)
* instance "dst".
*/
static void
addparents(src, dst)
register struct devi *src, *dst;
{
register struct nvlist *nv;
register struct devi *i, **p, **q;
register int j, n, old, new, ndup;
if (dst->i_collapsed)
panic("addparents() i_collapsed");
/* Collect up list of parents to add. */
if (src->i_at == NULL) /* none, 'cuz "at root" */
return;
if (src->i_atdev != NULL) {
n = nparents(NULL, src->i_atdev, src->i_atunit);
p = emalloc(n * sizeof *p);
if (n == 0)
return;
(void)nparents(p, src->i_atdev, src->i_atunit);
} else {
n = 0;
for (nv = src->i_atattr->a_refs; nv != NULL; nv = nv->nv_next)
n += nparents(NULL, nv->nv_ptr, src->i_atunit);
if (n == 0)
return;
p = emalloc(n * sizeof *p);
n = 0;
for (nv = src->i_atattr->a_refs; nv != NULL; nv = nv->nv_next)
n += nparents(p + n, nv->nv_ptr, src->i_atunit);
}
/* Now elide duplicates. */
ndup = 0;
for (j = 0; j < n; j++) {
i = p[j];
for (q = dst->i_parents; *q != NULL; q++) {
if (*q == i) {
ndup++;
p[j] = NULL;
break;
}
}
}
/* Finally, add all the non-duplicates. */
old = dst->i_pvlen;
new = old + (n - ndup);
if (old > new)
panic("addparents() old > new");
if (old == new) {
free(p);
return;
}
dst->i_parents = q = erealloc(dst->i_parents, (new + 1) * sizeof(*q));
dst->i_pvlen = new;
q[new] = NULL;
q += old;
for (j = 0; j < n; j++)
if (p[j] != NULL)
*q++ = p[j];
free(p);
}
/*
* Count up parents, and optionally store pointers to each.
*/
static int
nparents(p, dev, unit)
register struct devi **p;
register struct devbase *dev;
register int unit;
{
register struct devi *i, *l;
register int n;
n = 0;
/* for each instance ... */
for (i = dev->d_ihead; i != NULL; i = i->i_bsame) {
/* ... take each un-collapsed alias */
for (l = i; l != NULL; l = l->i_alias) {
if (!l->i_collapsed &&
(unit == WILD || unit == l->i_unit)) {
if (p != NULL)
*p++ = l;
n++;
}
}
}
return (n);
}
static void
packlocs()
{
register struct devi **p, *i;
register int l, o;
qsort(packed, npacked, sizeof *packed, loclencmp);
for (p = packed; (i = *p) != NULL; p++) {
if ((l = i->i_atattr->a_loclen) > 0) {
o = findvec(i->i_locs, LOCHASH(i->i_locs[l - 1]), l,
samelocs, locators.used);
i->i_locoff = o < 0 ? addlocs(i->i_locs, l) : o;
} else
i->i_locoff = -1;
}
resettails();
}
static void
packpvec()
{
register struct devi **p, *i, **par;
register int l, v, o;
register short *vec;
vec = emalloc(longest_pvec * sizeof(*vec));
qsort(packed, npacked, sizeof *packed, pvlencmp);
for (p = packed; (i = *p) != NULL; p++) {
l = i->i_pvlen;
if (l > longest_pvec) panic("packpvec");
par = i->i_parents;
for (v = 0; v < l; v++)
vec[v] = par[v]->i_cfindex;
if (l == 0 ||
(o = findvec(vec, PVHASH(vec[l - 1]), l,
samepv, parents.used)) < 0)
o = addpv(vec, l);
i->i_pvoff = o;
}
free(vec);
resettails();
}
/*
* Return the index at which the given vector already exists, or -1
* if it is not anywhere in the current set. If we return -1, we assume
* our caller will add it at the end of the current set, and we make
* sure that next time, we will find it there.
*/
static int
findvec(ptr, hash, len, cmp, nextplace)
const void *ptr;
int hash, len;
vec_cmp_func cmp;
int nextplace;
{
register struct tails *t, **hp;
register int off;
hp = &tails[hash];
for (t = *hp; t != NULL; t = t->t_next) {
off = t->t_ends_at - len;
if (off >= 0 && (*cmp)(ptr, off, len))
return (off);
}
t = emalloc(sizeof(*t));
t->t_next = *hp;
*hp = t;
t->t_ends_at = nextplace + len;
return (-1);
}
/*
* Comparison function for locators.
*/
static int
samelocs(ptr, off, len)
const void *ptr;
int off;
register int len;
{
register const char **p, **q;
for (p = &locators.vec[off], q = (const char **)ptr; --len >= 0;)
if (*p++ != *q++)
return (0); /* different */
return (1); /* same */
}
/*
* Add the given locators at the end of the global loc[] table.
*/
static int
addlocs(locs, len)
register const char **locs;
register int len;
{
register const char **p;
register int ret;
ret = locators.used;
if ((locators.used = ret + len) > locspace)
panic("addlocs: overrun");
for (p = &locators.vec[ret]; --len >= 0;)
*p++ = *locs++;
return (ret);
}
/*
* Comparison function for qsort-by-locator-length, longest first.
* We rashly assume that subtraction of these lengths does not overflow.
*/
static int
loclencmp(a, b)
const void *a, *b;
{
register int l1, l2;
l1 = (*(struct devi **)a)->i_atattr->a_loclen;
l2 = (*(struct devi **)b)->i_atattr->a_loclen;
return (l2 - l1);
}
/*
* Comparison function for parent vectors.
*/
static int
samepv(ptr, off, len)
const void *ptr;
int off;
register int len;
{
register short *p, *q;
for (p = &parents.vec[off], q = (short *)ptr; --len >= 0;)
if (*p++ != *q++)
return (0); /* different */
return (1); /* same */
}
/*
* Add the given parent vectors at the end of the global pv[] table.
*/
static int
addpv(pv, len)
register short *pv;
register int len;
{
register short *p;
register int ret;
static int firstend = -1;
/*
* If the vector is empty, reuse the first -1. It will be
* there if there are any nonempty vectors at all, since we
* do the longest first. If there are no nonempty vectors,
* something is probably wrong, but we will ignore that here.
*/
if (len == 0 && firstend >= 0)
return (firstend);
len++; /* account for trailing -1 */
ret = parents.used;
if ((parents.used = ret + len) > pvecspace)
panic("addpv: overrun");
for (p = &parents.vec[ret]; --len > 0;)
*p++ = *pv++;
*p = -1;
if (firstend < 0)
firstend = parents.used - 1;
return (ret);
}
/*
* Comparison function for qsort-by-parent-vector-length, longest first.
* We rashly assume that subtraction of these lengths does not overflow.
*/
static int
pvlencmp(a, b)
const void *a, *b;
{
register int l1, l2;
l1 = (*(struct devi **)a)->i_pvlen;
l2 = (*(struct devi **)b)->i_pvlen;
return (l2 - l1);
}
static void
resettails()
{
register struct tails **p, *t, *next;
register int i;
for (p = tails, i = TAILHSIZE; --i >= 0; p++) {
for (t = *p; t != NULL; t = next) {
next = t->t_next;
free(t);
}
*p = NULL;
}
}

View File

@ -1,240 +0,0 @@
%{
/*
* 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. 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, Berkeley and its contributors.
* 4. 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: @(#)scan.l 8.1 (Berkeley) 6/6/93
* $Id: scan.l,v 1.6 1995/01/25 20:44:43 cgd Exp $
*/
#include <sys/param.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "config.h"
#include "y.tab.h"
int yyline;
const char *yyfile;
const char *lastfile;
int include __P((const char *, int));
/*
* Data for returning to previous files from include files.
*/
struct incl {
struct incl *in_prev; /* previous includes in effect, if any */
YY_BUFFER_STATE in_buf; /* previous lex state */
const char *in_fname; /* previous file name */
int in_lineno; /* previous line number */
int in_preveof; /* previous eoftoken */
};
static struct incl *incl;
static int eoftoken; /* current EOF token */
static void endinclude __P((void));
#define yywrap() 1
%}
PATH [-/A-Za-z0-9_.]*[./][-/A-Za-z0-9_.]*
WORD [A-Za-z_][-A-Za-z_0-9]*
%%
/* plain keywords */
and { return AND; }
at { return AT; }
compile-with { return COMPILE_WITH; }
config { return CONFIG; }
define { return DEFINE; }
device { return DEVICE; }
dumps { return DUMPS; }
flags { return FLAGS; }
file { return XFILE; }
include { return INCLUDE; }
machine { return XMACHINE; }
major { return MAJOR; }
makeoptions { return MAKEOPTIONS; }
maxusers { return MAXUSERS; }
maxpartitions { return MAXPARTITIONS; }
minor { return MINOR; }
on { return ON; }
options { return OPTIONS; }
"pseudo-device" { return PSEUDO_DEVICE; }
root { return ROOT; }
swap { return SWAP; }
vector { return VECTOR; }
/* keywords with values */
config-dependent { yylval.val = FI_CONFIGDEP; return FFLAG; }
device-driver { yylval.val = FI_DRIVER; return FFLAG; }
needs-count { yylval.val = FI_NEEDSCOUNT; return FFLAG; }
needs-flag { yylval.val = FI_NEEDSFLAG; return FFLAG; }
/* all the rest */
{PATH} { yylval.str = intern(yytext); return PATHNAME; }
{WORD} { yylval.str = intern(yytext); return WORD; }
\"([^"]|\\\")*/\" {
yylval.str = intern(yytext + 1);
(void)input(); /* eat closing quote */
return WORD;
}
0[0-7]* {
yylval.val = strtol(yytext, NULL, 8);
return NUMBER;
}
0[xX][0-9a-fA-F]+ {
yylval.val = strtoul(yytext + 2, NULL, 16);
return NUMBER;
}
[1-9][0-9]* {
yylval.val = strtol(yytext, NULL, 10);
return NUMBER;
}
\n/[ \t] {
yyline++;
}
\n {
yyline++;
return '\n';
}
#.* { /* ignored (comment) */; }
[ \t]* { /* ignored (white space) */; }
. { return yytext[0]; }
<<EOF>> {
int tok;
tok = eoftoken;
eoftoken = YY_NULL;
if (incl != NULL)
endinclude();
return (tok);
}
%%
/*
* Open the "main" file (conffile).
*/
int
firstfile(fname)
const char *fname;
{
if ((yyin = fopen(fname, "r")) == NULL)
return (-1);
yyfile = conffile = fname;
yyline = 1;
eoftoken = YY_NULL;
return (0);
}
/*
* Open the named file for inclusion at the current point. Returns 0 on
* success (file opened and previous state pushed), nonzero on failure
* (fopen failed, complaint made). The `ateof' parameter controls the
* token to be returned at the end of the include file (typically '\n'
* or ENDFILE).
*/
int
include(fname, ateof)
const char *fname;
int ateof;
{
register FILE *fp;
register struct incl *in;
if ((fp = fopen(fname, "r")) == NULL) {
error("cannot open %s for reading: %s\n",
fname, strerror(errno));
return (-1);
}
in = emalloc(sizeof *in);
in->in_prev = incl;
in->in_buf = YY_CURRENT_BUFFER;
in->in_fname = yyfile;
in->in_lineno = yyline;
in->in_preveof = eoftoken;
incl = in;
yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE));
yyfile = intern(fname);
yyline = 1;
eoftoken = ateof;
return (0);
}
/*
* Terminate the most recent inclusion.
*/
static void
endinclude()
{
register struct incl *in;
if ((in = incl) == NULL)
panic("endinclude");
incl = in->in_prev;
lastfile = yyfile;
yy_delete_buffer(YY_CURRENT_BUFFER);
(void)fclose(yyin);
yy_switch_to_buffer(in->in_buf);
yyfile = in->in_fname;
yyline = in->in_lineno;
eoftoken = in->in_preveof;
free(in);
}
/*
* Return the current line number. If yacc has looked ahead and caused
* us to consume a newline, we have to subtract one. yychar is yacc's
* token lookahead, so we can tell.
*/
int
currentline()
{
extern int yychar;
return (yyline - (yychar == '\n'));
}

View File

@ -1,989 +0,0 @@
/*
* 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. 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, Berkeley and its contributors.
* 4. 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: @(#)sem.c 8.1 (Berkeley) 6/6/93
* $Id: sem.c,v 1.7 1995/01/25 20:44:44 cgd Exp $
*/
#include <sys/param.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "sem.h"
/*
* config semantics.
*/
#define NAMESIZE 100 /* local name buffers */
const char *s_generic;
const char *s_nfs;
static const char *s_qmark;
static struct hashtab *attrtab; /* for attribute lookup */
static struct hashtab *cfhashtab; /* for config lookup */
static struct hashtab *devitab; /* etc */
static struct attr errattr;
static struct devbase errdev;
static struct devbase **nextbase;
static struct config **nextcf;
static struct devi **nextdevi;
static struct devi **nextpseudo;
static int has_errobj __P((struct nvlist *, void *));
static struct nvlist *addtoattr __P((struct nvlist *, struct devbase *));
static int exclude __P((struct nvlist *, const char *, const char *));
static int resolve __P((struct nvlist **, const char *, const char *,
struct nvlist *, int));
static int lresolve __P((struct nvlist **, const char *, const char *,
struct nvlist *, int));
static struct devi *newdevi __P((const char *, int, struct devbase *d));
static struct devi *getdevi __P((const char *));
static const char *concat __P((const char *, int));
static int split __P((const char *, size_t, char *, size_t, int *));
static void selectbase __P((struct devbase *));
static int onlist __P((struct nvlist *, void *));
static const char **fixloc __P((const char *, struct attr *, struct nvlist *));
void
initsem()
{
attrtab = ht_new();
errattr.a_name = "<internal>";
allbases = NULL;
nextbase = &allbases;
cfhashtab = ht_new();
allcf = NULL;
nextcf = &allcf;
devitab = ht_new();
alldevi = NULL;
nextdevi = &alldevi;
errdev.d_name = "<internal>";
allpseudo = NULL;
nextpseudo = &allpseudo;
s_generic = intern("generic");
s_nfs = intern("nfs");
s_qmark = intern("?");
}
void
enddefs(fname)
const char *fname;
{
register struct devbase *dev;
for (dev = allbases; dev != NULL; dev = dev->d_next) {
if (!dev->d_isdef) {
(void)fprintf(stderr,
"%s: device `%s' used but not defined\n",
fname, dev->d_name);
errors++;
continue;
}
}
if (errors) {
(void)fprintf(stderr, "*** Stop.\n");
exit(1);
}
}
void
setdefmaxusers(min, def, max)
int min, def, max;
{
if (min < 1 || min > def || def > max)
error("maxusers must have 1 <= min <= default <= max");
else {
minmaxusers = min;
defmaxusers = def;
maxmaxusers = max;
}
}
void
setmaxusers(n)
int n;
{
if (maxusers != 0) {
error("duplicate maxusers parameter");
return;
}
maxusers = n;
if (n < minmaxusers) {
error("warning: minimum of %d maxusers assumed\n", minmaxusers);
errors--; /* take it away */
maxusers = minmaxusers;
} else if (n > maxmaxusers) {
error("warning: maxusers (%d) > %d", n, maxmaxusers);
errors--;
}
}
/*
* Define an attribute, optionally with an interface (a locator list).
* Since an empty locator list is logically different from "no interface",
* all locator lists include a dummy head node, which we discard here.
*/
int
defattr(name, locs)
const char *name;
struct nvlist *locs;
{
register struct attr *a;
register struct nvlist *nv;
register int len;
a = emalloc(sizeof *a);
if (ht_insert(attrtab, name, a)) {
free(a);
error("attribute `%s' already defined", name);
nvfreel(locs);
return (1);
}
a->a_name = name;
if (locs != NULL) {
a->a_iattr = 1;
a->a_locs = locs->nv_next;
nvfree(locs);
} else {
a->a_iattr = 0;
a->a_locs = NULL;
}
len = 0;
for (nv = a->a_locs; nv != NULL; nv = nv->nv_next)
len++;
a->a_loclen = len;
a->a_devs = NULL;
a->a_refs = NULL;
return (0);
}
/*
* Return true if the given `error object' is embedded in the given
* pointer list.
*/
static int
has_errobj(nv, obj)
register struct nvlist *nv;
register void *obj;
{
for (; nv != NULL; nv = nv->nv_next)
if (nv->nv_ptr == obj)
return (1);
return (0);
}
/*
* Add a device base to a list in an attribute (actually, to any list).
* Note that this does not check for duplicates, and does reverse the
* list order, but no one cares anyway.
*/
static struct nvlist *
addtoattr(l, dev)
register struct nvlist *l;
register struct devbase *dev;
{
register struct nvlist *n;
n = newnv(NULL, NULL, dev, 0);
n->nv_next = l;
return (n);
}
/*
* Device a device, giving its allowable parent attachments, if any.
* This may (or may not) also define an interface attribute and/or refer
* to existing attributes. There may be a list of vectors.
*/
void
defdev(dev, ispseudo, atlist, vectors, loclist, attrs)
register struct devbase *dev;
int ispseudo;
struct nvlist *atlist, *vectors, *loclist, *attrs;
{
register struct nvlist *nv;
register struct attr *a;
if (dev == &errdev)
goto bad;
if (dev->d_isdef) {
error("redefinition of `%s'", dev->d_name);
goto bad;
}
dev->d_isdef = 1;
if (has_errobj(attrs, &errattr))
goto bad;
/*
* Handle implicit attribute definition from locator list. Do
* this before scanning the `at' list so that we can have, e.g.:
* device foo at other, foo { slot = -1 }
* (where you can plug in a foo-bus extender to a foo-bus).
*/
if (loclist != NULL) {
nv = loclist;
loclist = NULL; /* defattr disposes of them for us */
if (defattr(dev->d_name, nv))
goto bad;
nv = newnv(dev->d_name, NULL, getattr(dev->d_name), 0);
nv->nv_next = attrs;
attrs = nv;
}
/* Committed! Set up fields. */
dev->d_ispseudo = ispseudo;
dev->d_atlist = atlist;
dev->d_vectors = vectors;
dev->d_attrs = attrs;
/*
* Turn the `at' list into interface attributes (map each
* nv_name to an attribute, or to NULL for root), and add
* this device to those attributes, so that children can
* be listed at this particular device if they are supported
* by that attribute.
*/
for (nv = atlist; nv != NULL; nv = nv->nv_next) {
if (nv->nv_name == NULL) {
nv->nv_ptr = NULL; /* at root */
continue;
}
nv->nv_ptr = a = getattr(nv->nv_name);
if (a == &errattr)
continue; /* already complained */
if (!a->a_iattr)
error("%s cannot be at plain attribute `%s'",
dev->d_name, a->a_name);
else
a->a_devs = addtoattr(a->a_devs, dev);
}
/*
* For each interface attribute this device refers to, add this
* device to its reference list. This makes, e.g., finding all
* "scsi"s easier.
*/
for (nv = attrs; nv != NULL; nv = nv->nv_next) {
a = nv->nv_ptr;
if (a->a_iattr)
a->a_refs = addtoattr(a->a_refs, dev);
}
return;
bad:
nvfreel(atlist);
nvfreel(vectors);
nvfreel(loclist);
nvfreel(attrs);
}
/*
* Look up a devbase. Also makes sure it is a reasonable name,
* i.e., does not end in a digit or contain special characters.
*/
struct devbase *
getdevbase(name)
const char *name;
{
register u_char *p;
register struct devbase *dev;
p = (u_char *)name;
if (!isalpha(*p))
goto badname;
while (*++p) {
if (!isalnum(*p) && *p != '_')
goto badname;
}
if (isdigit(*--p)) {
badname:
error("bad device base name `%s'", name);
return (&errdev);
}
dev = ht_lookup(devbasetab, name);
if (dev == NULL) {
dev = emalloc(sizeof *dev);
dev->d_name = name;
dev->d_next = NULL;
dev->d_isdef = 0;
dev->d_major = NODEV;
dev->d_atlist = NULL;
dev->d_vectors = NULL;
dev->d_attrs = NULL;
dev->d_ihead = NULL;
dev->d_ipp = &dev->d_ihead;
dev->d_umax = 0;
*nextbase = dev;
nextbase = &dev->d_next;
if (ht_insert(devbasetab, name, dev))
panic("getdevbase(%s)", name);
}
return (dev);
}
/*
* Look up an attribute.
*/
struct attr *
getattr(name)
const char *name;
{
struct attr *a;
if ((a = ht_lookup(attrtab, name)) == NULL) {
error("undefined attribute `%s'", name);
a = &errattr;
}
return (a);
}
/*
* Set the major device number for a device, so that it can be used
* as a root/swap/dumps "on" device in a configuration.
*/
void
setmajor(d, n)
struct devbase *d;
int n;
{
if (d != &errdev && d->d_major != NODEV)
error("device `%s' is already major %d",
d->d_name, d->d_major);
else
d->d_major = n;
}
#define ABS(x) ((x) < 0 ? -(x) : (x))
static int
exclude(nv, name, what)
struct nvlist *nv;
const char *name, *what;
{
if (nv != NULL) {
error("%s: swap generic must not specify %s", name, what);
return (1);
}
return (0);
}
/*
* Map things like "ra0b" => makedev(major("ra"), 0*maxpartitions + 'b'-'a').
* Handle the case where the device number is given but there is no
* corresponding name, and map NULL to the default.
*/
static int
resolve(nvp, name, what, dflt, part)
register struct nvlist **nvp;
const char *name, *what;
struct nvlist *dflt;
register int part;
{
register struct nvlist *nv;
register struct devbase *dev;
register const char *cp;
register int maj, min, l;
int unit;
char buf[NAMESIZE];
if ((u_int)(part -= 'a') >= maxpartitions)
panic("resolve");
if ((nv = *nvp) == NULL) {
dev_t d = NODEV;
/*
* Apply default. Easiest to do this by number.
* Make sure to retain NODEVness, if this is dflt's disposition.
*/
if (dflt->nv_int != NODEV) {
maj = major(dflt->nv_int);
min = (minor(dflt->nv_int) / maxpartitions) + part;
d = makedev(maj, min);
}
*nvp = nv = newnv(NULL, NULL, NULL, d);
}
if (nv->nv_int != NODEV) {
/*
* By the numbers. Find the appropriate major number
* to make a name.
*/
maj = major(nv->nv_int);
min = minor(nv->nv_int);
for (dev = allbases; dev != NULL; dev = dev->d_next)
if (dev->d_major == maj)
break;
if (dev == NULL)
(void)sprintf(buf, "<%d/%d>", maj, min);
else
(void)sprintf(buf, "%s%d%c", dev->d_name,
min / maxpartitions, (min % maxpartitions) + 'a');
nv->nv_str = intern(buf);
return (0);
}
if (nv->nv_str == NULL || nv->nv_str == s_nfs)
/*
* NFS spec. Leave as NODEV.
*/
return (0);
/*
* The normal case: things like "ra2b". Check for partition
* suffix, remove it if there, and split into name ("ra") and
* unit (2).
*/
l = strlen(nv->nv_str);
cp = &nv->nv_str[l];
if (l > 1 && *--cp >= 'a' && *cp <= 'a'+maxpartitions &&
isdigit(cp[-1])) {
l--;
part = *cp - 'a';
}
cp = nv->nv_str;
if (split(cp, l, buf, sizeof buf, &unit)) {
error("%s: invalid %s device name `%s'", name, what, cp);
return (1);
}
dev = ht_lookup(devbasetab, intern(buf));
if (dev == NULL || dev->d_major == NODEV) {
error("%s: can't make %s device from `%s'",
name, what, nv->nv_str);
return (1);
}
nv->nv_name = dev->d_name;
nv->nv_int = makedev(dev->d_major, unit * maxpartitions + part);
return (0);
}
static int
lresolve(nvp, name, what, dflt, part)
register struct nvlist **nvp;
const char *name, *what;
struct nvlist *dflt;
int part;
{
int err;
while ((err = resolve(nvp, name, what, dflt, part)) == 0 &&
(*nvp)->nv_next != NULL)
nvp = &(*nvp)->nv_next;
return (err);
}
/*
* Add a completed configuration to the list.
*/
void
addconf(cf0)
register struct config *cf0;
{
register struct config *cf;
register struct nvlist *nv;
const char *name;
name = cf0->cf_name;
cf = emalloc(sizeof *cf);
if (ht_insert(cfhashtab, name, cf)) {
error("configuration `%s' already defined", name);
free(cf);
goto bad;
}
*cf = *cf0;
/*
* Look for "swap generic".
*/
for (nv = cf->cf_swap; nv != NULL; nv = nv->nv_next)
if (nv->nv_str == s_generic)
break;
if (nv != NULL) {
/*
* Make sure no root or dump device specified, and no
* other swap devices. Note single | here (check all).
*/
nv = cf->cf_swap;
if (exclude(cf->cf_root, name, "root device") |
exclude(nv->nv_next, name, "additional swap devices") |
exclude(cf->cf_dump, name, "dump device"))
goto bad;
} else {
nv = cf->cf_root;
if (nv == NULL) {
error("%s: no root device specified", name);
goto bad;
}
if (resolve(&cf->cf_root, name, "root", nv, 'a') |
lresolve(&cf->cf_swap, name, "swap", nv, 'b') |
resolve(&cf->cf_dump, name, "dumps", nv, 'b'))
goto bad;
}
*nextcf = cf;
nextcf = &cf->cf_next;
return;
bad:
nvfreel(cf0->cf_root);
nvfreel(cf0->cf_swap);
nvfreel(cf0->cf_dump);
}
void
setconf(npp, what, v)
register struct nvlist **npp;
const char *what;
struct nvlist *v;
{
if (*npp != NULL) {
error("duplicate %s specification", what);
nvfreel(v);
} else
*npp = v;
}
static struct devi *
newdevi(name, unit, d)
const char *name;
int unit;
struct devbase *d;
{
register struct devi *i;
i = emalloc(sizeof *i);
i->i_name = name;
i->i_unit = unit;
i->i_base = d;
i->i_next = NULL;
i->i_bsame = NULL;
i->i_alias = NULL;
i->i_at = NULL;
i->i_atattr = NULL;
i->i_atdev = NULL;
i->i_locs = NULL;
i->i_cfflags = 0;
i->i_lineno = currentline();
if (unit >= d->d_umax)
d->d_umax = unit + 1;
return (i);
}
/*
* Add the named device as attaching to the named attribute (or perhaps
* another device instead) plus unit number.
*/
void
adddev(name, at, loclist, flags)
const char *name, *at;
struct nvlist *loclist;
int flags;
{
register struct devi *i; /* the new instance */
register struct attr *attr; /* attribute that allows attach */
register struct devbase *ib; /* i->i_base */
register struct devbase *ab; /* not NULL => at another dev */
register struct nvlist *nv;
const char *cp;
int atunit;
char atbuf[NAMESIZE];
ab = NULL;
if (at == NULL) {
/* "at root" */
if ((i = getdevi(name)) == NULL)
goto bad;
/*
* Must warn about i_unit > 0 later, after taking care of
* the STAR cases (we could do non-star's here but why
* bother?). Make sure this device can be at root.
*/
ib = i->i_base;
if (!onlist(ib->d_atlist, NULL)) {
error("%s's cannot attach to the root", ib->d_name);
goto bad;
}
attr = &errattr; /* a convenient "empty" attr */
} else {
if (split(at, strlen(at), atbuf, sizeof atbuf, &atunit)) {
error("invalid attachment name `%s'", at);
/* (void)getdevi(name); -- ??? */
goto bad;
}
if ((i = getdevi(name)) == NULL)
goto bad;
ib = i->i_base;
cp = intern(atbuf);
if ((attr = ht_lookup(attrtab, cp)) == NULL) {
/*
* Have to work a bit harder to see whether we have
* something like "tg0 at esp0" (where esp is merely
* not an attribute) or "tg0 at nonesuch0" (where
* nonesuch is not even a device).
*/
if ((ab = ht_lookup(devbasetab, cp)) == NULL) {
error("%s at %s: `%s' unknown",
name, at, atbuf);
goto bad;
}
/*
* See if the named parent carries an attribute
* that allows it to supervise device ib.
*/
for (nv = ab->d_attrs; nv != NULL; nv = nv->nv_next) {
attr = nv->nv_ptr;
if (onlist(attr->a_devs, ib))
goto ok;
}
attr = &errattr;/* now onlist below will fail */
}
if (!onlist(attr->a_devs, ib)) {
error("%s's cannot attach to %s's", ib->d_name, atbuf);
goto bad;
}
}
ok:
if ((i->i_locs = fixloc(name, attr, loclist)) == NULL)
goto bad;
if (i->i_unit == STAR && ib->d_vectors != NULL) {
error("%s's cannot be *'d as they have preset vectors",
ib->d_name);
goto bad;
}
i->i_at = at;
i->i_atattr = attr;
i->i_atdev = ab;
i->i_atunit = atunit;
i->i_cfflags = flags;
selectbase(ib);
/* all done, fall into ... */
bad:
nvfreel(loclist);
return;
}
void
addpseudo(name, number)
const char *name;
int number;
{
register struct devbase *d;
register struct devi *i;
d = ht_lookup(devbasetab, name);
if (d == NULL) {
error("undefined pseudo-device %s", name);
return;
}
if (!d->d_ispseudo) {
error("%s is a real device, not a pseudo-device", name);
return;
}
if (ht_lookup(devitab, name) != NULL) {
error("`%s' already defined", name);
return;
}
i = newdevi(name, number - 1, d); /* foo 16 => "foo0..foo15" */
if (ht_insert(devitab, name, i))
panic("addpseudo(%s)", name);
selectbase(d);
*nextpseudo = i;
nextpseudo = &i->i_next;
npseudo++;
}
/*
* Define a new instance of a specific device.
*/
static struct devi *
getdevi(name)
const char *name;
{
register struct devi *i, *firsti;
register struct devbase *d;
int unit;
char base[NAMESIZE];
if (split(name, strlen(name), base, sizeof base, &unit)) {
error("invalid device name `%s'", name);
return (NULL);
}
d = ht_lookup(devbasetab, intern(base));
if (d == NULL) {
error("%s: unknown device `%s'", name, base);
return (NULL);
}
if (d->d_ispseudo) {
error("%s: %s is a pseudo-device", name, base);
return (NULL);
}
firsti = ht_lookup(devitab, name);
i = newdevi(name, unit, d);
if (firsti == NULL) {
if (ht_insert(devitab, name, i))
panic("getdevi(%s)", name);
*d->d_ipp = i;
d->d_ipp = &i->i_bsame;
} else {
while (firsti->i_alias)
firsti = firsti->i_alias;
firsti->i_alias = i;
}
*nextdevi = i;
nextdevi = &i->i_next;
ndevi++;
return (i);
}
static const char *
concat(name, c)
const char *name;
int c;
{
register int len;
char buf[NAMESIZE];
len = strlen(name);
if (len + 2 > sizeof(buf)) {
error("device name `%s%c' too long", name, c);
len = sizeof(buf) - 2;
}
bcopy(name, buf, len);
buf[len] = c;
buf[len + 1] = 0;
return (intern(buf));
}
const char *
starref(name)
const char *name;
{
return (concat(name, '*'));
}
const char *
wildref(name)
const char *name;
{
return (concat(name, '?'));
}
/*
* Split a name like "foo0" into base name (foo) and unit number (0).
* Return 0 on success. To make this useful for names like "foo0a",
* the length of the "foo0" part is one of the arguments.
*/
static int
split(name, nlen, base, bsize, aunit)
register const char *name;
size_t nlen;
char *base;
size_t bsize;
int *aunit;
{
register const char *cp;
register int c, l;
l = nlen;
if (l < 2 || l >= bsize || isdigit(*name))
return (1);
c = (u_char)name[--l];
if (!isdigit(c)) {
if (c == '*')
*aunit = STAR;
else if (c == '?')
*aunit = WILD;
else
return (1);
} else {
cp = &name[l];
while (isdigit(cp[-1]))
l--, cp--;
*aunit = atoi(cp);
}
bcopy(name, base, l);
base[l] = 0;
return (0);
}
/*
* We have an instance of the base foo, so select it and all its
* attributes for "optional foo".
*/
static void
selectbase(d)
register struct devbase *d;
{
register struct attr *a;
register struct nvlist *nv;
(void)ht_insert(selecttab, d->d_name, (char *)d->d_name);
for (nv = d->d_attrs; nv != NULL; nv = nv->nv_next) {
a = nv->nv_ptr;
(void)ht_insert(selecttab, a->a_name, (char *)a->a_name);
}
}
/*
* Is the given pointer on the given list of pointers?
*/
static int
onlist(nv, ptr)
register struct nvlist *nv;
register void *ptr;
{
for (; nv != NULL; nv = nv->nv_next)
if (nv->nv_ptr == ptr)
return (1);
return (0);
}
static char *
extend(p, name)
register char *p;
const char *name;
{
register int l;
l = strlen(name);
bcopy(name, p, l);
p += l;
*p++ = ',';
*p++ = ' ';
return (p);
}
/*
* Check that we got all required locators, and default any that are
* given as "?" and have defaults. Return 0 on success.
*/
static const char **
fixloc(name, attr, got)
const char *name;
register struct attr *attr;
register struct nvlist *got;
{
register struct nvlist *m, *n;
register int ord;
register const char **lp;
int nmissing, nextra, nnodefault;
char *mp, *ep, *ndp;
char missing[1000], extra[1000], nodefault[1000];
static const char *nullvec[1];
/*
* Look for all required locators, and number the given ones
* according to the required order. While we are numbering,
* set default values for defaulted locators.
*/
if (attr->a_loclen == 0) /* e.g., "at root" */
lp = nullvec;
else
lp = emalloc((attr->a_loclen + 1) * sizeof(const char *));
for (n = got; n != NULL; n = n->nv_next)
n->nv_int = -1;
nmissing = 0;
mp = missing;
/* yes, this is O(mn), but m and n should be small */
for (ord = 0, m = attr->a_locs; m != NULL; m = m->nv_next, ord++) {
for (n = got; n != NULL; n = n->nv_next) {
if (n->nv_name == m->nv_name) {
n->nv_int = ord;
break;
}
}
if (n == NULL && m->nv_int == 0) {
nmissing++;
mp = extend(mp, m->nv_name);
}
lp[ord] = m->nv_str;
}
if (ord != attr->a_loclen)
panic("fixloc");
lp[ord] = NULL;
nextra = 0;
ep = extra;
nnodefault = 0;
ndp = nodefault;
for (n = got; n != NULL; n = n->nv_next) {
if (n->nv_int >= 0) {
if (n->nv_str != NULL)
lp[n->nv_int] = n->nv_str;
else if (lp[n->nv_int] == NULL) {
nnodefault++;
ndp = extend(ndp, n->nv_name);
}
} else {
nextra++;
ep = extend(ep, n->nv_name);
}
}
if (nextra) {
ep[-2] = 0; /* kill ", " */
error("%s: extraneous locator%s: %s",
name, nextra > 1 ? "s" : "", extra);
}
if (nmissing) {
mp[-2] = 0;
error("%s: must specify %s", name, missing);
}
if (nnodefault) {
ndp[-2] = 0;
error("%s: cannot wildcard %s", name, nodefault);
}
if (nmissing || nnodefault) {
free(lp);
lp = NULL;
}
return (lp);
}

View File

@ -1,65 +0,0 @@
/*
* 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. 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, Berkeley and its contributors.
* 4. 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: @(#)sem.h 8.1 (Berkeley) 6/6/93
* $Id: sem.h,v 1.4 1994/06/22 10:44:26 pk Exp $
*/
void enddefs __P((const char *));
void setdefmaxusers __P((int, int, int));
void setmaxusers __P((int));
int defattr __P((const char *, struct nvlist *));
void defdev __P((struct devbase *, int, struct nvlist *,
struct nvlist *, struct nvlist *, struct nvlist *));
struct devbase *getdevbase __P((const char *name));
struct attr *getattr __P((const char *name));
void setmajor __P((struct devbase *d, int n));
void addconf __P((struct config *));
void setconf __P((struct nvlist **, const char *, struct nvlist *));
void adddev __P((const char *, const char *, struct nvlist *, int));
void addpseudo __P((const char *name, int number));
const char *ref __P((const char *name));
const char *starref __P((const char *name));
const char *wildref __P((const char *name));
extern const char *s_generic;
extern const char *s_nfs;

View File

@ -1,265 +0,0 @@
/*
* 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. 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, Berkeley and its contributors.
* 4. 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: @(#)util.c 8.1 (Berkeley) 6/6/93
* $Id: util.c,v 1.7 1994/12/23 16:25:45 cgd Exp $
*/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#include <sys/types.h>
#include "config.h"
static void nomem __P((void));
static void vxerror __P((const char *, int, const char *, va_list));
/*
* Malloc, with abort on error.
*/
void *
emalloc(size)
size_t size;
{
void *p;
if ((p = malloc(size)) == NULL)
nomem();
return (p);
}
/*
* Realloc, with abort on error.
*/
void *
erealloc(p, size)
void *p;
size_t size;
{
if ((p = realloc(p, size)) == NULL)
nomem();
return (p);
}
static void
nomem()
{
(void)fprintf(stderr, "config: out of memory\n");
exit(1);
}
/*
* Prepend the compilation directory to a file name.
*/
char *
path(file)
const char *file;
{
register char *cp;
#define CDIR "../compile/"
if (file == NULL) {
cp = emalloc(sizeof(CDIR) + strlen(confdirbase));
(void)sprintf(cp, "%s%s", CDIR, confdirbase);
} else {
cp = emalloc(sizeof(CDIR) + strlen(confdirbase) + 1 +
strlen(file));
(void)sprintf(cp, "%s%s/%s", CDIR, confdirbase, file);
}
return (cp);
}
static struct nvlist *nvhead;
struct nvlist *
newnv(name, str, ptr, i)
const char *name, *str;
void *ptr;
int i;
{
register struct nvlist *nv;
if ((nv = nvhead) == NULL)
nv = emalloc(sizeof(*nv));
else
nvhead = nv->nv_next;
nv->nv_next = NULL;
nv->nv_name = name;
if (ptr == NULL)
nv->nv_str = str;
else {
if (str != NULL)
panic("newnv");
nv->nv_ptr = ptr;
}
nv->nv_int = i;
return (nv);
}
/*
* Free an nvlist structure (just one).
*/
void
nvfree(nv)
register struct nvlist *nv;
{
nv->nv_next = nvhead;
nvhead = nv;
}
/*
* Free an nvlist (the whole list).
*/
void
nvfreel(nv)
register struct nvlist *nv;
{
register struct nvlist *next;
for (; nv != NULL; nv = next) {
next = nv->nv_next;
nv->nv_next = nvhead;
nvhead = nv;
}
}
/*
* External (config file) error. Complain, using current file
* and line number.
*/
void
#if __STDC__
error(const char *fmt, ...)
#else
error(fmt, va_alist)
const char *fmt;
va_dcl
#endif
{
va_list ap;
extern const char *yyfile;
#if __STDC__
va_start(ap, fmt);
#else
va_start(ap);
#endif
vxerror(yyfile, currentline(), fmt, ap);
va_end(ap);
}
/*
* Delayed config file error (i.e., something was wrong but we could not
* find out about it until later).
*/
void
#if __STDC__
xerror(const char *file, int line, const char *fmt, ...)
#else
xerror(file, line, fmt, va_alist)
const char *file;
int line;
const char *fmt;
va_dcl
#endif
{
va_list ap;
#if __STDC__
va_start(ap, fmt);
#else
va_start(ap);
#endif
vxerror(file, line, fmt, ap);
va_end(ap);
}
/*
* Internal form of error() and xerror().
*/
static void
vxerror(file, line, fmt, ap)
const char *file;
int line;
const char *fmt;
va_list ap;
{
(void)fprintf(stderr, "%s:%d: ", file, line);
(void)vfprintf(stderr, fmt, ap);
(void)putc('\n', stderr);
errors++;
}
/*
* Internal error, abort.
*/
__dead void
#if __STDC__
panic(const char *fmt, ...)
#else
panic(fmt, va_alist)
const char *fmt;
va_dcl
#endif
{
va_list ap;
#if __STDC__
va_start(ap, fmt);
#else
va_start(ap);
#endif
(void)fprintf(stderr, "config: panic: ");
(void)vfprintf(stderr, fmt, ap);
(void)putc('\n', stderr);
va_end(ap);
exit(2);
}