xref: /csrg-svn/usr.sbin/config.new/files.c (revision 57488)
1*57488Storek /*
2*57488Storek  * Copyright (c) 1992 The Regents of the University of California.
3*57488Storek  * All rights reserved.
4*57488Storek  *
5*57488Storek  * This software was developed by the Computer Systems Engineering group
6*57488Storek  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
7*57488Storek  * contributed to Berkeley.
8*57488Storek  *
9*57488Storek  * All advertising materials mentioning features or use of this software
10*57488Storek  * must display the following acknowledgement:
11*57488Storek  *	This product includes software developed by the University of
12*57488Storek  *	California, Lawrence Berkeley Laboratories.
13*57488Storek  *
14*57488Storek  * %sccs.include.redist.c%
15*57488Storek  *
16*57488Storek  *	@(#)files.c	5.1 (Berkeley) 01/12/93
17*57488Storek  *
18*57488Storek  * from: $Header: files.c,v 1.4 93/01/12 03:56:19 torek Exp $
19*57488Storek  */
20*57488Storek 
21*57488Storek #include <sys/param.h>
22*57488Storek #include <errno.h>
23*57488Storek #include <stdio.h>
24*57488Storek #include <stdlib.h>
25*57488Storek #include <string.h>
26*57488Storek #include "config.h"
27*57488Storek 
28*57488Storek extern const char *yyfile;
29*57488Storek 
30*57488Storek /*
31*57488Storek  * We check that each full path name is unique.  File base names
32*57488Storek  * should generally also be unique, e.g., having both a net/xx.c and
33*57488Storek  * a kern/xx.c (or, worse, a net/xx.c and a new/xx.c++) is probably
34*57488Storek  * wrong, but is permitted under some conditions.
35*57488Storek  */
36*57488Storek static struct hashtab *basetab;		/* file base names */
37*57488Storek static struct hashtab *pathtab;		/* full path names */
38*57488Storek 
39*57488Storek static struct files **nextfile;
40*57488Storek static struct files **unchecked;
41*57488Storek 
42*57488Storek void
43*57488Storek initfiles()
44*57488Storek {
45*57488Storek 
46*57488Storek 	basetab = ht_new();
47*57488Storek 	pathtab = ht_new();
48*57488Storek 	nextfile = &allfiles;
49*57488Storek 	unchecked = &allfiles;
50*57488Storek }
51*57488Storek 
52*57488Storek static void
53*57488Storek showprev(pref, fi)
54*57488Storek 	const char *pref;
55*57488Storek 	register struct files *fi;
56*57488Storek {
57*57488Storek 
58*57488Storek 	xerror(fi->fi_srcfile, fi->fi_srcline,
59*57488Storek 	    "%sfile %s ...", pref, fi->fi_path);
60*57488Storek 	errors--;
61*57488Storek }
62*57488Storek 
63*57488Storek void
64*57488Storek addfile(path, opts, flags, rule)
65*57488Storek 	const char *path;
66*57488Storek 	struct nvlist *opts;
67*57488Storek 	int flags;
68*57488Storek 	const char *rule;
69*57488Storek {
70*57488Storek 	struct files *fi;
71*57488Storek 	const char *base, *dotp, *tail;
72*57488Storek 	size_t baselen;
73*57488Storek 	int needc, needf;
74*57488Storek 	char buf[200];
75*57488Storek 
76*57488Storek 	/* check various errors */
77*57488Storek 	needc = flags & FI_NEEDSCOUNT;
78*57488Storek 	needf = flags & FI_NEEDSFLAG;
79*57488Storek 	if (needc && needf) {
80*57488Storek 		error("cannot mix needs-count and needs-flag");
81*57488Storek 		goto bad;
82*57488Storek 	}
83*57488Storek 	if (opts == NULL && (needc || needf)) {
84*57488Storek 		error("nothing to %s for %s", needc ? "count" : "flag", path);
85*57488Storek 		goto bad;
86*57488Storek 	}
87*57488Storek 	if ((fi = ht_lookup(pathtab, path)) != NULL) {
88*57488Storek 		showprev("", fi);
89*57488Storek 		error("file %s listed again", path);
90*57488Storek 		goto bad;
91*57488Storek 	}
92*57488Storek 
93*57488Storek 	/* find last part of pathname, and same without trailing suffix */
94*57488Storek 	tail = rindex(path, '/');
95*57488Storek 	if (tail == NULL)
96*57488Storek 		tail = path;
97*57488Storek 	else
98*57488Storek 		tail++;
99*57488Storek 	dotp = rindex(tail, '.');
100*57488Storek 	if (dotp == NULL || dotp[1] == 0 ||
101*57488Storek 	    (baselen = dotp - tail) >= sizeof(buf)) {
102*57488Storek 		error("invalid pathname `%s'", path);
103*57488Storek 		goto bad;
104*57488Storek 	}
105*57488Storek 
106*57488Storek 	/*
107*57488Storek 	 * Make a copy of the path without the .c/.s/whatever suffix.
108*57488Storek 	 * This must be unique per "files" file (e.g., a specific
109*57488Storek 	 * file can override a standard file, but no standard file
110*57488Storek 	 * can override another standard file).  This is not perfect
111*57488Storek 	 * but should catch any major errors.
112*57488Storek 	 */
113*57488Storek 	bcopy(tail, buf, baselen);
114*57488Storek 	buf[baselen] = 0;
115*57488Storek 	base = intern(buf);
116*57488Storek 	if ((fi = ht_lookup(basetab, base)) != NULL) {
117*57488Storek 		if (fi->fi_srcfile != yyfile) {
118*57488Storek 			showprev("note: ", fi);
119*57488Storek 			error("is overriden by %s", path);
120*57488Storek 			errors--;	/* take it away */
121*57488Storek 			fi->fi_flags |= FI_HIDDEN;
122*57488Storek 		} else {
123*57488Storek 			showprev("", fi);
124*57488Storek 			error("collides with %s (both make %s.o)",
125*57488Storek 			    path, base);
126*57488Storek 			goto bad;
127*57488Storek 		}
128*57488Storek 	}
129*57488Storek 
130*57488Storek 	/*
131*57488Storek 	 * Commit this file to memory.
132*57488Storek 	 */
133*57488Storek 	fi = emalloc(sizeof *fi);
134*57488Storek 	fi->fi_next = NULL;
135*57488Storek 	fi->fi_srcfile = yyfile;
136*57488Storek 	fi->fi_srcline = currentline();
137*57488Storek 	fi->fi_flags = flags;
138*57488Storek 	fi->fi_lastc = dotp[strlen(dotp) - 1];
139*57488Storek 	fi->fi_path = path;
140*57488Storek 	fi->fi_tail = tail;
141*57488Storek 	fi->fi_base = base;
142*57488Storek 	fi->fi_opt = opts;
143*57488Storek 	fi->fi_mkrule = rule;
144*57488Storek 	if (ht_insert(pathtab, path, fi))
145*57488Storek 		panic("addfile: ht_insert(%s)", path);
146*57488Storek 	(void)ht_replace(basetab, base, fi);
147*57488Storek 	*nextfile = fi;
148*57488Storek 	nextfile = &fi->fi_next;
149*57488Storek 	return;
150*57488Storek bad:
151*57488Storek 	nvfreel(opts);
152*57488Storek }
153*57488Storek 
154*57488Storek /*
155*57488Storek  * We have finished reading some "files" file, either ../../conf/files
156*57488Storek  * or ./files.$machine.  Make sure that everything that is flagged as
157*57488Storek  * needing a count is reasonable.  (This prevents ../../conf/files from
158*57488Storek  * depending on some machine-specific device.)
159*57488Storek  */
160*57488Storek void
161*57488Storek checkfiles()
162*57488Storek {
163*57488Storek 	register struct files *fi, *last;
164*57488Storek 	register struct nvlist *nv;
165*57488Storek 
166*57488Storek 	last = NULL;
167*57488Storek 	for (fi = *unchecked; fi != NULL; last = fi, fi = fi->fi_next) {
168*57488Storek 		if ((fi->fi_flags & FI_NEEDSCOUNT) == 0)
169*57488Storek 			continue;
170*57488Storek 		for (nv = fi->fi_opt; nv != NULL; nv = nv->nv_next)
171*57488Storek 			if (ht_lookup(devbasetab, nv->nv_name) == NULL) {
172*57488Storek 				xerror(fi->fi_srcfile, fi->fi_srcline,
173*57488Storek 				    "`%s' is not a countable device",
174*57488Storek 				    nv->nv_name);
175*57488Storek 				/* keep fixfiles() from complaining again */
176*57488Storek 				fi->fi_flags |= FI_HIDDEN;
177*57488Storek 			}
178*57488Storek 	}
179*57488Storek 	if (last != NULL)
180*57488Storek 		unchecked = &last->fi_next;
181*57488Storek }
182*57488Storek 
183*57488Storek /*
184*57488Storek  * We have finished reading everything.  Tack the files down: calculate
185*57488Storek  * selection and counts as needed.
186*57488Storek  */
187*57488Storek int
188*57488Storek fixfiles()
189*57488Storek {
190*57488Storek 	register struct files *fi;
191*57488Storek 	register struct nvlist *nv;
192*57488Storek 	register struct devbase *dev;
193*57488Storek 	int sel, err;
194*57488Storek 
195*57488Storek 	err = 0;
196*57488Storek 	for (fi = allfiles; fi != NULL; fi = fi->fi_next) {
197*57488Storek 		if (fi->fi_flags & FI_HIDDEN)
198*57488Storek 			continue;
199*57488Storek 		if ((nv = fi->fi_opt) == NULL) {	/* standard */
200*57488Storek 			fi->fi_flags |= FI_SEL;
201*57488Storek 			continue;
202*57488Storek 		}
203*57488Storek 		/* figure out whether it is selected */
204*57488Storek 		sel = 0;
205*57488Storek 		if (fi->fi_flags & FI_NEEDSCOUNT) {
206*57488Storek 			/* ... and compute counts too */
207*57488Storek 			do {
208*57488Storek 				dev = ht_lookup(devbasetab, nv->nv_name);
209*57488Storek 				if (dev == NULL) {
210*57488Storek 					xerror(fi->fi_srcfile, fi->fi_srcline,
211*57488Storek 					    "`%s' is not a countable device",
212*57488Storek 					    nv->nv_name);
213*57488Storek 					err = 1;
214*57488Storek 				} else {
215*57488Storek 					if (dev->d_umax)
216*57488Storek 						sel = 1;
217*57488Storek 					nv->nv_int = dev->d_umax;
218*57488Storek 					(void)ht_insert(needcnttab,
219*57488Storek 					    nv->nv_name, nv);
220*57488Storek 				}
221*57488Storek 			} while ((nv = nv->nv_next) != NULL);
222*57488Storek 		} else {
223*57488Storek 			do {
224*57488Storek 				if (ht_lookup(selecttab, nv->nv_name)) {
225*57488Storek 					sel = 1;
226*57488Storek 					break;
227*57488Storek 				}
228*57488Storek 			} while ((nv = nv->nv_next) != NULL);
229*57488Storek 			if (fi->fi_flags & FI_NEEDSFLAG)
230*57488Storek 				for (nv = fi->fi_opt; nv; nv = nv->nv_next)
231*57488Storek 					nv->nv_int = sel;
232*57488Storek 		}
233*57488Storek 		/* if selected, we are go */
234*57488Storek 		if (sel)
235*57488Storek 			fi->fi_flags |= FI_SEL;
236*57488Storek 	}
237*57488Storek 	return (err);
238*57488Storek }
239