Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.sbin/config Add support for specifiying attribute depend...



details:   https://anonhg.NetBSD.org/src/rev/a0397c431b52
branches:  trunk
changeset: 538005:a0397c431b52
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Wed Oct 09 20:17:00 2002 +0000

description:
Add support for specifiying attribute dependencies on attributes.  This
allows for the following:

define foo
define bar { }: foo

device foobar: bar

An instance of "foobar" will select "bar", which will in turn select
"foo" due to "bar"'s dependency on "foo".

Circular dependencies are not allowed, and a dependency may also not
be an interface attribute.

diffstat:

 usr.sbin/config/defs.h |   4 +-
 usr.sbin/config/gram.y |   7 ++-
 usr.sbin/config/sem.c  |  79 ++++++++++++++++++++++++++++++++++++++++++++-----
 usr.sbin/config/sem.h  |   5 +-
 4 files changed, 81 insertions(+), 14 deletions(-)

diffs (210 lines):

diff -r 5f7df4c06f55 -r a0397c431b52 usr.sbin/config/defs.h
--- a/usr.sbin/config/defs.h    Wed Oct 09 19:58:35 2002 +0000
+++ b/usr.sbin/config/defs.h    Wed Oct 09 20:17:00 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: defs.h,v 1.7 2002/09/26 04:07:36 thorpej Exp $ */
+/*     $NetBSD: defs.h,v 1.8 2002/10/09 20:17:00 thorpej Exp $ */
 
 /*
  * Copyright (c) 1992, 1993
@@ -153,6 +153,8 @@
        int     a_loclen;               /* length of above list */
        struct  nvlist *a_devs;         /* children */
        struct  nvlist *a_refs;         /* parents */
+       struct  nvlist *a_deps;         /* we depend on these other attrs */
+       int     a_expanding;            /* to detect cycles in attr graph */
 };
 
 /*
diff -r 5f7df4c06f55 -r a0397c431b52 usr.sbin/config/gram.y
--- a/usr.sbin/config/gram.y    Wed Oct 09 19:58:35 2002 +0000
+++ b/usr.sbin/config/gram.y    Wed Oct 09 20:17:00 2002 +0000
@@ -1,5 +1,5 @@
 %{
-/*     $NetBSD: gram.y,v 1.36 2002/09/11 06:20:09 enami Exp $  */
+/*     $NetBSD: gram.y,v 1.37 2002/10/09 20:17:00 thorpej Exp $        */
 
 /*
  * Copyright (c) 1992, 1993
@@ -266,9 +266,10 @@
        device_major                    { do_devsw = 1; } |
        include |
        prefix |
-       DEVCLASS WORD                   { (void)defattr($2, NULL, 1); } |
+       DEVCLASS WORD                   { (void)defattr($2, NULL, NULL, 1); } |
        DEFFS fsoptfile_opt deffses     { deffilesystem($2, $3); } |
-       DEFINE WORD interface_opt       { (void)defattr($2, $3, 0); } |
+       DEFINE WORD interface_opt attrs_opt
+                                       { (void)defattr($2, $3, $4, 0); } |
        DEFOPT optfile_opt defopts defoptdeps
                                        { defoption($2, $3, $4); } |
        DEFFLAG optfile_opt defopts defoptdeps
diff -r 5f7df4c06f55 -r a0397c431b52 usr.sbin/config/sem.c
--- a/usr.sbin/config/sem.c     Wed Oct 09 19:58:35 2002 +0000
+++ b/usr.sbin/config/sem.c     Wed Oct 09 20:17:00 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sem.c,v 1.33 2002/09/26 04:07:36 thorpej Exp $ */
+/*     $NetBSD: sem.c,v 1.34 2002/10/09 20:17:00 thorpej Exp $ */
 
 /*
  * Copyright (c) 1992, 1993
@@ -180,20 +180,41 @@
 }
 
 /*
- * Define an attribute, optionally with an interface (a locator list).
+ * Define an attribute, optionally with an interface (a locator list)
+ * and a set of attribute-dependencies.
+ *
+ * Attribute dependencies MAY NOT be interface attributes.
+ *
  * Since an empty locator list is logically different from "no interface",
  * all locator lists include a dummy head node, which we discard here.
  */
 int
