📄 sem.c
字号:
} dev = ht_lookup(devbasetab, intern(buf)); if (dev == NULL || dev->d_major == NODEV) { error("%s: can't make %s device from `%s'", name, what, nv->nv_str); return (1); } nv->nv_name = dev->d_name; nv->nv_int = makedev(dev->d_major, unit * 16 + part); return (0);}static intlresolve(nvp, name, what, dflt, part) register struct nvlist **nvp; const char *name, *what; struct nvlist *dflt; int part;{ int err; while ((err = resolve(nvp, name, what, dflt, part)) == 0 && (*nvp)->nv_next != NULL) nvp = &(*nvp)->nv_next; return (err);}/* * Add a completed configuration to the list. */voidaddconf(cf0) register struct config *cf0;{ register struct config *cf; register struct nvlist *nv; const char *name; name = cf0->cf_name; cf = emalloc(sizeof *cf); if (ht_insert(cfhashtab, name, cf)) { error("configuration `%s' already defined", name); free(cf); goto bad; } *cf = *cf0; *nextcf = cf; nextcf = &cf->cf_next; return;bad: nvfreel(cf0->cf_root); nvfreel(cf0->cf_swap); nvfreel(cf0->cf_dump);}voidsetconf(npp, what, v) register struct nvlist **npp; const char *what; struct nvlist *v;{ if (*npp != NULL) { error("duplicate %s specification", what); nvfreel(v); } else *npp = v;}static struct devi *newdevi(name, unit, d) const char *name; int unit; struct devbase *d;{ register struct devi *i; i = emalloc(sizeof *i); i->i_name = name; i->i_unit = unit; i->i_base = d; i->i_next = NULL; i->i_bsame = NULL; i->i_asame = NULL; i->i_alias = NULL; i->i_at = NULL; i->i_atattr = NULL; i->i_atdev = NULL; i->i_atdeva = NULL; i->i_locs = NULL; i->i_cfflags = 0; i->i_cfindex = -1; i->i_lineno = currentline(); if (unit >= d->d_umax) d->d_umax = unit + 1; return (i);}/* * Enable an already declared but disabled device. */voidenabledev(name, at) const char *name, *at;{ struct devbase *ib, *ab; char atbuf[NAMESIZE]; struct attr *attr; struct nvlist *nv; struct devi *i; const char *cp; int atunit; i = ht_lookup(devitab, name); if (i == NULL) { error("invalid device `%s'", name); return; } ib = i->i_base; if (split(at, strlen(at), atbuf, sizeof atbuf, &atunit)) { error("invalid attachment name `%s'", at); return; } cp = intern(atbuf); ab = ht_lookup(devbasetab, cp); if (ab == NULL) { error("invalid attachment device `%s'", cp); return; } for (nv = ab->d_attrs; nv != NULL; nv = nv->nv_next) { attr = nv->nv_ptr; if (onlist(attr->a_devs, ib)) goto foundattachment; } error("%s's cannot attach to %s's", ib->d_name, atbuf); return;foundattachment: while (i && i->i_atdev != ab) i = i->i_alias; if (i == NULL) { error("%s at %s not found", name, at); return; } else i->i_disable = 0; /* Enable */}/* * Add the named device as attaching to the named attribute (or perhaps * another device instead) plus unit number. */voidadddev(name, at, loclist, flags, disable) const char *name, *at; struct nvlist *loclist; int flags, disable;{ register struct devi *i; /* the new instance */ register struct attr *attr; /* attribute that allows attach */ register struct devbase *ib; /* i->i_base */ register struct devbase *ab; /* not NULL => at another dev */ register struct nvlist *nv; register struct deva *iba; /* devbase attachment used */ const char *cp; int atunit; char atbuf[NAMESIZE]; int hit; ab = NULL; iba = NULL; if (at == NULL) { /* "at root" */ if ((i = getdevi(name)) == NULL) goto bad; /* * Must warn about i_unit > 0 later, after taking care of * the STAR cases (we could do non-star's here but why * bother?). Make sure this device can be at root. */ ib = i->i_base; hit = 0; for (iba = ib->d_ahead; iba != NULL; iba = iba->d_bsame) if (onlist(iba->d_atlist, NULL)) { hit = 1; break; } if (!hit) { error("%s's cannot attach to the root", ib->d_name); goto bad; } attr = &errattr; /* a convenient "empty" attr */ } else { if (split(at, strlen(at), atbuf, sizeof atbuf, &atunit)) { error("invalid attachment name `%s'", at); /* (void)getdevi(name); -- ??? */ goto bad; } if ((i = getdevi(name)) == NULL) goto bad; ib = i->i_base; cp = intern(atbuf); /* * Devices can attach to two types of things: Attributes, * and other devices (which have the appropriate attributes * to allow attachment). * * (1) If we're attached to an attribute, then we don't need * look at the parent base device to see what attributes * it has, and make sure that we can attach to them. * * (2) If we're attached to a real device (i.e. named in * the config file), we want to remember that so that * at cross-check time, if the device we're attached to * is missing but other devices which also provide the * attribute are present, we don't get a false "OK." * * (3) If the thing we're attached to is an attribute * but is actually named in the config file, we still * have to remember its devbase. */ /* Figure out parent's devbase, to satisfy case (3). */ ab = ht_lookup(devbasetab, cp); /* Find out if it's an attribute. */ attr = ht_lookup(attrtab, cp); /* Make sure we're _really_ attached to the attr. Case (1). */ if (attr != NULL && onlist(attr->a_devs, ib)) goto findattachment; /* * Else a real device, and not just an attribute. Case (2). * * Have to work a bit harder to see whether we have * something like "tg0 at esp0" (where esp is merely * not an attribute) or "tg0 at nonesuch0" (where * nonesuch is not even a device). */ if (ab == NULL) { error("%s at %s: `%s' unknown", name, at, atbuf); goto bad; } /* * See if the named parent carries an attribute * that allows it to supervise device ib. */ for (nv = ab->d_attrs; nv != NULL; nv = nv->nv_next) { attr = nv->nv_ptr; if (onlist(attr->a_devs, ib)) goto findattachment; } error("%s's cannot attach to %s's", ib->d_name, atbuf); goto bad;findattachment: /* find out which attachment it uses */ hit = 0; for (iba = ib->d_ahead; iba != NULL; iba = iba->d_bsame) if (onlist(iba->d_atlist, attr)) { hit = 1; break; } if (!hit) panic("adddev: can't figure out attachment"); } if ((i->i_locs = fixloc(name, attr, loclist)) == NULL) goto bad; i->i_at = at; i->i_atattr = attr; i->i_atdev = ab; i->i_atdeva = iba; i->i_atunit = atunit; i->i_cfflags = flags; i->i_disable = disable; *iba->d_ipp = i; iba->d_ipp = &i->i_asame; selectbase(ib, iba); /* all done, fall into ... */bad: nvfreel(loclist); return;}voidaddpseudo(name, number) const char *name; int number;{ register struct devbase *d; register struct devi *i; d = ht_lookup(devbasetab, name); if (d == NULL) { error("undefined pseudo-device %s", name); return; } if (!d->d_ispseudo) { error("%s is a real device, not a pseudo-device", name); return; } if (ht_lookup(devitab, name) != NULL) { fprintf(stderr, "warning: duplicate definition of `%s', will use latest definition", name); d->d_umax = number; return; } i = newdevi(name, number - 1, d); /* foo 16 => "foo0..foo15" */ if (ht_insert(devitab, name, i)) panic("addpseudo(%s)", name); selectbase(d, NULL); *nextpseudo = i; nextpseudo = &i->i_next; npseudo++;}/* * Define a new instance of a specific device. */static struct devi *getdevi(name) const char *name;{ register struct devi *i, *firsti; register struct devbase *d; int unit; char base[NAMESIZE]; if (split(name, strlen(name), base, sizeof base, &unit)) { error("invalid device name `%s'", name); return (NULL); } d = ht_lookup(devbasetab, intern(base)); if (d == NULL) { error("%s: unknown device `%s'", name, base); return (NULL); } if (d->d_ispseudo) { error("%s: %s is a pseudo-device", name, base); return (NULL); } firsti = ht_lookup(devitab, name); i = newdevi(name, unit, d); if (firsti == NULL) { if (ht_insert(devitab, name, i)) panic("getdevi(%s)", name); *d->d_ipp = i; d->d_ipp = &i->i_bsame; } else { while (firsti->i_alias) firsti = firsti->i_alias; firsti->i_alias = i; } *nextdevi = i; nextdevi = &i->i_next; ndevi++; return (i);}static const char *concat(name, c) const char *name; int c;{ size_t len; char buf[NAMESIZE]; len = strlen(name); if (len + 2 > sizeof(buf)) { error("device name `%s%c' too long", name, c); len = sizeof(buf) - 2; } bcopy(name, buf, len); buf[len] = c; buf[len + 1] = 0; return (intern(buf));}const char *starref(name) const char *name;{ return (concat(name, '*'));}const char *wildref(name) const char *name;{ return (concat(name, '?'));}/* * Split a name like "foo0" into base name (foo) and unit number (0). * Return 0 on success. To make this useful for names like "foo0a", * the length of the "foo0" part is one of the arguments. */static intsplit(name, nlen, base, bsize, aunit) register const char *name; size_t nlen; char *base; size_t bsize; int *aunit;{ register const char *cp; register int c; size_t l; l = nlen; if (l < 2 || l >= bsize || isdigit(*name)) return (1); c = (u_char)name[--l]; if (!isdigit(c)) { if (c == '*') *aunit = STAR; else if (c == '?') *aunit = WILD; else return (1); } else { cp = &name[l]; while (isdigit(cp[-1])) l--, cp--; *aunit = atoi(cp); } bcopy(name, base, l); base[l] = 0; return (0);}/* * We have an instance of the base foo, so select it and all its * attributes for "optional foo". */static voidselectbase(d, da) register struct devbase *d; register struct deva *da;{ register struct attr *a; register struct nvlist *nv; (void)ht_insert(selecttab, d->d_name, (char *)d->d_name); for (nv = d->d_attrs; nv != NULL; nv = nv->nv_next) { a = nv->nv_ptr; (void)ht_insert(selecttab, a->a_name, (char *)a->a_name); } if (da != NULL) { (void)ht_insert(selecttab, da->d_name, (char *)da->d_name); for (nv = da->d_attrs; nv != NULL; nv = nv->nv_next) { a = nv->nv_ptr; (void)ht_insert(selecttab, a->a_name, (char *)a->a_name); } }}/* * Is the given pointer on the given list of pointers? */static intonlist(nv, ptr) register struct nvlist *nv; register void *ptr;{ for (; nv != NULL; nv = nv->nv_next) if (nv->nv_ptr == ptr) return (1); return (0);}static char *extend(p, name) register char *p; const char *name;{ register int l; l = strlen(name); bcopy(name, p, l); p += l; *p++ = ','; *p++ = ' '; return (p);}/* * Check that we got all required locators, and default any that are * given as "?" and have defaults. Return 0 on success. */static const char **fixloc(name, attr, got) const char *name; register struct attr *attr; register struct nvlist *got;{ register struct nvlist *m, *n; register int ord; register const char **lp; int nmissing, nextra, nnodefault; char *mp, *ep, *ndp; char missing[1000], extra[1000], nodefault[1000]; static const char *nullvec[1]; /* * Look for all required locators, and number the given ones * according to the required order. While we are numbering, * set default values for defaulted locators. */ if (attr->a_loclen == 0) /* e.g., "at root" */ lp = nullvec; else lp = emalloc((attr->a_loclen + 1) * sizeof(const char *)); for (n = got; n != NULL; n = n->nv_next) n->nv_int = -1; nmissing = 0; mp = missing; /* yes, this is O(mn), but m and n should be small */ for (ord = 0, m = attr->a_locs; m != NULL; m = m->nv_next, ord++) { for (n = got; n != NULL; n = n->nv_next) { if (n->nv_name == m->nv_name) { n->nv_int = ord; break; } } if (n == NULL && m->nv_int == 0) { nmissing++; mp = extend(mp, m->nv_name); } lp[ord] = m->nv_str; } if (ord != attr->a_loclen) panic("fixloc"); lp[ord] = NULL; nextra = 0; ep = extra; nnodefault = 0; ndp = nodefault; for (n = got; n != NULL; n = n->nv_next) { if (n->nv_int >= 0) { if (n->nv_str != NULL) lp[n->nv_int] = n->nv_str; else if (lp[n->nv_int] == NULL) { nnodefault++; ndp = extend(ndp, n->nv_name); } } else { nextra++; ep = extend(ep, n->nv_name); } } if (nextra) { ep[-2] = 0; /* kill ", " */ error("%s: extraneous locator%s: %s", name, nextra > 1 ? "s" : "", extra); } if (nmissing) { mp[-2] = 0; error("%s: must specify %s", name, missing); } if (nnodefault) { ndp[-2] = 0; error("%s: cannot wildcard %s", name, nodefault); } if (nmissing || nnodefault) { free(lp); lp = NULL; } return (lp);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -