diff options
author | rgrimes <rgrimes@FreeBSD.org> | 1994-05-26 05:23:31 +0000 |
---|---|---|
committer | rgrimes <rgrimes@FreeBSD.org> | 1994-05-26 05:23:31 +0000 |
commit | 862fdf11a2ede45dec0da01ed575525d79468981 (patch) | |
tree | 7a1c88ccb8006476bd4b4a548a6ad48fbfc33a01 /usr.sbin/config.new | |
parent | 8e1a19ddde0df113b0b26b0ea621afd61dbaf91f (diff) | |
download | FreeBSD-src-862fdf11a2ede45dec0da01ed575525d79468981.zip FreeBSD-src-862fdf11a2ede45dec0da01ed575525d79468981.tar.gz |
BSD 4.4 Lite usr.sbin Sources
Diffstat (limited to 'usr.sbin/config.new')
-rw-r--r-- | usr.sbin/config.new/Makefile | 14 | ||||
-rw-r--r-- | usr.sbin/config.new/config.h | 281 | ||||
-rw-r--r-- | usr.sbin/config.new/config.new.8 | 167 | ||||
-rw-r--r-- | usr.sbin/config.new/files.c | 262 | ||||
-rw-r--r-- | usr.sbin/config.new/gram.y | 392 | ||||
-rw-r--r-- | usr.sbin/config.new/hash.c | 279 | ||||
-rw-r--r-- | usr.sbin/config.new/main.c | 466 | ||||
-rw-r--r-- | usr.sbin/config.new/mkheaders.c | 148 | ||||
-rw-r--r-- | usr.sbin/config.new/mkioconf.c | 395 | ||||
-rw-r--r-- | usr.sbin/config.new/mkmakefile.c | 364 | ||||
-rw-r--r-- | usr.sbin/config.new/mkswap.c | 118 | ||||
-rw-r--r-- | usr.sbin/config.new/pack.c | 520 | ||||
-rw-r--r-- | usr.sbin/config.new/scan.l | 238 | ||||
-rw-r--r-- | usr.sbin/config.new/sem.c | 974 | ||||
-rw-r--r-- | usr.sbin/config.new/sem.h | 61 | ||||
-rw-r--r-- | usr.sbin/config.new/util.c | 262 |
16 files changed, 4941 insertions, 0 deletions
diff --git a/usr.sbin/config.new/Makefile b/usr.sbin/config.new/Makefile new file mode 100644 index 0000000..6dc5a7e --- /dev/null +++ b/usr.sbin/config.new/Makefile @@ -0,0 +1,14 @@ +# @(#)Makefile 8.2 (Berkeley) 4/19/94 + +PROG= config +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. +CLEANFILES=gram.c scan.c y.tab.h +MAN8= config.new.0 + +MLINKS+=config.new.0 config.0 + +.include <bsd.prog.mk> + +.depend: gram.c scan.c diff --git a/usr.sbin/config.new/config.h b/usr.sbin/config.new/config.h new file mode 100644 index 0000000..dde683d --- /dev/null +++ b/usr.sbin/config.new/config.h @@ -0,0 +1,281 @@ +/* + * 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. + * + * @(#)config.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * 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" */ +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 */ +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 *)); diff --git a/usr.sbin/config.new/config.new.8 b/usr.sbin/config.new/config.new.8 new file mode 100644 index 0000000..5eae8d3 --- /dev/null +++ b/usr.sbin/config.new/config.new.8 @@ -0,0 +1,167 @@ +.\" 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. +.\" +.\" @(#)config.8 8.2 (Berkeley) 4/19/94 +.\" +.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 +.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 +builds a set of configuration files from the file +.Ar system-name , +which describes +the system to configure. +.Pp +.Nm Config +should run from the +.Pa conf +subdirectory of the top-level machine-specific directory +of the system source (usually +.Pa /sys/MACHINE/conf , +where +.Pa MACHINE +is one of +.Pa vax , +.Pa tahoe , +.Pa hp300 , +and so forth). +.Nm Config +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 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 +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 +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 , +it is wise to run +.Dq Li make depend +in the directory where the new makefile +was created. +.Nm Config +prints a reminder of this when it completes. +.Pp +If +.Nm config +stops due to errors, the problems reported should be corrected and +.Nm config +should be run again. +.Nm Config +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 +command appeared in +.Bx 4.1 . +It was completely revised in +.Bx 4.4 . diff --git a/usr.sbin/config.new/files.c b/usr.sbin/config.new/files.c new file mode 100644 index 0000000..40cddf8 --- /dev/null +++ b/usr.sbin/config.new/files.c @@ -0,0 +1,262 @@ +/* + * 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. + * + * @(#)files.c 8.1 (Berkeley) 6/6/93 + */ + +#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); +} diff --git a/usr.sbin/config.new/gram.y b/usr.sbin/config.new/gram.y new file mode 100644 index 0000000..6b53801 --- /dev/null +++ b/usr.sbin/config.new/gram.y @@ -0,0 +1,392 @@ +%{ + +/* + * 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. + * + * @(#)gram.y 8.1 (Berkeley) 6/6/93 + */ + +#include <sys/param.h> +#include <ctype.h> +#include <stdio.h> +#include <stdlib.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 *)); + +%} + +%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 MINOR +%token 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 */ + specs; /* rest of machine description */ + +hdrs: + hdrs hdr | + /* empty */; + +hdr: + include | + '\n'; + +machine_spec: + XMACHINE WORD = { setmachine($2); } | + error = { stop("cannot proceed without machine specifier"); }; + +dev_eof: + ENDFILE = { enddefs(lastfile); checkfiles(); }; + + + +/* + * 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) + const char *mch; +{ + char buf[MAXPATHLEN]; + + machine = mch; + (void)sprintf(buf, "files.%s", mch); + if (include(buf, ENDFILE) || + include("../../conf/files.newconf", ENDFILE)) + exit(1); +} diff --git a/usr.sbin/config.new/hash.c b/usr.sbin/config.new/hash.c new file mode 100644 index 0000000..d7617da --- /dev/null +++ b/usr.sbin/config.new/hash.c @@ -0,0 +1,279 @@ +/* + * 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. + * + * @(#)hash.c 8.1 (Berkeley) 6/6/93 + */ + +#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); +} diff --git a/usr.sbin/config.new/main.c b/usr.sbin/config.new/main.c new file mode 100644 index 0000000..50b930e --- /dev/null +++ b/usr.sbin/config.new/main.c @@ -0,0 +1,466 @@ +/* + * 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. + * + * @(#)main.c 8.1 (Berkeley) 6/6/93 + */ + +#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. + */ +static int +mksymlinks() +{ + int ret; + char *p, buf[200]; + + p = path("machine"); + (void)sprintf(buf, "../../%s/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); + 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; + 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) >> 3)) + continue; + (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++; + } + 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); +} diff --git a/usr.sbin/config.new/mkheaders.c b/usr.sbin/config.new/mkheaders.c new file mode 100644 index 0000000..f627243 --- /dev/null +++ b/usr.sbin/config.new/mkheaders.c @@ -0,0 +1,148 @@ +/* + * 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. + * + * @(#)mkheaders.c 8.1 (Berkeley) 6/6/93 + */ + +#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); +} diff --git a/usr.sbin/config.new/mkioconf.c b/usr.sbin/config.new/mkioconf.c new file mode 100644 index 0000000..8b1ebe0 --- /dev/null +++ b/usr.sbin/config.new/mkioconf.c @@ -0,0 +1,395 @@ +/* + * 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. + * + * @(#)mkioconf.c 8.1 (Berkeley) 6/6/93 + */ + +#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); +} diff --git a/usr.sbin/config.new/mkmakefile.c b/usr.sbin/config.new/mkmakefile.c new file mode 100644 index 0000000..06971a5 --- /dev/null +++ b/usr.sbin/config.new/mkmakefile.c @@ -0,0 +1,364 @@ +/* + * 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. + * + * @(#)mkmakefile.c 8.1 (Berkeley) 6/6/93 + */ + +#include <sys/param.h> +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "config.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%s%s", sp, nv->nv_name, + nv->nv_str ? "=" : "", nv->nv_str ? 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/%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/%s/%s/swapgeneric.c\n", + machine, machine) < 0) + return (1); + } + if (fputs("\t${NORMAL_C}\n\n", fp) < 0) + return (1); + } + return (0); +} diff --git a/usr.sbin/config.new/mkswap.c b/usr.sbin/config.new/mkswap.c new file mode 100644 index 0000000..afea210 --- /dev/null +++ b/usr.sbin/config.new/mkswap.c @@ -0,0 +1,118 @@ +/* + * 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. + * + * @(#)mkswap.c 8.1 (Berkeley) 6/6/93 + */ + +#include <sys/param.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "config.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 int +mkoneswap(cf) + register struct config *cf; +{ + register struct nvlist *nv; + register FILE *fp; + register char *fname; + char buf[200]; + + (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 = makedev(%d, %d);\t/* %s */\n", + major(nv->nv_int), minor(nv->nv_int), nv->nv_str) < 0) + goto wrerror; + nv = cf->cf_dump; + if (fprintf(fp, "dev_t\tdumpdev = makedev(%d, %d);\t/* %s */\n", + major(nv->nv_int), minor(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{ makedev(%d, %d),\t0,\t0 },\t/* %s */\n", + major(nv->nv_int), minor(nv->nv_int), nv->nv_str) < 0) + goto wrerror; + if (fputs("\t{ NODEV, 0, 0 }\n};\n", fp) < 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); +} diff --git a/usr.sbin/config.new/pack.c b/usr.sbin/config.new/pack.c new file mode 100644 index 0000000..8b525ec --- /dev/null +++ b/usr.sbin/config.new/pack.c @@ -0,0 +1,520 @@ +/* + * 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. + * + * @(#)pack.c 8.1 (Berkeley) 6/6/93 + */ + +#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) (((int)(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; + } +} diff --git a/usr.sbin/config.new/scan.l b/usr.sbin/config.new/scan.l new file mode 100644 index 0000000..b7301a3 --- /dev/null +++ b/usr.sbin/config.new/scan.l @@ -0,0 +1,238 @@ +%{ +/* + * 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. + * + * @(#)scan.l 8.1 (Berkeley) 6/6/93 + */ + +#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; } +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 = strtol(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')); +} diff --git a/usr.sbin/config.new/sem.c b/usr.sbin/config.new/sem.c new file mode 100644 index 0000000..aa60169 --- /dev/null +++ b/usr.sbin/config.new/sem.c @@ -0,0 +1,974 @@ +/* + * 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. + * + * @(#)sem.c 8.1 (Berkeley) 6/6/93 + */ + +#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 */ + +static const char *s_generic; +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_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*8 + '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') >= 7) + panic("resolve"); + if ((nv = *nvp) == NULL) { + /* + * Apply default. Easiest to do this by number. + */ + maj = major(dflt->nv_int); + min = (minor(dflt->nv_int) & ~7) | part; + *nvp = nv = newnv(NULL, NULL, NULL, makedev(maj, min)); + } + 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 >> 3, (min & 7) + 'a'); + nv->nv_str = intern(buf); + 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 <= 'h' && 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 * 8 + 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); +} diff --git a/usr.sbin/config.new/sem.h b/usr.sbin/config.new/sem.h new file mode 100644 index 0000000..14d6c2b --- /dev/null +++ b/usr.sbin/config.new/sem.h @@ -0,0 +1,61 @@ +/* + * 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. + * + * @(#)sem.h 8.1 (Berkeley) 6/6/93 + */ + +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)); diff --git a/usr.sbin/config.new/util.c b/usr.sbin/config.new/util.c new file mode 100644 index 0000000..6ef37db --- /dev/null +++ b/usr.sbin/config.new/util.c @@ -0,0 +1,262 @@ +/* + * 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. + * + * @(#)util.c 8.1 (Berkeley) 6/6/93 + */ + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#if __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif +#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); +} |