-defattr(const char *name, struct nvlist *locs, int devclass)
+defattr(const char *name, struct nvlist *locs, struct nvlist *deps,
+    int devclass)
 {
-       struct attr *a;
+       struct attr *a, *dep;
        struct nvlist *nv;
        int len;
 
        if (locs != NULL && devclass)
                panic("defattr(%s): locators and devclass", name);
 
+       if (deps != NULL && devclass)
+               panic("defattr(%s): dependencies and devclass", name);
+
+       /*
+        * If this attribute depends on any others, make sure none of
+        * the dependencies are interface attributes.
+        */
+       for (nv = deps; nv != NULL; nv = nv->nv_next) {
+               dep = nv->nv_ptr;
+               if (dep->a_iattr) {
+                       error("`%s' dependency `%s' is an interface attribute",
+                           name, dep->a_name);
+                       return (1);
+               }
+       }
+
        a = emalloc(sizeof *a);
        if (ht_insert(attrtab, name, a)) {
                free(a);
@@ -235,6 +256,12 @@
        a->a_loclen = len;
        a->a_devs = NULL;
        a->a_refs = NULL;
+       a->a_deps = deps;
+       a->a_expanding = 0;
+
+       /* Expand the attribute to check for cycles in the graph. */
+       expandattr(a, NULL);
+
        return (0);
 }
 
@@ -315,7 +342,7 @@
        if (loclist != NULL) {
                nv = loclist;
                loclist = NULL; /* defattr disposes of them for us */
-               if (defattr(dev->d_name, nv, 0))
+               if (defattr(dev->d_name, nv, NULL, 0))
                        goto bad;
                attrs = newnv(dev->d_name, NULL, getattr(dev->d_name), 0,
                    attrs);
@@ -540,6 +567,36 @@
 }
 
 /*
+ * Recursively expand an attribute and its dependencies, checking for
+ * cycles, and invoking a callback for each attribute found.
+ */
+void
+expandattr(struct attr *a, void (*callback)(struct attr *))
+{
+       struct nvlist *nv;
+       struct attr *dep;
+
+       if (a->a_expanding) {
+               error("circular dependency on attribute `%s'", a->a_name);
+               return;
+       }
+
+       a->a_expanding = 1;
+
+       /* First expand all of this attribute's dependencies. */
+       for (nv = a->a_deps; nv != NULL; nv = nv->nv_next) {
+               dep = nv->nv_ptr;
+               expandattr(dep, callback);
+       }
+
+       /* ...and now invoke the callback for ourself. */
+       if (callback != NULL)
+               (*callback)(a);
+
+       a->a_expanding = 0;
+}
+
+/*
  * Set the major device number for a device, so that it can be used
  * as a root/dumps "on" device in a configuration.
  */
@@ -1230,6 +1287,13 @@
        return (0);
 }
 
+static void
+selectattr(struct attr *a)
+{
+
+       (void)ht_insert(selecttab, a->a_name, (char *)a->a_name);
+}
+
 /*
  * We have an instance of the base foo, so select it and all its
  * attributes for "optional foo".
@@ -1243,14 +1307,13 @@
        (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);
+               expandattr(a, selectattr);
        }
        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);
+                       expandattr(a, selectattr);
                }
        }
 }
diff -r 5f7df4c06f55 -r a0397c431b52 usr.sbin/config/sem.h
--- a/usr.sbin/config/sem.h     Wed Oct 09 19:58:35 2002 +0000
+++ b/usr.sbin/config/sem.h     Wed Oct 09 20:17:00 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sem.h,v 1.15 2002/09/06 13:18:43 gehenna Exp $ */
+/*     $NetBSD: sem.h,v 1.16 2002/10/09 20:17:00 thorpej Exp $ */
 
 /*
  * Copyright (c) 1992, 1993
@@ -49,13 +49,14 @@
 void           setdefmaxusers(int, int, int);
 void           setmaxusers(int);
 void           setident(const char *);
-int            defattr(const char *, struct nvlist *, int);
+int            defattr(const char *, struct nvlist *, struct nvlist *, int);
 void           defdev(struct devbase *, struct nvlist *, struct nvlist *, int);
 void           defdevattach(struct deva *, struct devbase *, struct nvlist *,
                             struct nvlist *);
 struct devbase *getdevbase(const char *);
 struct deva    *getdevattach(const char *);
 struct attr    *getattr(const char *);
+void           expandattr(struct attr *, void (*)(struct attr *));
 void           setmajor(struct devbase *, int);
 void           addconf(struct config *);
 void           setconf(struct nvlist **, const char *, struct nvlist *);



Home | Main Index | Thread Index | Old Index