moved into config.
This commit is contained in:
parent
d64248e551
commit
8aec5a0ab6
|
@ -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
|
|
@ -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 *));
|
|
@ -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 .
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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'));
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue