1*6dc5a3c0Sriastradh /* $NetBSD: files.c,v 1.38 2024/04/05 00:43:42 riastradh Exp $ */
25ecc953bSthorpej
35ecc953bSthorpej /*
45ecc953bSthorpej * Copyright (c) 1992, 1993
55ecc953bSthorpej * The Regents of the University of California. All rights reserved.
65ecc953bSthorpej *
75ecc953bSthorpej * This software was developed by the Computer Systems Engineering group
85ecc953bSthorpej * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
95ecc953bSthorpej * contributed to Berkeley.
105ecc953bSthorpej *
115ecc953bSthorpej * All advertising materials mentioning features or use of this software
125ecc953bSthorpej * must display the following acknowledgement:
135ecc953bSthorpej * This product includes software developed by the University of
145ecc953bSthorpej * California, Lawrence Berkeley Laboratories.
155ecc953bSthorpej *
165ecc953bSthorpej * Redistribution and use in source and binary forms, with or without
175ecc953bSthorpej * modification, are permitted provided that the following conditions
185ecc953bSthorpej * are met:
195ecc953bSthorpej * 1. Redistributions of source code must retain the above copyright
205ecc953bSthorpej * notice, this list of conditions and the following disclaimer.
215ecc953bSthorpej * 2. Redistributions in binary form must reproduce the above copyright
225ecc953bSthorpej * notice, this list of conditions and the following disclaimer in the
235ecc953bSthorpej * documentation and/or other materials provided with the distribution.
245ecc953bSthorpej * 3. Neither the name of the University nor the names of its contributors
255ecc953bSthorpej * may be used to endorse or promote products derived from this software
265ecc953bSthorpej * without specific prior written permission.
275ecc953bSthorpej *
285ecc953bSthorpej * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
295ecc953bSthorpej * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
305ecc953bSthorpej * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
315ecc953bSthorpej * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
325ecc953bSthorpej * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
335ecc953bSthorpej * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
345ecc953bSthorpej * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
355ecc953bSthorpej * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
365ecc953bSthorpej * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
375ecc953bSthorpej * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
385ecc953bSthorpej * SUCH DAMAGE.
395ecc953bSthorpej *
405ecc953bSthorpej * from: @(#)files.c 8.1 (Berkeley) 6/6/93
415ecc953bSthorpej */
425ecc953bSthorpej
435ecc953bSthorpej #if HAVE_NBTOOL_CONFIG_H
445ecc953bSthorpej #include "nbtool_config.h"
455ecc953bSthorpej #endif
465ecc953bSthorpej
47d12b0036Schristos #include <sys/cdefs.h>
48*6dc5a3c0Sriastradh __RCSID("$NetBSD: files.c,v 1.38 2024/04/05 00:43:42 riastradh Exp $");
49d12b0036Schristos
505ecc953bSthorpej #include <sys/param.h>
51cea9d6a0Suebayasi #include <assert.h>
525ecc953bSthorpej #include <errno.h>
535ecc953bSthorpej #include <stdio.h>
545ecc953bSthorpej #include <stdlib.h>
555ecc953bSthorpej #include <string.h>
56d0fb8901Schristos #include <util.h>
575ecc953bSthorpej #include "defs.h"
585ecc953bSthorpej
595ecc953bSthorpej extern const char *yyfile;
605ecc953bSthorpej
619b48d494Suebayasi int nallfiles;
629b48d494Suebayasi size_t nselfiles;
639b48d494Suebayasi struct files **selfiles;
649b48d494Suebayasi
655ecc953bSthorpej /*
665ecc953bSthorpej * We check that each full path name is unique. File base names
675ecc953bSthorpej * should generally also be unique, e.g., having both a net/xx.c and
685ecc953bSthorpej * a kern/xx.c (or, worse, a net/xx.c and a new/xx.c++) is probably
695ecc953bSthorpej * wrong, but is permitted under some conditions.
705ecc953bSthorpej */
715ecc953bSthorpej static struct hashtab *basetab; /* file base names */
725ecc953bSthorpej static struct hashtab *pathtab; /* full path names */
735ecc953bSthorpej
745ecc953bSthorpej static struct files **unchecked;
755ecc953bSthorpej
76fa3d8504Suebayasi static void addfiletoattr(const char *, struct files *);
775ecc953bSthorpej static int checkaux(const char *, void *);
785ecc953bSthorpej static int fixcount(const char *, void *);
795ecc953bSthorpej static int fixfsel(const char *, void *);
805ecc953bSthorpej static int fixsel(const char *, void *);
815ecc953bSthorpej
825ecc953bSthorpej void
initfiles(void)835ecc953bSthorpej initfiles(void)
845ecc953bSthorpej {
855ecc953bSthorpej
865ecc953bSthorpej basetab = ht_new();
875ecc953bSthorpej pathtab = ht_new();
885ecc953bSthorpej TAILQ_INIT(&allfiles);
890b130540Suebayasi TAILQ_INIT(&allcfiles);
900b130540Suebayasi TAILQ_INIT(&allsfiles);
910b130540Suebayasi TAILQ_INIT(&allofiles);
925ecc953bSthorpej unchecked = &TAILQ_FIRST(&allfiles);
935ecc953bSthorpej }
945ecc953bSthorpej
955ecc953bSthorpej void
addfile(const char * path,struct condexpr * optx,u_char flags,const char * rule)96ca847f03Suebayasi addfile(const char *path, struct condexpr *optx, u_char flags, const char *rule)
975ecc953bSthorpej {
985ecc953bSthorpej struct files *fi;
995ecc953bSthorpej const char *dotp, *tail;
1005ecc953bSthorpej size_t baselen;
101974426ddSuebayasi size_t dirlen;
1025ecc953bSthorpej int needc, needf;
1035ecc953bSthorpej char base[200];
104974426ddSuebayasi char dir[MAXPATHLEN];
1055ecc953bSthorpej
1065ecc953bSthorpej /* check various errors */
1075ecc953bSthorpej needc = flags & FI_NEEDSCOUNT;
1085ecc953bSthorpej needf = flags & FI_NEEDSFLAG;
1095ecc953bSthorpej if (needc && needf) {
110c7295a4cSchristos cfgerror("cannot mix needs-count and needs-flag");
1115ecc953bSthorpej goto bad;
1125ecc953bSthorpej }
1135ecc953bSthorpej if (optx == NULL && (needc || needf)) {
114c7295a4cSchristos cfgerror("nothing to %s for %s", needc ? "count" : "flag",
115c7295a4cSchristos path);
1165ecc953bSthorpej goto bad;
1175ecc953bSthorpej }
11836644ae2Suebayasi if (*path == '/') {
11936644ae2Suebayasi cfgerror("path must be relative");
12036644ae2Suebayasi goto bad;
12136644ae2Suebayasi }
1225ecc953bSthorpej
1235ecc953bSthorpej /* find last part of pathname, and same without trailing suffix */
1245ecc953bSthorpej tail = strrchr(path, '/');
125974426ddSuebayasi if (tail == NULL) {
126974426ddSuebayasi dirlen = 0;
1275ecc953bSthorpej tail = path;
128974426ddSuebayasi } else {
129974426ddSuebayasi dirlen = (size_t)(tail - path);
1305ecc953bSthorpej tail++;
131974426ddSuebayasi }
132974426ddSuebayasi memcpy(dir, path, dirlen);
133974426ddSuebayasi dir[dirlen] = '\0';
134974426ddSuebayasi
1355ecc953bSthorpej dotp = strrchr(tail, '.');
1365ecc953bSthorpej if (dotp == NULL || dotp[1] == 0 ||
137d12b0036Schristos (baselen = (size_t)(dotp - tail)) >= sizeof(base)) {
138c7295a4cSchristos cfgerror("invalid pathname `%s'", path);
1395ecc953bSthorpej goto bad;
1405ecc953bSthorpej }
1415ecc953bSthorpej
1425ecc953bSthorpej /*
1435ecc953bSthorpej * Commit this file to memory. We will decide later whether it
1445ecc953bSthorpej * will be used after all.
1455ecc953bSthorpej */
1465ecc953bSthorpej fi = ecalloc(1, sizeof *fi);
1475ecc953bSthorpej if (ht_insert(pathtab, path, fi)) {
1485ecc953bSthorpej free(fi);
1495ecc953bSthorpej if ((fi = ht_lookup(pathtab, path)) == NULL)
1505ecc953bSthorpej panic("addfile: ht_lookup(%s)", path);
151ca847f03Suebayasi
152ca847f03Suebayasi /*
153ca847f03Suebayasi * If it's a duplicate entry, it is must specify a make
154ca847f03Suebayasi * rule, and only a make rule, and must come from
155ca847f03Suebayasi * a different source file than the original entry.
156ca847f03Suebayasi * If it does otherwise, it is disallowed. This allows
157ca847f03Suebayasi * machine-dependent files to override the compilation
158ca847f03Suebayasi * options for specific files.
159ca847f03Suebayasi */
160ca847f03Suebayasi if (rule != NULL && optx == NULL && flags == 0 &&
16120255392Schristos yyfile != fi->fi_where.w_srcfile) {
162ca847f03Suebayasi fi->fi_mkrule = rule;
163ca847f03Suebayasi return;
164ca847f03Suebayasi }
165c7295a4cSchristos cfgerror("duplicate file %s", path);
16620255392Schristos cfgxerror(fi->fi_where.w_srcfile, fi->fi_where.w_srcline,
1675ecc953bSthorpej "here is the original definition");
1685ecc953bSthorpej goto bad;
1695ecc953bSthorpej }
1705ecc953bSthorpej memcpy(base, tail, baselen);
171974426ddSuebayasi base[baselen] = '\0';
17220255392Schristos fi->fi_where.w_srcfile = yyfile;
17320255392Schristos fi->fi_where.w_srcline = currentline();
1745ecc953bSthorpej fi->fi_flags = flags;
1755ecc953bSthorpej fi->fi_path = path;
1765ecc953bSthorpej fi->fi_tail = tail;
1775ecc953bSthorpej fi->fi_base = intern(base);
178974426ddSuebayasi fi->fi_dir = intern(dir);
1795ecc953bSthorpej fi->fi_prefix = SLIST_EMPTY(&prefixes) ? NULL :
1805ecc953bSthorpej SLIST_FIRST(&prefixes)->pf_prefix;
1812cb009cdSuebayasi fi->fi_buildprefix = SLIST_EMPTY(&buildprefixes) ? NULL :
1822cb009cdSuebayasi SLIST_FIRST(&buildprefixes)->pf_prefix;
18357751c84Suebayasi fi->fi_len = strlen(path);
18457751c84Suebayasi fi->fi_suffix = path[fi->fi_len - 1];
1855ecc953bSthorpej fi->fi_optx = optx;
1865ecc953bSthorpej fi->fi_optf = NULL;
187ca847f03Suebayasi fi->fi_mkrule = rule;
188fa3d8504Suebayasi fi->fi_attr = NULL;
1899b48d494Suebayasi fi->fi_order = (int)nallfiles + (includedepth << 16);
1900b130540Suebayasi switch (fi->fi_suffix) {
1910b130540Suebayasi case 'c':
1920b130540Suebayasi TAILQ_INSERT_TAIL(&allcfiles, fi, fi_snext);
1935ecc953bSthorpej TAILQ_INSERT_TAIL(&allfiles, fi, fi_next);
1940b130540Suebayasi break;
1950b130540Suebayasi case 'S':
1963374c75eSuebayasi fi->fi_suffix = 's';
1973374c75eSuebayasi /* FALLTHRU */
1980b130540Suebayasi case 's':
1990b130540Suebayasi TAILQ_INSERT_TAIL(&allsfiles, fi, fi_snext);
2000b130540Suebayasi TAILQ_INSERT_TAIL(&allfiles, fi, fi_next);
2010b130540Suebayasi break;
2020b130540Suebayasi case 'o':
2030b130540Suebayasi TAILQ_INSERT_TAIL(&allofiles, fi, fi_snext);
204dc9cfb5dSuebayasi TAILQ_INSERT_TAIL(&allfiles, fi, fi_next);
2053374c75eSuebayasi break;
2063374c75eSuebayasi default:
20720255392Schristos cfgxerror(fi->fi_where.w_srcfile, fi->fi_where.w_srcline,
2083374c75eSuebayasi "unknown suffix");
2090b130540Suebayasi break;
2100b130540Suebayasi }
2119b48d494Suebayasi CFGDBG(3, "file added `%s' at order score %d", fi->fi_path, fi->fi_order);
2129b48d494Suebayasi nallfiles++;
2135ecc953bSthorpej return;
2145ecc953bSthorpej bad:
215d8da1d60Sdholland if (optx != NULL) {
216a551c5e8Sdholland condexpr_destroy(optx);
2175ecc953bSthorpej }
218d8da1d60Sdholland }
2195ecc953bSthorpej
220fa3d8504Suebayasi static void
addfiletoattr(const char * name,struct files * fi)221fa3d8504Suebayasi addfiletoattr(const char *name, struct files *fi)
222fa3d8504Suebayasi {
223fa3d8504Suebayasi struct attr *a;
224fa3d8504Suebayasi
225fa3d8504Suebayasi a = ht_lookup(attrtab, name);
226adf6a455Suebayasi if (a == NULL) {
227adf6a455Suebayasi CFGDBG(1, "attr `%s' not found", name);
228adf6a455Suebayasi } else {
229fa3d8504Suebayasi fi->fi_attr = a;
230adf6a455Suebayasi TAILQ_INSERT_TAIL(&a->a_files, fi, fi_anext);
231fa3d8504Suebayasi }
232fa3d8504Suebayasi }
233fa3d8504Suebayasi
2345ecc953bSthorpej /*
2355ecc953bSthorpej * We have finished reading some "files" file, either ../../conf/files
2365ecc953bSthorpej * or ./files.$machine. Make sure that everything that is flagged as
2375ecc953bSthorpej * needing a count is reasonable. (This prevents ../../conf/files from
2385ecc953bSthorpej * depending on some machine-specific device.)
2395ecc953bSthorpej */
2405ecc953bSthorpej void
checkfiles(void)2415ecc953bSthorpej checkfiles(void)
2425ecc953bSthorpej {
2435ecc953bSthorpej struct files *fi, *last;
2445ecc953bSthorpej
2455ecc953bSthorpej last = NULL;
2465ecc953bSthorpej for (fi = *unchecked; fi != NULL;
2475ecc953bSthorpej last = fi, fi = TAILQ_NEXT(fi, fi_next)) {
2485ecc953bSthorpej if ((fi->fi_flags & FI_NEEDSCOUNT) != 0)
2495ecc953bSthorpej (void)expr_eval(fi->fi_optx, checkaux, fi);
2505ecc953bSthorpej }
2515ecc953bSthorpej if (last != NULL)
2525ecc953bSthorpej unchecked = &TAILQ_NEXT(last, fi_next);
2535ecc953bSthorpej }
2545ecc953bSthorpej
2555ecc953bSthorpej /*
2565ecc953bSthorpej * Auxiliary function for checkfiles, called from expr_eval.
2575ecc953bSthorpej * We are not actually interested in the expression's value.
2585ecc953bSthorpej */
2595ecc953bSthorpej static int
checkaux(const char * name,void * context)2605ecc953bSthorpej checkaux(const char *name, void *context)
2615ecc953bSthorpej {
2625ecc953bSthorpej struct files *fi = context;
2635ecc953bSthorpej
2645ecc953bSthorpej if (ht_lookup(devbasetab, name) == NULL) {
26520255392Schristos cfgxerror(fi->fi_where.w_srcfile, fi->fi_where.w_srcline,
2665ecc953bSthorpej "`%s' is not a countable device",
2675ecc953bSthorpej name);
2685ecc953bSthorpej /* keep fixfiles() from complaining again */
2695ecc953bSthorpej fi->fi_flags |= FI_HIDDEN;
2705ecc953bSthorpej }
2715ecc953bSthorpej return (0);
2725ecc953bSthorpej }
2735ecc953bSthorpej
2749b48d494Suebayasi static int
cmpfiles(const void * a,const void * b)2759b48d494Suebayasi cmpfiles(const void *a, const void *b)
2769b48d494Suebayasi {
2779b48d494Suebayasi const struct files * const *fia = a, * const *fib = b;
2789b48d494Suebayasi int sa = (*fia)->fi_order;
2799b48d494Suebayasi int sb = (*fib)->fi_order;
2809b48d494Suebayasi
2819b48d494Suebayasi if (sa < sb)
2829b48d494Suebayasi return -1;
2839b48d494Suebayasi else if (sa > sb)
284*6dc5a3c0Sriastradh return +1;
2859b48d494Suebayasi else
286*6dc5a3c0Sriastradh abort(); /* no ties possible */
2879b48d494Suebayasi }
2889b48d494Suebayasi
2895ecc953bSthorpej /*
2905ecc953bSthorpej * We have finished reading everything. Tack the files down: calculate
2915ecc953bSthorpej * selection and counts as needed. Check that the object files built
2925ecc953bSthorpej * from the selected sources do not collide.
2935ecc953bSthorpej */
2945ecc953bSthorpej int
fixfiles(void)2955ecc953bSthorpej fixfiles(void)
2965ecc953bSthorpej {
2975ecc953bSthorpej struct files *fi, *ofi;
2985ecc953bSthorpej struct nvlist *flathead, **flatp;
2995ecc953bSthorpej int err, sel;
300bc2bf167Suebayasi struct config *cf;
301bc2bf167Suebayasi char swapname[100];
3025ecc953bSthorpej
3039b48d494Suebayasi /* Place these files at last. */
3049b48d494Suebayasi int onallfiles = nallfiles;
3059b48d494Suebayasi nallfiles = 1 << 30;
306bc619545Suebayasi addfile("devsw.c", NULL, 0, NULL);
307bc619545Suebayasi addfile("ioconf.c", NULL, 0, NULL);
308bc619545Suebayasi
309b0681745Suebayasi TAILQ_FOREACH(cf, &allcf, cf_next) {
310b5b4952dSuebayasi (void)snprintf(swapname, sizeof(swapname), "swap%s.c",
311b0681745Suebayasi cf->cf_name);
312b0681745Suebayasi addfile(intern(swapname), NULL, 0, NULL);
313b0681745Suebayasi }
3149b48d494Suebayasi nallfiles = onallfiles;
315b0681745Suebayasi
3165ecc953bSthorpej err = 0;
3175ecc953bSthorpej TAILQ_FOREACH(fi, &allfiles, fi_next) {
318cd429362Serh
3195ecc953bSthorpej /* Skip files that generated counted-device complaints. */
3205ecc953bSthorpej if (fi->fi_flags & FI_HIDDEN)
3215ecc953bSthorpej continue;
3225ecc953bSthorpej
323b35679c0Suebayasi if (fi->fi_optx != NULL) {
324fa3d8504Suebayasi if (fi->fi_optx->cx_type == CX_ATOM) {
325fa3d8504Suebayasi addfiletoattr(fi->fi_optx->cx_u.atom, fi);
326fa3d8504Suebayasi }
3275ecc953bSthorpej flathead = NULL;
3285ecc953bSthorpej flatp = &flathead;
3295ecc953bSthorpej sel = expr_eval(fi->fi_optx,
3305ecc953bSthorpej fi->fi_flags & FI_NEEDSCOUNT ? fixcount :
3315ecc953bSthorpej fi->fi_flags & FI_NEEDSFLAG ? fixfsel :
3325ecc953bSthorpej fixsel,
3335ecc953bSthorpej &flatp);
3345ecc953bSthorpej fi->fi_optf = flathead;
3355ecc953bSthorpej if (!sel)
3365ecc953bSthorpej continue;
3375ecc953bSthorpej }
3383a850393Schristos if (fi->fi_attr && fi->fi_attr->a_deselected) {
3393a850393Schristos CFGDBG(5, "file `%s' deselected because attr `%s' was",
3403a850393Schristos fi->fi_path, fi->fi_attr->a_name);
3413a850393Schristos continue;
3423a850393Schristos }
3435ecc953bSthorpej
3445ecc953bSthorpej /* We like this file. Make sure it generates a unique .o. */
3455ecc953bSthorpej if (ht_insert(basetab, fi->fi_base, fi)) {
3465ecc953bSthorpej if ((ofi = ht_lookup(basetab, fi->fi_base)) == NULL)
3475ecc953bSthorpej panic("fixfiles ht_lookup(%s)", fi->fi_base);
3485ecc953bSthorpej /*
3495ecc953bSthorpej * If the new file comes from a different source,
3505ecc953bSthorpej * allow the new one to override the old one.
3515ecc953bSthorpej */
3525ecc953bSthorpej if (fi->fi_path != ofi->fi_path) {
3535ecc953bSthorpej if (ht_replace(basetab, fi->fi_base, fi) != 1)
3545ecc953bSthorpej panic("fixfiles ht_replace(%s)",
3555ecc953bSthorpej fi->fi_base);
356d12b0036Schristos ofi->fi_flags &= (u_char)~FI_SEL;
3575ecc953bSthorpej ofi->fi_flags |= FI_HIDDEN;
3585ecc953bSthorpej } else {
35920255392Schristos cfgxerror(fi->fi_where.w_srcfile, fi->fi_where.w_srcline,
3605ecc953bSthorpej "object file collision on %s.o, from %s",
3615ecc953bSthorpej fi->fi_base, fi->fi_path);
36220255392Schristos cfgxerror(ofi->fi_where.w_srcfile, ofi->fi_where.w_srcline,
3635ecc953bSthorpej "here is the previous file: %s",
3645ecc953bSthorpej ofi->fi_path);
3655ecc953bSthorpej err = 1;
3665ecc953bSthorpej }
3675ecc953bSthorpej }
3685ecc953bSthorpej fi->fi_flags |= FI_SEL;
3699b48d494Suebayasi nselfiles++;
370adf6a455Suebayasi CFGDBG(3, "file selected `%s'", fi->fi_path);
371adf6a455Suebayasi
372adf6a455Suebayasi /* Add other files to the default "netbsd" attribute. */
373adf6a455Suebayasi if (fi->fi_attr == NULL) {
374adf6a455Suebayasi addfiletoattr(allattr.a_name, fi);
375adf6a455Suebayasi }
376fa3d8504Suebayasi CFGDBG(3, "file `%s' belongs to attr `%s'", fi->fi_path,
377fa3d8504Suebayasi fi->fi_attr->a_name);
3785ecc953bSthorpej }
3799b48d494Suebayasi
3809b48d494Suebayasi /* Order files. */
3819b48d494Suebayasi selfiles = malloc(nselfiles * sizeof(fi));
38282a183ddSuebayasi unsigned i = 0;
3839b48d494Suebayasi TAILQ_FOREACH(fi, &allfiles, fi_next) {
3849b48d494Suebayasi if ((fi->fi_flags & FI_SEL) == 0)
3859b48d494Suebayasi continue;
3869b48d494Suebayasi selfiles[i++] = fi;
3879b48d494Suebayasi }
388cea9d6a0Suebayasi assert(i <= nselfiles);
389cea9d6a0Suebayasi nselfiles = i;
3909b48d494Suebayasi qsort(selfiles, nselfiles, (unsigned)sizeof(fi), cmpfiles);
3915ecc953bSthorpej return (err);
3925ecc953bSthorpej }
3935ecc953bSthorpej
3945ecc953bSthorpej
3955ecc953bSthorpej /*
3965ecc953bSthorpej * We have finished reading everything. Tack the devsws down: calculate
3975ecc953bSthorpej * selection.
3985ecc953bSthorpej */
3995ecc953bSthorpej int
fixdevsw(void)4005ecc953bSthorpej fixdevsw(void)
4015ecc953bSthorpej {
4022f403ebeSalc int error;
4035ecc953bSthorpej struct devm *dm, *res;
4045ecc953bSthorpej struct hashtab *fixdevmtab;
4055ecc953bSthorpej char mstr[16];
4065ecc953bSthorpej
4072f403ebeSalc error = 0;
4085ecc953bSthorpej fixdevmtab = ht_new();
4095ecc953bSthorpej
4105ecc953bSthorpej TAILQ_FOREACH(dm, &alldevms, dm_next) {
4115ecc953bSthorpej res = ht_lookup(fixdevmtab, intern(dm->dm_name));
4125ecc953bSthorpej if (res != NULL) {
4135ecc953bSthorpej if (res->dm_cmajor != dm->dm_cmajor ||
4145ecc953bSthorpej res->dm_bmajor != dm->dm_bmajor) {
41520255392Schristos cfgxerror(res->dm_where.w_srcfile,
41620255392Schristos res->dm_where.w_srcline,
41782225543Sdsl "device-major '%s' "
41882225543Sdsl "block %d, char %d redefined"
41982225543Sdsl " at %s:%d as block %d, char %d",
42082225543Sdsl res->dm_name,
42182225543Sdsl res->dm_bmajor, res->dm_cmajor,
42220255392Schristos dm->dm_where.w_srcfile, dm->dm_where.w_srcline,
4235ecc953bSthorpej dm->dm_bmajor, dm->dm_cmajor);
4245ecc953bSthorpej } else {
42520255392Schristos cfgxerror(res->dm_where.w_srcfile,
42620255392Schristos res->dm_where.w_srcline,
42782225543Sdsl "device-major '%s' "
42882225543Sdsl "(block %d, char %d) duplicated"
42982225543Sdsl " at %s:%d",
4305ecc953bSthorpej dm->dm_name, dm->dm_bmajor,
43182225543Sdsl dm->dm_cmajor,
43220255392Schristos dm->dm_where.w_srcfile,
43320255392Schristos dm->dm_where.w_srcline);
43482225543Sdsl }
4352f403ebeSalc error = 1;
436c0156a49Schristos goto out;
4375ecc953bSthorpej }
4385ecc953bSthorpej if (ht_insert(fixdevmtab, intern(dm->dm_name), dm)) {
4395ecc953bSthorpej panic("fixdevsw: %s char %d block %d",
4405ecc953bSthorpej dm->dm_name, dm->dm_cmajor, dm->dm_bmajor);
4415ecc953bSthorpej }
4425ecc953bSthorpej
4435ecc953bSthorpej if (dm->dm_opts != NULL &&
4445ecc953bSthorpej !expr_eval(dm->dm_opts, fixsel, NULL))
4455ecc953bSthorpej continue;
4465ecc953bSthorpej
447d767912bSdrochner if (dm->dm_cmajor != NODEVMAJOR) {
4485ecc953bSthorpej if (ht_lookup(cdevmtab, intern(dm->dm_name)) != NULL) {
44920255392Schristos cfgxerror(dm->dm_where.w_srcfile,
45020255392Schristos dm->dm_where.w_srcline,
4515ecc953bSthorpej "device-major of character device '%s' "
4525ecc953bSthorpej "is already defined", dm->dm_name);
4532f403ebeSalc error = 1;
454c0156a49Schristos goto out;
4555ecc953bSthorpej }
4565ecc953bSthorpej (void)snprintf(mstr, sizeof(mstr), "%d", dm->dm_cmajor);
4575ecc953bSthorpej if (ht_lookup(cdevmtab, intern(mstr)) != NULL) {
45820255392Schristos cfgxerror(dm->dm_where.w_srcfile, dm->dm_where.w_srcline,
4595ecc953bSthorpej "device-major of character major '%d' "
4605ecc953bSthorpej "is already defined", dm->dm_cmajor);
4612f403ebeSalc error = 1;
462c0156a49Schristos goto out;
4635ecc953bSthorpej }
4645ecc953bSthorpej if (ht_insert(cdevmtab, intern(dm->dm_name), dm) ||
4655ecc953bSthorpej ht_insert(cdevmtab, intern(mstr), dm)) {
4665ecc953bSthorpej panic("fixdevsw: %s character major %d",
4675ecc953bSthorpej dm->dm_name, dm->dm_cmajor);
4685ecc953bSthorpej }
4695ecc953bSthorpej }
470d767912bSdrochner if (dm->dm_bmajor != NODEVMAJOR) {
4715ecc953bSthorpej if (ht_lookup(bdevmtab, intern(dm->dm_name)) != NULL) {
47220255392Schristos cfgxerror(dm->dm_where.w_srcfile, dm->dm_where.w_srcline,
4735ecc953bSthorpej "device-major of block device '%s' "
4745ecc953bSthorpej "is already defined", dm->dm_name);
4752f403ebeSalc error = 1;
476c0156a49Schristos goto out;
4775ecc953bSthorpej }
4785ecc953bSthorpej (void)snprintf(mstr, sizeof(mstr), "%d", dm->dm_bmajor);
4795ecc953bSthorpej if (ht_lookup(bdevmtab, intern(mstr)) != NULL) {
48020255392Schristos cfgxerror(dm->dm_where.w_srcfile, dm->dm_where.w_srcline,
4815ecc953bSthorpej "device-major of block major '%d' "
4825ecc953bSthorpej "is already defined", dm->dm_bmajor);
4832f403ebeSalc error = 1;
484c0156a49Schristos goto out;
4855ecc953bSthorpej }
4865ecc953bSthorpej if (ht_insert(bdevmtab, intern(dm->dm_name), dm) ||
4875ecc953bSthorpej ht_insert(bdevmtab, intern(mstr), dm)) {
4885ecc953bSthorpej panic("fixdevsw: %s block major %d",
4895ecc953bSthorpej dm->dm_name, dm->dm_bmajor);
4905ecc953bSthorpej }
4915ecc953bSthorpej }
4925ecc953bSthorpej }
4935ecc953bSthorpej
494c0156a49Schristos out:
495c0156a49Schristos ht_free(fixdevmtab);
4962f403ebeSalc return (error);
4975ecc953bSthorpej }
4985ecc953bSthorpej
4995ecc953bSthorpej /*
5005ecc953bSthorpej * Called when evaluating a needs-count expression. Make sure the
5015ecc953bSthorpej * atom is a countable device. The expression succeeds iff there
5025ecc953bSthorpej * is at least one of them (note that while `xx*' will not always
5035ecc953bSthorpej * set xx's d_umax > 0, you cannot mix '*' and needs-count). The
5045ecc953bSthorpej * mkheaders() routine wants a flattened, in-order list of the
5055ecc953bSthorpej * atoms for `#define name value' lines, so we build that as we
5065ecc953bSthorpej * are called to eval each atom.
5075ecc953bSthorpej */
5085ecc953bSthorpej static int
fixcount(const char * name,void * context)5095ecc953bSthorpej fixcount(const char *name, void *context)
5105ecc953bSthorpej {
5115ecc953bSthorpej struct nvlist ***p = context;
5125ecc953bSthorpej struct devbase *dev;
5135ecc953bSthorpej struct nvlist *nv;
5145ecc953bSthorpej
5155ecc953bSthorpej dev = ht_lookup(devbasetab, name);
5165ecc953bSthorpej if (dev == NULL) /* cannot occur here; we checked earlier */
5175ecc953bSthorpej panic("fixcount(%s)", name);
5185ecc953bSthorpej nv = newnv(name, NULL, NULL, dev->d_umax, NULL);
5195ecc953bSthorpej **p = nv;
5205ecc953bSthorpej *p = &nv->nv_next;
5215ecc953bSthorpej (void)ht_insert(needcnttab, name, nv);
5225ecc953bSthorpej return (dev->d_umax != 0);
5235ecc953bSthorpej }
5245ecc953bSthorpej
5255ecc953bSthorpej /*
5265ecc953bSthorpej * Called from fixfiles when eval'ing a selection expression for a
5275ecc953bSthorpej * file that will generate a .h with flags. We will need the flat list.
5285ecc953bSthorpej */
5295ecc953bSthorpej static int
fixfsel(const char * name,void * context)5305ecc953bSthorpej fixfsel(const char *name, void *context)
5315ecc953bSthorpej {
5325ecc953bSthorpej struct nvlist ***p = context;
5335ecc953bSthorpej struct nvlist *nv;
5345ecc953bSthorpej int sel;
5355ecc953bSthorpej
5365ecc953bSthorpej sel = ht_lookup(selecttab, name) != NULL;
5375ecc953bSthorpej nv = newnv(name, NULL, NULL, sel, NULL);
5385ecc953bSthorpej **p = nv;
5395ecc953bSthorpej *p = &nv->nv_next;
5405ecc953bSthorpej return (sel);
5415ecc953bSthorpej }
5425ecc953bSthorpej
5435ecc953bSthorpej /*
5445ecc953bSthorpej * As for fixfsel above, but we do not need the flat list.
5455ecc953bSthorpej */
5465ecc953bSthorpej static int
547c7295a4cSchristos /*ARGSUSED*/
fixsel(const char * name,void * context)5485ecc953bSthorpej fixsel(const char *name, void *context)
5495ecc953bSthorpej {
5505ecc953bSthorpej
5515ecc953bSthorpej return (ht_lookup(selecttab, name) != NULL);
5525ecc953bSthorpej }
5535ecc953bSthorpej
5545ecc953bSthorpej /*
5555ecc953bSthorpej * Eval an expression tree. Calls the given function on each node,
5565ecc953bSthorpej * passing it the given context & the name; return value is &/|/! of
5575ecc953bSthorpej * results of evaluating atoms.
5585ecc953bSthorpej *
5595ecc953bSthorpej * No short circuiting ever occurs. fn must return 0 or 1 (otherwise
5605ecc953bSthorpej * our mixing of C's bitwise & boolean here may give surprises).
5615ecc953bSthorpej */
562a16a6365Scube int
expr_eval(struct condexpr * expr,int (* fn)(const char *,void *),void * ctx)563a551c5e8Sdholland expr_eval(struct condexpr *expr, int (*fn)(const char *, void *), void *ctx)
5645ecc953bSthorpej {
5655ecc953bSthorpej int lhs, rhs;
5665ecc953bSthorpej
567a551c5e8Sdholland switch (expr->cx_type) {
5685ecc953bSthorpej
569a551c5e8Sdholland case CX_ATOM:
570a551c5e8Sdholland return ((*fn)(expr->cx_atom, ctx));
5715ecc953bSthorpej
572a551c5e8Sdholland case CX_NOT:
573a551c5e8Sdholland return (!expr_eval(expr->cx_not, fn, ctx));
5745ecc953bSthorpej
575a551c5e8Sdholland case CX_AND:
576a551c5e8Sdholland lhs = expr_eval(expr->cx_and.left, fn, ctx);
577a551c5e8Sdholland rhs = expr_eval(expr->cx_and.right, fn, ctx);
5785ecc953bSthorpej return (lhs & rhs);
5795ecc953bSthorpej
580a551c5e8Sdholland case CX_OR:
581a551c5e8Sdholland lhs = expr_eval(expr->cx_or.left, fn, ctx);
582a551c5e8Sdholland rhs = expr_eval(expr->cx_or.right, fn, ctx);
5835ecc953bSthorpej return (lhs | rhs);
5845ecc953bSthorpej }
585a551c5e8Sdholland panic("invalid condexpr type %d", (int)expr->cx_type);
5865ecc953bSthorpej /* NOTREACHED */
5875ecc953bSthorpej return (0);
5885ecc953bSthorpej }
5895ecc953bSthorpej
5905ecc953bSthorpej #ifdef DEBUG
5915ecc953bSthorpej /*
5925ecc953bSthorpej * Print expression tree.
5935ecc953bSthorpej */
5945ecc953bSthorpej void
prexpr(struct nvlist * expr)5955ecc953bSthorpej prexpr(struct nvlist *expr)
5965ecc953bSthorpej {
5975ecc953bSthorpej static void pr0();
5985ecc953bSthorpej
5995ecc953bSthorpej printf("expr =");
6005ecc953bSthorpej pr0(expr);
6015ecc953bSthorpej printf("\n");
6025ecc953bSthorpej (void)fflush(stdout);
6035ecc953bSthorpej }
6045ecc953bSthorpej
6055ecc953bSthorpej static void
pr0(struct nvlist * e)6065ecc953bSthorpej pr0(struct nvlist *e)
6075ecc953bSthorpej {
6085ecc953bSthorpej
6090001b928Schristos switch (e->nv_num) {
6105ecc953bSthorpej case FX_ATOM:
6115ecc953bSthorpej printf(" %s", e->nv_name);
6125ecc953bSthorpej return;
6135ecc953bSthorpej case FX_NOT:
6145ecc953bSthorpej printf(" (!");
6155ecc953bSthorpej break;
6165ecc953bSthorpej case FX_AND:
6175ecc953bSthorpej printf(" (&");
6185ecc953bSthorpej break;
6195ecc953bSthorpej case FX_OR:
6205ecc953bSthorpej printf(" (|");
6215ecc953bSthorpej break;
6225ecc953bSthorpej default:
6230001b928Schristos printf(" (?%lld?", e->nv_num);
6245ecc953bSthorpej break;
6255ecc953bSthorpej }
6265ecc953bSthorpej if (e->nv_ptr)
6275ecc953bSthorpej pr0(e->nv_ptr);
6285ecc953bSthorpej pr0(e->nv_next);
6295ecc953bSthorpej printf(")");
6305ecc953bSthorpej }
6315ecc953bSthorpej #endif
632