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