files.c revision 1.37.6.1 1 1.37.6.1 martin /* $NetBSD: files.c,v 1.37.6.1 2024/08/23 17:19:19 martin Exp $ */
2 1.1 thorpej
3 1.1 thorpej /*
4 1.1 thorpej * Copyright (c) 1992, 1993
5 1.1 thorpej * The Regents of the University of California. All rights reserved.
6 1.1 thorpej *
7 1.1 thorpej * This software was developed by the Computer Systems Engineering group
8 1.1 thorpej * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9 1.1 thorpej * contributed to Berkeley.
10 1.1 thorpej *
11 1.1 thorpej * All advertising materials mentioning features or use of this software
12 1.1 thorpej * must display the following acknowledgement:
13 1.1 thorpej * This product includes software developed by the University of
14 1.1 thorpej * California, Lawrence Berkeley Laboratories.
15 1.1 thorpej *
16 1.1 thorpej * Redistribution and use in source and binary forms, with or without
17 1.1 thorpej * modification, are permitted provided that the following conditions
18 1.1 thorpej * are met:
19 1.1 thorpej * 1. Redistributions of source code must retain the above copyright
20 1.1 thorpej * notice, this list of conditions and the following disclaimer.
21 1.1 thorpej * 2. Redistributions in binary form must reproduce the above copyright
22 1.1 thorpej * notice, this list of conditions and the following disclaimer in the
23 1.1 thorpej * documentation and/or other materials provided with the distribution.
24 1.1 thorpej * 3. Neither the name of the University nor the names of its contributors
25 1.1 thorpej * may be used to endorse or promote products derived from this software
26 1.1 thorpej * without specific prior written permission.
27 1.1 thorpej *
28 1.1 thorpej * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 1.1 thorpej * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 1.1 thorpej * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 1.1 thorpej * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 1.1 thorpej * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 1.1 thorpej * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 1.1 thorpej * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 1.1 thorpej * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 1.1 thorpej * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 1.1 thorpej * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 1.1 thorpej * SUCH DAMAGE.
39 1.1 thorpej *
40 1.1 thorpej * from: @(#)files.c 8.1 (Berkeley) 6/6/93
41 1.1 thorpej */
42 1.1 thorpej
43 1.1 thorpej #if HAVE_NBTOOL_CONFIG_H
44 1.1 thorpej #include "nbtool_config.h"
45 1.1 thorpej #endif
46 1.1 thorpej
47 1.17 christos #include <sys/cdefs.h>
48 1.37.6.1 martin __RCSID("$NetBSD: files.c,v 1.37.6.1 2024/08/23 17:19:19 martin Exp $");
49 1.17 christos
50 1.1 thorpej #include <sys/param.h>
51 1.34 uebayasi #include <assert.h>
52 1.1 thorpej #include <errno.h>
53 1.1 thorpej #include <stdio.h>
54 1.1 thorpej #include <stdlib.h>
55 1.1 thorpej #include <string.h>
56 1.3 christos #include <util.h>
57 1.1 thorpej #include "defs.h"
58 1.1 thorpej
59 1.1 thorpej extern const char *yyfile;
60 1.1 thorpej
61 1.33 uebayasi int nallfiles;
62 1.33 uebayasi size_t nselfiles;
63 1.33 uebayasi struct files **selfiles;
64 1.33 uebayasi
65 1.1 thorpej /*
66 1.1 thorpej * We check that each full path name is unique. File base names
67 1.1 thorpej * should generally also be unique, e.g., having both a net/xx.c and
68 1.1 thorpej * a kern/xx.c (or, worse, a net/xx.c and a new/xx.c++) is probably
69 1.1 thorpej * wrong, but is permitted under some conditions.
70 1.1 thorpej */
71 1.1 thorpej static struct hashtab *basetab; /* file base names */
72 1.1 thorpej static struct hashtab *pathtab; /* full path names */
73 1.1 thorpej
74 1.1 thorpej static struct files **unchecked;
75 1.1 thorpej
76 1.14 uebayasi static void addfiletoattr(const char *, struct files *);
77 1.1 thorpej static int checkaux(const char *, void *);
78 1.1 thorpej static int fixcount(const char *, void *);
79 1.1 thorpej static int fixfsel(const char *, void *);
80 1.1 thorpej static int fixsel(const char *, void *);
81 1.1 thorpej
82 1.1 thorpej void
83 1.1 thorpej initfiles(void)
84 1.1 thorpej {
85 1.1 thorpej
86 1.1 thorpej basetab = ht_new();
87 1.1 thorpej pathtab = ht_new();
88 1.1 thorpej TAILQ_INIT(&allfiles);
89 1.22 uebayasi TAILQ_INIT(&allcfiles);
90 1.22 uebayasi TAILQ_INIT(&allsfiles);
91 1.22 uebayasi TAILQ_INIT(&allofiles);
92 1.1 thorpej unchecked = &TAILQ_FIRST(&allfiles);
93 1.1 thorpej }
94 1.1 thorpej
95 1.1 thorpej void
96 1.21 uebayasi addfile(const char *path, struct condexpr *optx, u_char flags, const char *rule)
97 1.1 thorpej {
98 1.1 thorpej struct files *fi;
99 1.1 thorpej const char *dotp, *tail;
100 1.1 thorpej size_t baselen;
101 1.24 uebayasi size_t dirlen;
102 1.1 thorpej int needc, needf;
103 1.1 thorpej char base[200];
104 1.24 uebayasi char dir[MAXPATHLEN];
105 1.1 thorpej
106 1.1 thorpej /* check various errors */
107 1.1 thorpej needc = flags & FI_NEEDSCOUNT;
108 1.1 thorpej needf = flags & FI_NEEDSFLAG;
109 1.1 thorpej if (needc && needf) {
110 1.6 christos cfgerror("cannot mix needs-count and needs-flag");
111 1.1 thorpej goto bad;
112 1.1 thorpej }
113 1.1 thorpej if (optx == NULL && (needc || needf)) {
114 1.6 christos cfgerror("nothing to %s for %s", needc ? "count" : "flag",
115 1.6 christos path);
116 1.1 thorpej goto bad;
117 1.1 thorpej }
118 1.19 uebayasi if (*path == '/') {
119 1.19 uebayasi cfgerror("path must be relative");
120 1.19 uebayasi goto bad;
121 1.19 uebayasi }
122 1.1 thorpej
123 1.1 thorpej /* find last part of pathname, and same without trailing suffix */
124 1.1 thorpej tail = strrchr(path, '/');
125 1.24 uebayasi if (tail == NULL) {
126 1.24 uebayasi dirlen = 0;
127 1.1 thorpej tail = path;
128 1.24 uebayasi } else {
129 1.24 uebayasi dirlen = (size_t)(tail - path);
130 1.1 thorpej tail++;
131 1.24 uebayasi }
132 1.24 uebayasi memcpy(dir, path, dirlen);
133 1.24 uebayasi dir[dirlen] = '\0';
134 1.24 uebayasi
135 1.1 thorpej dotp = strrchr(tail, '.');
136 1.1 thorpej if (dotp == NULL || dotp[1] == 0 ||
137 1.17 christos (baselen = (size_t)(dotp - tail)) >= sizeof(base)) {
138 1.6 christos cfgerror("invalid pathname `%s'", path);
139 1.1 thorpej goto bad;
140 1.1 thorpej }
141 1.1 thorpej
142 1.1 thorpej /*
143 1.1 thorpej * Commit this file to memory. We will decide later whether it
144 1.1 thorpej * will be used after all.
145 1.1 thorpej */
146 1.1 thorpej fi = ecalloc(1, sizeof *fi);
147 1.1 thorpej if (ht_insert(pathtab, path, fi)) {
148 1.1 thorpej free(fi);
149 1.1 thorpej if ((fi = ht_lookup(pathtab, path)) == NULL)
150 1.1 thorpej panic("addfile: ht_lookup(%s)", path);
151 1.21 uebayasi
152 1.21 uebayasi /*
153 1.21 uebayasi * If it's a duplicate entry, it is must specify a make
154 1.21 uebayasi * rule, and only a make rule, and must come from
155 1.21 uebayasi * a different source file than the original entry.
156 1.21 uebayasi * If it does otherwise, it is disallowed. This allows
157 1.21 uebayasi * machine-dependent files to override the compilation
158 1.21 uebayasi * options for specific files.
159 1.21 uebayasi */
160 1.21 uebayasi if (rule != NULL && optx == NULL && flags == 0 &&
161 1.37 christos yyfile != fi->fi_where.w_srcfile) {
162 1.21 uebayasi fi->fi_mkrule = rule;
163 1.21 uebayasi return;
164 1.21 uebayasi }
165 1.6 christos cfgerror("duplicate file %s", path);
166 1.37 christos cfgxerror(fi->fi_where.w_srcfile, fi->fi_where.w_srcline,
167 1.1 thorpej "here is the original definition");
168 1.1 thorpej goto bad;
169 1.1 thorpej }
170 1.1 thorpej memcpy(base, tail, baselen);
171 1.24 uebayasi base[baselen] = '\0';
172 1.37 christos fi->fi_where.w_srcfile = yyfile;
173 1.37 christos fi->fi_where.w_srcline = currentline();
174 1.1 thorpej fi->fi_flags = flags;
175 1.1 thorpej fi->fi_path = path;
176 1.1 thorpej fi->fi_tail = tail;
177 1.1 thorpej fi->fi_base = intern(base);
178 1.24 uebayasi fi->fi_dir = intern(dir);
179 1.1 thorpej fi->fi_prefix = SLIST_EMPTY(&prefixes) ? NULL :
180 1.1 thorpej SLIST_FIRST(&prefixes)->pf_prefix;
181 1.25 uebayasi fi->fi_buildprefix = SLIST_EMPTY(&buildprefixes) ? NULL :
182 1.25 uebayasi SLIST_FIRST(&buildprefixes)->pf_prefix;
183 1.18 uebayasi fi->fi_len = strlen(path);
184 1.18 uebayasi fi->fi_suffix = path[fi->fi_len - 1];
185 1.1 thorpej fi->fi_optx = optx;
186 1.1 thorpej fi->fi_optf = NULL;
187 1.21 uebayasi fi->fi_mkrule = rule;
188 1.14 uebayasi fi->fi_attr = NULL;
189 1.33 uebayasi fi->fi_order = (int)nallfiles + (includedepth << 16);
190 1.22 uebayasi switch (fi->fi_suffix) {
191 1.22 uebayasi case 'c':
192 1.22 uebayasi TAILQ_INSERT_TAIL(&allcfiles, fi, fi_snext);
193 1.22 uebayasi TAILQ_INSERT_TAIL(&allfiles, fi, fi_next);
194 1.22 uebayasi break;
195 1.22 uebayasi case 'S':
196 1.23 uebayasi fi->fi_suffix = 's';
197 1.23 uebayasi /* FALLTHRU */
198 1.22 uebayasi case 's':
199 1.22 uebayasi TAILQ_INSERT_TAIL(&allsfiles, fi, fi_snext);
200 1.22 uebayasi TAILQ_INSERT_TAIL(&allfiles, fi, fi_next);
201 1.22 uebayasi break;
202 1.22 uebayasi case 'o':
203 1.22 uebayasi TAILQ_INSERT_TAIL(&allofiles, fi, fi_snext);
204 1.30 uebayasi TAILQ_INSERT_TAIL(&allfiles, fi, fi_next);
205 1.23 uebayasi break;
206 1.23 uebayasi default:
207 1.37 christos cfgxerror(fi->fi_where.w_srcfile, fi->fi_where.w_srcline,
208 1.23 uebayasi "unknown suffix");
209 1.22 uebayasi break;
210 1.22 uebayasi }
211 1.33 uebayasi CFGDBG(3, "file added `%s' at order score %d", fi->fi_path, fi->fi_order);
212 1.33 uebayasi nallfiles++;
213 1.1 thorpej return;
214 1.1 thorpej bad:
215 1.12 dholland if (optx != NULL) {
216 1.12 dholland condexpr_destroy(optx);
217 1.12 dholland }
218 1.1 thorpej }
219 1.1 thorpej
220 1.14 uebayasi static void
221 1.14 uebayasi addfiletoattr(const char *name, struct files *fi)
222 1.14 uebayasi {
223 1.14 uebayasi struct attr *a;
224 1.14 uebayasi
225 1.14 uebayasi a = ht_lookup(attrtab, name);
226 1.15 uebayasi if (a == NULL) {
227 1.15 uebayasi CFGDBG(1, "attr `%s' not found", name);
228 1.15 uebayasi } else {
229 1.15 uebayasi fi->fi_attr = a;
230 1.14 uebayasi TAILQ_INSERT_TAIL(&a->a_files, fi, fi_anext);
231 1.14 uebayasi }
232 1.14 uebayasi }
233 1.14 uebayasi
234 1.1 thorpej /*
235 1.1 thorpej * We have finished reading some "files" file, either ../../conf/files
236 1.1 thorpej * or ./files.$machine. Make sure that everything that is flagged as
237 1.1 thorpej * needing a count is reasonable. (This prevents ../../conf/files from
238 1.1 thorpej * depending on some machine-specific device.)
239 1.1 thorpej */
240 1.1 thorpej void
241 1.1 thorpej checkfiles(void)
242 1.1 thorpej {
243 1.1 thorpej struct files *fi, *last;
244 1.1 thorpej
245 1.1 thorpej last = NULL;
246 1.1 thorpej for (fi = *unchecked; fi != NULL;
247 1.1 thorpej last = fi, fi = TAILQ_NEXT(fi, fi_next)) {
248 1.1 thorpej if ((fi->fi_flags & FI_NEEDSCOUNT) != 0)
249 1.1 thorpej (void)expr_eval(fi->fi_optx, checkaux, fi);
250 1.1 thorpej }
251 1.1 thorpej if (last != NULL)
252 1.1 thorpej unchecked = &TAILQ_NEXT(last, fi_next);
253 1.1 thorpej }
254 1.1 thorpej
255 1.1 thorpej /*
256 1.1 thorpej * Auxiliary function for checkfiles, called from expr_eval.
257 1.1 thorpej * We are not actually interested in the expression's value.
258 1.1 thorpej */
259 1.1 thorpej static int
260 1.1 thorpej checkaux(const char *name, void *context)
261 1.1 thorpej {
262 1.1 thorpej struct files *fi = context;
263 1.1 thorpej
264 1.1 thorpej if (ht_lookup(devbasetab, name) == NULL) {
265 1.37 christos cfgxerror(fi->fi_where.w_srcfile, fi->fi_where.w_srcline,
266 1.1 thorpej "`%s' is not a countable device",
267 1.1 thorpej name);
268 1.1 thorpej /* keep fixfiles() from complaining again */
269 1.1 thorpej fi->fi_flags |= FI_HIDDEN;
270 1.1 thorpej }
271 1.1 thorpej return (0);
272 1.1 thorpej }
273 1.1 thorpej
274 1.33 uebayasi static int
275 1.33 uebayasi cmpfiles(const void *a, const void *b)
276 1.33 uebayasi {
277 1.33 uebayasi const struct files * const *fia = a, * const *fib = b;
278 1.33 uebayasi int sa = (*fia)->fi_order;
279 1.33 uebayasi int sb = (*fib)->fi_order;
280 1.33 uebayasi
281 1.33 uebayasi if (sa < sb)
282 1.33 uebayasi return -1;
283 1.33 uebayasi else if (sa > sb)
284 1.37.6.1 martin return +1;
285 1.33 uebayasi else
286 1.37.6.1 martin abort(); /* no ties possible */
287 1.33 uebayasi }
288 1.33 uebayasi
289 1.1 thorpej /*
290 1.1 thorpej * We have finished reading everything. Tack the files down: calculate
291 1.1 thorpej * selection and counts as needed. Check that the object files built
292 1.1 thorpej * from the selected sources do not collide.
293 1.1 thorpej */
294 1.1 thorpej int
295 1.1 thorpej fixfiles(void)
296 1.1 thorpej {
297 1.1 thorpej struct files *fi, *ofi;
298 1.1 thorpej struct nvlist *flathead, **flatp;
299 1.1 thorpej int err, sel;
300 1.31 uebayasi struct config *cf;
301 1.31 uebayasi char swapname[100];
302 1.1 thorpej
303 1.33 uebayasi /* Place these files at last. */
304 1.33 uebayasi int onallfiles = nallfiles;
305 1.33 uebayasi nallfiles = 1 << 30;
306 1.29 uebayasi addfile("devsw.c", NULL, 0, NULL);
307 1.29 uebayasi addfile("ioconf.c", NULL, 0, NULL);
308 1.29 uebayasi
309 1.31 uebayasi TAILQ_FOREACH(cf, &allcf, cf_next) {
310 1.31 uebayasi (void)snprintf(swapname, sizeof(swapname), "swap%s.c",
311 1.31 uebayasi cf->cf_name);
312 1.31 uebayasi addfile(intern(swapname), NULL, 0, NULL);
313 1.31 uebayasi }
314 1.33 uebayasi nallfiles = onallfiles;
315 1.26 uebayasi
316 1.1 thorpej err = 0;
317 1.1 thorpej TAILQ_FOREACH(fi, &allfiles, fi_next) {
318 1.2 erh
319 1.1 thorpej /* Skip files that generated counted-device complaints. */
320 1.1 thorpej if (fi->fi_flags & FI_HIDDEN)
321 1.1 thorpej continue;
322 1.1 thorpej
323 1.16 uebayasi if (fi->fi_optx != NULL) {
324 1.14 uebayasi if (fi->fi_optx->cx_type == CX_ATOM) {
325 1.14 uebayasi addfiletoattr(fi->fi_optx->cx_u.atom, fi);
326 1.14 uebayasi }
327 1.1 thorpej flathead = NULL;
328 1.1 thorpej flatp = &flathead;
329 1.1 thorpej sel = expr_eval(fi->fi_optx,
330 1.1 thorpej fi->fi_flags & FI_NEEDSCOUNT ? fixcount :
331 1.1 thorpej fi->fi_flags & FI_NEEDSFLAG ? fixfsel :
332 1.1 thorpej fixsel,
333 1.1 thorpej &flatp);
334 1.1 thorpej fi->fi_optf = flathead;
335 1.1 thorpej if (!sel)
336 1.1 thorpej continue;
337 1.1 thorpej }
338 1.36 christos if (fi->fi_attr && fi->fi_attr->a_deselected) {
339 1.36 christos CFGDBG(5, "file `%s' deselected because attr `%s' was",
340 1.36 christos fi->fi_path, fi->fi_attr->a_name);
341 1.36 christos continue;
342 1.36 christos }
343 1.1 thorpej
344 1.1 thorpej /* We like this file. Make sure it generates a unique .o. */
345 1.1 thorpej if (ht_insert(basetab, fi->fi_base, fi)) {
346 1.1 thorpej if ((ofi = ht_lookup(basetab, fi->fi_base)) == NULL)
347 1.1 thorpej panic("fixfiles ht_lookup(%s)", fi->fi_base);
348 1.1 thorpej /*
349 1.1 thorpej * If the new file comes from a different source,
350 1.1 thorpej * allow the new one to override the old one.
351 1.1 thorpej */
352 1.1 thorpej if (fi->fi_path != ofi->fi_path) {
353 1.1 thorpej if (ht_replace(basetab, fi->fi_base, fi) != 1)
354 1.1 thorpej panic("fixfiles ht_replace(%s)",
355 1.1 thorpej fi->fi_base);
356 1.17 christos ofi->fi_flags &= (u_char)~FI_SEL;
357 1.1 thorpej ofi->fi_flags |= FI_HIDDEN;
358 1.1 thorpej } else {
359 1.37 christos cfgxerror(fi->fi_where.w_srcfile, fi->fi_where.w_srcline,
360 1.1 thorpej "object file collision on %s.o, from %s",
361 1.1 thorpej fi->fi_base, fi->fi_path);
362 1.37 christos cfgxerror(ofi->fi_where.w_srcfile, ofi->fi_where.w_srcline,
363 1.1 thorpej "here is the previous file: %s",
364 1.1 thorpej ofi->fi_path);
365 1.1 thorpej err = 1;
366 1.1 thorpej }
367 1.1 thorpej }
368 1.1 thorpej fi->fi_flags |= FI_SEL;
369 1.33 uebayasi nselfiles++;
370 1.15 uebayasi CFGDBG(3, "file selected `%s'", fi->fi_path);
371 1.15 uebayasi
372 1.15 uebayasi /* Add other files to the default "netbsd" attribute. */
373 1.15 uebayasi if (fi->fi_attr == NULL) {
374 1.15 uebayasi addfiletoattr(allattr.a_name, fi);
375 1.15 uebayasi }
376 1.15 uebayasi CFGDBG(3, "file `%s' belongs to attr `%s'", fi->fi_path,
377 1.15 uebayasi fi->fi_attr->a_name);
378 1.1 thorpej }
379 1.33 uebayasi
380 1.33 uebayasi /* Order files. */
381 1.33 uebayasi selfiles = malloc(nselfiles * sizeof(fi));
382 1.35 uebayasi unsigned i = 0;
383 1.33 uebayasi TAILQ_FOREACH(fi, &allfiles, fi_next) {
384 1.33 uebayasi if ((fi->fi_flags & FI_SEL) == 0)
385 1.33 uebayasi continue;
386 1.33 uebayasi selfiles[i++] = fi;
387 1.33 uebayasi }
388 1.34 uebayasi assert(i <= nselfiles);
389 1.34 uebayasi nselfiles = i;
390 1.33 uebayasi qsort(selfiles, nselfiles, (unsigned)sizeof(fi), cmpfiles);
391 1.1 thorpej return (err);
392 1.1 thorpej }
393 1.1 thorpej
394 1.1 thorpej
395 1.1 thorpej /*
396 1.1 thorpej * We have finished reading everything. Tack the devsws down: calculate
397 1.1 thorpej * selection.
398 1.1 thorpej */
399 1.1 thorpej int
400 1.1 thorpej fixdevsw(void)
401 1.1 thorpej {
402 1.5 alc int error;
403 1.1 thorpej struct devm *dm, *res;
404 1.1 thorpej struct hashtab *fixdevmtab;
405 1.1 thorpej char mstr[16];
406 1.1 thorpej
407 1.5 alc error = 0;
408 1.1 thorpej fixdevmtab = ht_new();
409 1.1 thorpej
410 1.1 thorpej TAILQ_FOREACH(dm, &alldevms, dm_next) {
411 1.1 thorpej res = ht_lookup(fixdevmtab, intern(dm->dm_name));
412 1.1 thorpej if (res != NULL) {
413 1.1 thorpej if (res->dm_cmajor != dm->dm_cmajor ||
414 1.1 thorpej res->dm_bmajor != dm->dm_bmajor) {
415 1.37 christos cfgxerror(res->dm_where.w_srcfile,
416 1.37 christos res->dm_where.w_srcline,
417 1.37 christos "device-major '%s' "
418 1.37 christos "block %d, char %d redefined"
419 1.37 christos " at %s:%d as block %d, char %d",
420 1.37 christos res->dm_name,
421 1.37 christos res->dm_bmajor, res->dm_cmajor,
422 1.37 christos dm->dm_where.w_srcfile, dm->dm_where.w_srcline,
423 1.37 christos dm->dm_bmajor, dm->dm_cmajor);
424 1.1 thorpej } else {
425 1.37 christos cfgxerror(res->dm_where.w_srcfile,
426 1.37 christos res->dm_where.w_srcline,
427 1.37 christos "device-major '%s' "
428 1.37 christos "(block %d, char %d) duplicated"
429 1.37 christos " at %s:%d",
430 1.37 christos dm->dm_name, dm->dm_bmajor,
431 1.37 christos dm->dm_cmajor,
432 1.37 christos dm->dm_where.w_srcfile,
433 1.37 christos dm->dm_where.w_srcline);
434 1.1 thorpej }
435 1.7 dsl error = 1;
436 1.7 dsl goto out;
437 1.1 thorpej }
438 1.1 thorpej if (ht_insert(fixdevmtab, intern(dm->dm_name), dm)) {
439 1.1 thorpej panic("fixdevsw: %s char %d block %d",
440 1.1 thorpej dm->dm_name, dm->dm_cmajor, dm->dm_bmajor);
441 1.1 thorpej }
442 1.1 thorpej
443 1.1 thorpej if (dm->dm_opts != NULL &&
444 1.1 thorpej !expr_eval(dm->dm_opts, fixsel, NULL))
445 1.1 thorpej continue;
446 1.1 thorpej
447 1.9 drochner if (dm->dm_cmajor != NODEVMAJOR) {
448 1.1 thorpej if (ht_lookup(cdevmtab, intern(dm->dm_name)) != NULL) {
449 1.37 christos cfgxerror(dm->dm_where.w_srcfile,
450 1.37 christos dm->dm_where.w_srcline,
451 1.37 christos "device-major of character device '%s' "
452 1.37 christos "is already defined", dm->dm_name);
453 1.5 alc error = 1;
454 1.4 christos goto out;
455 1.1 thorpej }
456 1.1 thorpej (void)snprintf(mstr, sizeof(mstr), "%d", dm->dm_cmajor);
457 1.1 thorpej if (ht_lookup(cdevmtab, intern(mstr)) != NULL) {
458 1.37 christos cfgxerror(dm->dm_where.w_srcfile, dm->dm_where.w_srcline,
459 1.1 thorpej "device-major of character major '%d' "
460 1.1 thorpej "is already defined", dm->dm_cmajor);
461 1.5 alc error = 1;
462 1.4 christos goto out;
463 1.1 thorpej }
464 1.1 thorpej if (ht_insert(cdevmtab, intern(dm->dm_name), dm) ||
465 1.1 thorpej ht_insert(cdevmtab, intern(mstr), dm)) {
466 1.1 thorpej panic("fixdevsw: %s character major %d",
467 1.1 thorpej dm->dm_name, dm->dm_cmajor);
468 1.1 thorpej }
469 1.1 thorpej }
470 1.9 drochner if (dm->dm_bmajor != NODEVMAJOR) {
471 1.1 thorpej if (ht_lookup(bdevmtab, intern(dm->dm_name)) != NULL) {
472 1.37 christos cfgxerror(dm->dm_where.w_srcfile, dm->dm_where.w_srcline,
473 1.1 thorpej "device-major of block device '%s' "
474 1.1 thorpej "is already defined", dm->dm_name);
475 1.5 alc error = 1;
476 1.4 christos goto out;
477 1.1 thorpej }
478 1.1 thorpej (void)snprintf(mstr, sizeof(mstr), "%d", dm->dm_bmajor);
479 1.1 thorpej if (ht_lookup(bdevmtab, intern(mstr)) != NULL) {
480 1.37 christos cfgxerror(dm->dm_where.w_srcfile, dm->dm_where.w_srcline,
481 1.1 thorpej "device-major of block major '%d' "
482 1.1 thorpej "is already defined", dm->dm_bmajor);
483 1.5 alc error = 1;
484 1.4 christos goto out;
485 1.1 thorpej }
486 1.1 thorpej if (ht_insert(bdevmtab, intern(dm->dm_name), dm) ||
487 1.1 thorpej ht_insert(bdevmtab, intern(mstr), dm)) {
488 1.1 thorpej panic("fixdevsw: %s block major %d",
489 1.1 thorpej dm->dm_name, dm->dm_bmajor);
490 1.1 thorpej }
491 1.1 thorpej }
492 1.1 thorpej }
493 1.1 thorpej
494 1.4 christos out:
495 1.4 christos ht_free(fixdevmtab);
496 1.5 alc return (error);
497 1.1 thorpej }
498 1.1 thorpej
499 1.1 thorpej /*
500 1.1 thorpej * Called when evaluating a needs-count expression. Make sure the
501 1.1 thorpej * atom is a countable device. The expression succeeds iff there
502 1.1 thorpej * is at least one of them (note that while `xx*' will not always
503 1.1 thorpej * set xx's d_umax > 0, you cannot mix '*' and needs-count). The
504 1.1 thorpej * mkheaders() routine wants a flattened, in-order list of the
505 1.1 thorpej * atoms for `#define name value' lines, so we build that as we
506 1.1 thorpej * are called to eval each atom.
507 1.1 thorpej */
508 1.1 thorpej static int
509 1.1 thorpej fixcount(const char *name, void *context)
510 1.1 thorpej {
511 1.1 thorpej struct nvlist ***p = context;
512 1.1 thorpej struct devbase *dev;
513 1.1 thorpej struct nvlist *nv;
514 1.1 thorpej
515 1.1 thorpej dev = ht_lookup(devbasetab, name);
516 1.1 thorpej if (dev == NULL) /* cannot occur here; we checked earlier */
517 1.1 thorpej panic("fixcount(%s)", name);
518 1.1 thorpej nv = newnv(name, NULL, NULL, dev->d_umax, NULL);
519 1.1 thorpej **p = nv;
520 1.1 thorpej *p = &nv->nv_next;
521 1.1 thorpej (void)ht_insert(needcnttab, name, nv);
522 1.1 thorpej return (dev->d_umax != 0);
523 1.1 thorpej }
524 1.1 thorpej
525 1.1 thorpej /*
526 1.1 thorpej * Called from fixfiles when eval'ing a selection expression for a
527 1.1 thorpej * file that will generate a .h with flags. We will need the flat list.
528 1.1 thorpej */
529 1.1 thorpej static int
530 1.1 thorpej fixfsel(const char *name, void *context)
531 1.1 thorpej {
532 1.1 thorpej struct nvlist ***p = context;
533 1.1 thorpej struct nvlist *nv;
534 1.1 thorpej int sel;
535 1.1 thorpej
536 1.1 thorpej sel = ht_lookup(selecttab, name) != NULL;
537 1.1 thorpej nv = newnv(name, NULL, NULL, sel, NULL);
538 1.1 thorpej **p = nv;
539 1.1 thorpej *p = &nv->nv_next;
540 1.1 thorpej return (sel);
541 1.1 thorpej }
542 1.1 thorpej
543 1.1 thorpej /*
544 1.1 thorpej * As for fixfsel above, but we do not need the flat list.
545 1.1 thorpej */
546 1.1 thorpej static int
547 1.6 christos /*ARGSUSED*/
548 1.1 thorpej fixsel(const char *name, void *context)
549 1.1 thorpej {
550 1.1 thorpej
551 1.1 thorpej return (ht_lookup(selecttab, name) != NULL);
552 1.1 thorpej }
553 1.1 thorpej
554 1.1 thorpej /*
555 1.1 thorpej * Eval an expression tree. Calls the given function on each node,
556 1.1 thorpej * passing it the given context & the name; return value is &/|/! of
557 1.1 thorpej * results of evaluating atoms.
558 1.1 thorpej *
559 1.1 thorpej * No short circuiting ever occurs. fn must return 0 or 1 (otherwise
560 1.1 thorpej * our mixing of C's bitwise & boolean here may give surprises).
561 1.1 thorpej */
562 1.10 cube int
563 1.11 dholland expr_eval(struct condexpr *expr, int (*fn)(const char *, void *), void *ctx)
564 1.1 thorpej {
565 1.1 thorpej int lhs, rhs;
566 1.1 thorpej
567 1.11 dholland switch (expr->cx_type) {
568 1.1 thorpej
569 1.11 dholland case CX_ATOM:
570 1.11 dholland return ((*fn)(expr->cx_atom, ctx));
571 1.1 thorpej
572 1.11 dholland case CX_NOT:
573 1.11 dholland return (!expr_eval(expr->cx_not, fn, ctx));
574 1.1 thorpej
575 1.11 dholland case CX_AND:
576 1.11 dholland lhs = expr_eval(expr->cx_and.left, fn, ctx);
577 1.11 dholland rhs = expr_eval(expr->cx_and.right, fn, ctx);
578 1.1 thorpej return (lhs & rhs);
579 1.1 thorpej
580 1.11 dholland case CX_OR:
581 1.11 dholland lhs = expr_eval(expr->cx_or.left, fn, ctx);
582 1.11 dholland rhs = expr_eval(expr->cx_or.right, fn, ctx);
583 1.1 thorpej return (lhs | rhs);
584 1.1 thorpej }
585 1.11 dholland panic("invalid condexpr type %d", (int)expr->cx_type);
586 1.1 thorpej /* NOTREACHED */
587 1.1 thorpej return (0);
588 1.1 thorpej }
589 1.1 thorpej
590 1.1 thorpej #ifdef DEBUG
591 1.1 thorpej /*
592 1.1 thorpej * Print expression tree.
593 1.1 thorpej */
594 1.1 thorpej void
595 1.1 thorpej prexpr(struct nvlist *expr)
596 1.1 thorpej {
597 1.1 thorpej static void pr0();
598 1.1 thorpej
599 1.1 thorpej printf("expr =");
600 1.1 thorpej pr0(expr);
601 1.1 thorpej printf("\n");
602 1.1 thorpej (void)fflush(stdout);
603 1.1 thorpej }
604 1.1 thorpej
605 1.1 thorpej static void
606 1.1 thorpej pr0(struct nvlist *e)
607 1.1 thorpej {
608 1.1 thorpej
609 1.8 christos switch (e->nv_num) {
610 1.1 thorpej case FX_ATOM:
611 1.1 thorpej printf(" %s", e->nv_name);
612 1.1 thorpej return;
613 1.1 thorpej case FX_NOT:
614 1.1 thorpej printf(" (!");
615 1.1 thorpej break;
616 1.1 thorpej case FX_AND:
617 1.1 thorpej printf(" (&");
618 1.1 thorpej break;
619 1.1 thorpej case FX_OR:
620 1.1 thorpej printf(" (|");
621 1.1 thorpej break;
622 1.1 thorpej default:
623 1.8 christos printf(" (?%lld?", e->nv_num);
624 1.1 thorpej break;
625 1.1 thorpej }
626 1.1 thorpej if (e->nv_ptr)
627 1.1 thorpej pr0(e->nv_ptr);
628 1.1 thorpej pr0(e->nv_next);
629 1.1 thorpej printf(")");
630 1.1 thorpej }
631 1.1 thorpej #endif
632