xref: /csrg-svn/usr.sbin/config.new/files.c (revision 61818)
157488Storek /*
2*61818Sbostic  * Copyright (c) 1992, 1993
3*61818Sbostic  *	The Regents of the University of California.  All rights reserved.
457488Storek  *
557488Storek  * This software was developed by the Computer Systems Engineering group
657488Storek  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
757488Storek  * contributed to Berkeley.
857488Storek  *
957488Storek  * All advertising materials mentioning features or use of this software
1057488Storek  * must display the following acknowledgement:
1157488Storek  *	This product includes software developed by the University of
1257488Storek  *	California, Lawrence Berkeley Laboratories.
1357488Storek  *
1457488Storek  * %sccs.include.redist.c%
1557488Storek  *
16*61818Sbostic  *	@(#)files.c	8.1 (Berkeley) 06/06/93
1757488Storek  */
1857488Storek 
1957488Storek #include <sys/param.h>
2057488Storek #include <errno.h>
2157488Storek #include <stdio.h>
2257488Storek #include <stdlib.h>
2357488Storek #include <string.h>
2457488Storek #include "config.h"
2557488Storek 
2657488Storek extern const char *yyfile;
2757488Storek 
2857488Storek /*
2957488Storek  * We check that each full path name is unique.  File base names
3057488Storek  * should generally also be unique, e.g., having both a net/xx.c and
3157488Storek  * a kern/xx.c (or, worse, a net/xx.c and a new/xx.c++) is probably
3257488Storek  * wrong, but is permitted under some conditions.
3357488Storek  */
3457488Storek static struct hashtab *basetab;		/* file base names */
3557488Storek static struct hashtab *pathtab;		/* full path names */
3657488Storek 
3757488Storek static struct files **nextfile;
3857488Storek static struct files **unchecked;
3957488Storek 
4057488Storek void
initfiles()4157488Storek initfiles()
4257488Storek {
4357488Storek 
4457488Storek 	basetab = ht_new();
4557488Storek 	pathtab = ht_new();
4657488Storek 	nextfile = &allfiles;
4757488Storek 	unchecked = &allfiles;
4857488Storek }
4957488Storek 
5057488Storek static void
showprev(pref,fi)5157488Storek showprev(pref, fi)
5257488Storek 	const char *pref;
5357488Storek 	register struct files *fi;
5457488Storek {
5557488Storek 
5657488Storek 	xerror(fi->fi_srcfile, fi->fi_srcline,
5757488Storek 	    "%sfile %s ...", pref, fi->fi_path);
5857488Storek 	errors--;
5957488Storek }
6057488Storek 
6157488Storek void
addfile(path,opts,flags,rule)6257488Storek addfile(path, opts, flags, rule)
6357488Storek 	const char *path;
6457488Storek 	struct nvlist *opts;
6557488Storek 	int flags;
6657488Storek 	const char *rule;
6757488Storek {
6857488Storek 	struct files *fi;
6957488Storek 	const char *base, *dotp, *tail;
7057488Storek 	size_t baselen;
7157488Storek 	int needc, needf;
7257488Storek 	char buf[200];
7357488Storek 
7457488Storek 	/* check various errors */
7557488Storek 	needc = flags & FI_NEEDSCOUNT;
7657488Storek 	needf = flags & FI_NEEDSFLAG;
7757488Storek 	if (needc && needf) {
7857488Storek 		error("cannot mix needs-count and needs-flag");
7957488Storek 		goto bad;
8057488Storek 	}
8157488Storek 	if (opts == NULL && (needc || needf)) {
8257488Storek 		error("nothing to %s for %s", needc ? "count" : "flag", path);
8357488Storek 		goto bad;
8457488Storek 	}
8557488Storek 	if ((fi = ht_lookup(pathtab, path)) != NULL) {
8657488Storek 		showprev("", fi);
8757488Storek 		error("file %s listed again", path);
8857488Storek 		goto bad;
8957488Storek 	}
9057488Storek 
9157488Storek 	/* find last part of pathname, and same without trailing suffix */
9257488Storek 	tail = rindex(path, '/');
9357488Storek 	if (tail == NULL)
9457488Storek 		tail = path;
9557488Storek 	else
9657488Storek 		tail++;
9757488Storek 	dotp = rindex(tail, '.');
9857488Storek 	if (dotp == NULL || dotp[1] == 0 ||
9957488Storek 	    (baselen = dotp - tail) >= sizeof(buf)) {
10057488Storek 		error("invalid pathname `%s'", path);
10157488Storek 		goto bad;
10257488Storek 	}
10357488Storek 
10457488Storek 	/*
10557488Storek 	 * Make a copy of the path without the .c/.s/whatever suffix.
10657488Storek 	 * This must be unique per "files" file (e.g., a specific
10757488Storek 	 * file can override a standard file, but no standard file
10857488Storek 	 * can override another standard file).  This is not perfect
10957488Storek 	 * but should catch any major errors.
11057488Storek 	 */
11157488Storek 	bcopy(tail, buf, baselen);
11257488Storek 	buf[baselen] = 0;
11357488Storek 	base = intern(buf);
11457488Storek 	if ((fi = ht_lookup(basetab, base)) != NULL) {
11557488Storek 		if (fi->fi_srcfile != yyfile) {
11657488Storek 			showprev("note: ", fi);
11757488Storek 			error("is overriden by %s", path);
11857488Storek 			errors--;	/* take it away */
11957488Storek 			fi->fi_flags |= FI_HIDDEN;
12057488Storek 		} else {
12157488Storek 			showprev("", fi);
12257488Storek 			error("collides with %s (both make %s.o)",
12357488Storek 			    path, base);
12457488Storek 			goto bad;
12557488Storek 		}
12657488Storek 	}
12757488Storek 
12857488Storek 	/*
12957488Storek 	 * Commit this file to memory.
13057488Storek 	 */
13157488Storek 	fi = emalloc(sizeof *fi);
13257488Storek 	fi->fi_next = NULL;
13357488Storek 	fi->fi_srcfile = yyfile;
13457488Storek 	fi->fi_srcline = currentline();
13557488Storek 	fi->fi_flags = flags;
13657488Storek 	fi->fi_lastc = dotp[strlen(dotp) - 1];
13757488Storek 	fi->fi_path = path;
13857488Storek 	fi->fi_tail = tail;
13957488Storek 	fi->fi_base = base;
14057488Storek 	fi->fi_opt = opts;
14157488Storek 	fi->fi_mkrule = rule;
14257488Storek 	if (ht_insert(pathtab, path, fi))
14357488Storek 		panic("addfile: ht_insert(%s)", path);
14457488Storek 	(void)ht_replace(basetab, base, fi);
14557488Storek 	*nextfile = fi;
14657488Storek 	nextfile = &fi->fi_next;
14757488Storek 	return;
14857488Storek bad:
14957488Storek 	nvfreel(opts);
15057488Storek }
15157488Storek 
15257488Storek /*
15357488Storek  * We have finished reading some "files" file, either ../../conf/files
15457488Storek  * or ./files.$machine.  Make sure that everything that is flagged as
15557488Storek  * needing a count is reasonable.  (This prevents ../../conf/files from
15657488Storek  * depending on some machine-specific device.)
15757488Storek  */
15857488Storek void
checkfiles()15957488Storek checkfiles()
16057488Storek {
16157488Storek 	register struct files *fi, *last;
16257488Storek 	register struct nvlist *nv;
16357488Storek 
16457488Storek 	last = NULL;
16557488Storek 	for (fi = *unchecked; fi != NULL; last = fi, fi = fi->fi_next) {
16657488Storek 		if ((fi->fi_flags & FI_NEEDSCOUNT) == 0)
16757488Storek 			continue;
16857488Storek 		for (nv = fi->fi_opt; nv != NULL; nv = nv->nv_next)
16957488Storek 			if (ht_lookup(devbasetab, nv->nv_name) == NULL) {
17057488Storek 				xerror(fi->fi_srcfile, fi->fi_srcline,
17157488Storek 				    "`%s' is not a countable device",
17257488Storek 				    nv->nv_name);
17357488Storek 				/* keep fixfiles() from complaining again */
17457488Storek 				fi->fi_flags |= FI_HIDDEN;
17557488Storek 			}
17657488Storek 	}
17757488Storek 	if (last != NULL)
17857488Storek 		unchecked = &last->fi_next;
17957488Storek }
18057488Storek 
18157488Storek /*
18257488Storek  * We have finished reading everything.  Tack the files down: calculate
18357488Storek  * selection and counts as needed.
18457488Storek  */
18557488Storek int
fixfiles()18657488Storek fixfiles()
18757488Storek {
18857488Storek 	register struct files *fi;
18957488Storek 	register struct nvlist *nv;
19057488Storek 	register struct devbase *dev;
19157488Storek 	int sel, err;
19257488Storek 
19357488Storek 	err = 0;
19457488Storek 	for (fi = allfiles; fi != NULL; fi = fi->fi_next) {
19557488Storek 		if (fi->fi_flags & FI_HIDDEN)
19657488Storek 			continue;
19757488Storek 		if ((nv = fi->fi_opt) == NULL) {	/* standard */
19857488Storek 			fi->fi_flags |= FI_SEL;
19957488Storek 			continue;
20057488Storek 		}
20157488Storek 		/* figure out whether it is selected */
20257488Storek 		sel = 0;
20357488Storek 		if (fi->fi_flags & FI_NEEDSCOUNT) {
20457488Storek 			/* ... and compute counts too */
20557488Storek 			do {
20657488Storek 				dev = ht_lookup(devbasetab, nv->nv_name);
20757488Storek 				if (dev == NULL) {
20857488Storek 					xerror(fi->fi_srcfile, fi->fi_srcline,
20957488Storek 					    "`%s' is not a countable device",
21057488Storek 					    nv->nv_name);
21157488Storek 					err = 1;
21257488Storek 				} else {
21357488Storek 					if (dev->d_umax)
21457488Storek 						sel = 1;
21557488Storek 					nv->nv_int = dev->d_umax;
21657488Storek 					(void)ht_insert(needcnttab,
21757488Storek 					    nv->nv_name, nv);
21857488Storek 				}
21957488Storek 			} while ((nv = nv->nv_next) != NULL);
22057488Storek 		} else {
22157488Storek 			do {
22257488Storek 				if (ht_lookup(selecttab, nv->nv_name)) {
22357488Storek 					sel = 1;
22457488Storek 					break;
22557488Storek 				}
22657488Storek 			} while ((nv = nv->nv_next) != NULL);
22757488Storek 			if (fi->fi_flags & FI_NEEDSFLAG)
22857488Storek 				for (nv = fi->fi_opt; nv; nv = nv->nv_next)
22957488Storek 					nv->nv_int = sel;
23057488Storek 		}
23157488Storek 		/* if selected, we are go */
23257488Storek 		if (sel)
23357488Storek 			fi->fi_flags |= FI_SEL;
23457488Storek 	}
23557488Storek 	return (err);
23657488Storek }
237