Module Name:    src
Committed By:   dholland
Date:           Sun Mar 11 07:32:41 UTC 2012

Modified Files:
        src/usr.bin/config: defs.h gram.y lint.c main.c mkioconf.c sem.c sem.h
            util.c

Log Message:
Create a new type struct attrlist to manage lists of attributes,
instead of using struct nvlist.

(struct nvlist holds lists (or trees!) of semi-arbitrary stuff with no
structure and almost no type safety; it should go away.)


To generate a diff of this commit:
cvs rdiff -u -r1.37 -r1.38 src/usr.bin/config/defs.h
cvs rdiff -u -r1.31 -r1.32 src/usr.bin/config/gram.y
cvs rdiff -u -r1.8 -r1.9 src/usr.bin/config/lint.c
cvs rdiff -u -r1.43 -r1.44 src/usr.bin/config/main.c
cvs rdiff -u -r1.19 -r1.20 src/usr.bin/config/mkioconf.c
cvs rdiff -u -r1.38 -r1.39 src/usr.bin/config/sem.c
cvs rdiff -u -r1.7 -r1.8 src/usr.bin/config/sem.h
cvs rdiff -u -r1.9 -r1.10 src/usr.bin/config/util.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/config/defs.h
diff -u src/usr.bin/config/defs.h:1.37 src/usr.bin/config/defs.h:1.38
--- src/usr.bin/config/defs.h:1.37	Sun Mar 11 05:31:37 2012
+++ src/usr.bin/config/defs.h	Sun Mar 11 07:32:41 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: defs.h,v 1.37 2012/03/11 05:31:37 dholland Exp $	*/
+/*	$NetBSD: defs.h,v 1.38 2012/03/11 07:32:41 dholland Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -161,11 +161,19 @@ struct attr {
 	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 */
+	struct	attrlist *a_deps;	/* we depend on these other attrs */
 	int	a_expanding;		/* to detect cycles in attr graph */
 };
 
 /*
+ * List of attributes.
+ */
+struct attrlist {
+	struct attrlist *al_next;
+	struct attr *al_this;
+};
+
+/*
  * Parent specification.  Multiple device instances may share a
  * given parent spec.  Parent specs are emitted only if there are
  * device instances which actually reference it.
@@ -209,7 +217,7 @@ struct devbase {
 	int	d_isdef;		/* set once properly defined */
 	int	d_ispseudo;		/* is a pseudo-device */
 	devmajor_t d_major;		/* used for "root on sd0", e.g. */
-	struct	nvlist *d_attrs;	/* attributes, if any */
+	struct	attrlist *d_attrs;	/* attributes, if any */
 	int	d_umax;			/* highest unit number + 1 */
 	struct	devi *d_ihead;		/* first instance, if any */
 	struct	devi **d_ipp;		/* used for tacking on more instances */
@@ -225,7 +233,7 @@ struct deva {
 	int	d_isdef;		/* set once properly defined */
 	struct	devbase *d_devbase;	/* the base device */
 	struct	nvlist *d_atlist;	/* e.g., "at tg" (attr list) */
-	struct	nvlist *d_attrs;	/* attributes, if any */
+	struct	attrlist *d_attrs;	/* attributes, if any */
 	struct	devi *d_ihead;		/* first instance, if any */
 	struct	devi **d_ipp;		/* used for tacking on more instances */
 };
@@ -572,6 +580,10 @@ void	nvfree(struct nvlist *);
 void	nvfreel(struct nvlist *);
 struct nvlist *nvcat(struct nvlist *, struct nvlist *);
 void	autogen_comment(FILE *, const char *);
+struct attrlist *attrlist_create(void);
+struct attrlist *attrlist_cons(struct attrlist *, struct attr *);
+void attrlist_destroy(struct attrlist *);
+void attrlist_destroyall(struct attrlist *);
 
 /* liby */
 void	yyerror(const char *);

Index: src/usr.bin/config/gram.y
diff -u src/usr.bin/config/gram.y:1.31 src/usr.bin/config/gram.y:1.32
--- src/usr.bin/config/gram.y:1.31	Sun Mar 11 07:27:02 2012
+++ src/usr.bin/config/gram.y	Sun Mar 11 07:32:41 2012
@@ -1,5 +1,5 @@
 %{
-/*	$NetBSD: gram.y,v 1.31 2012/03/11 07:27:02 dholland Exp $	*/
+/*	$NetBSD: gram.y,v 1.32 2012/03/11 07:32:41 dholland Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -70,6 +70,7 @@ static void wrap_cleanup(void);
  * Allocation wrapper type codes
  */
 #define WRAP_CODE_nvlist	1
+#define WRAP_CODE_attrlist	2
 
 /*
  * The allocation wrappers themselves
@@ -77,11 +78,13 @@ static void wrap_cleanup(void);
 #define DECL_ALLOCWRAP(t)	static struct t *wrap_mk_##t(struct t *arg)
 
 DECL_ALLOCWRAP(nvlist);
+DECL_ALLOCWRAP(attrlist);
 
 /*
  * Macros for allocating new objects
  */
 
+/* old-style for struct nvlist */
 #define	new0(n,s,p,i,x)	wrap_mk_nvlist(newnv(n, s, p, i, x))
 #define	new_n(n)	new0(n, NULL, NULL, 0, NULL)
 #define	new_nx(n, x)	new0(n, NULL, NULL, 0, x)
@@ -101,6 +104,17 @@ DECL_ALLOCWRAP(nvlist);
 #define	fx_and(e1, e2)	new0(NULL, NULL, e1, FX_AND, e2)
 #define	fx_or(e1, e2)	new0(NULL, NULL, e1, FX_OR, e2)
 
+/* new style, type-polymorphic */
+#define MK0(t)		wrap_mk_##t(mk_##t())
+#define MK1(t, a0)	wrap_mk_##t(mk_##t(a0))
+#define MK2(t, a0, a1)	wrap_mk_##t(mk_##t(a0, a1))
+
+/*
+ * Data constructors
+ */
+
+static struct attrlist *mk_attrlist(struct attrlist *, struct attr *);
+
 /*
  * Other private functions
  */
@@ -120,6 +134,7 @@ static	struct nvlist *mk_ns(const char *
 	struct	devbase *devb;
 	struct	deva *deva;
 	struct	nvlist *list;
+	struct attrlist *attrlist;
 	const char *str;
 	struct	numconst num;
 	int64_t	val;
@@ -160,7 +175,7 @@ static	struct nvlist *mk_ns(const char *
 %type	<list>	loclist locdef
 %type	<str>	locdefault
 %type	<list>	values locdefaults
-%type	<list>	attrs_opt attrs
+%type	<attrlist>	attrs_opt attrs
 %type	<list>	locators locator
 %type	<list>	dev_spec
 %type	<str>	device_instance
@@ -472,8 +487,8 @@ attrs_opt:
 
 /* one or more attributes */
 attrs:
-	  attr				{ $$ = new_p($1); }
-	| attrs ',' attr		{ $$ = new_px($3, $1); }
+	  attr				{ $$ = MK2(attrlist, NULL, $1); }
+	| attrs ',' attr		{ $$ = MK2(attrlist, $1, $3); }
 ;
 
 /* one attribute */
@@ -935,11 +950,25 @@ wrap_cleanup(void)
 		    case WRAP_CODE_nvlist:
 			nvfree(wrapstack[i].ptr);
 			break;
+		    case WRAP_CODE_attrlist:
+			{
+				struct attrlist *al = wrapstack[i].ptr;
+
+				/*
+				 * Contents got wrapped separately;
+				 * just blank it out to destroy.
+				 */
+				al->al_next = NULL;
+				al->al_this = NULL;
+				attrlist_destroy(al);
+			}
+			break;
 		    default:
 			panic("invalid code %u on allocation wrapper stack",
 			      wrapstack[i].typecode);
 		}
 	}
+
 	wrap_depth = 0;
 }
 
@@ -959,6 +988,19 @@ wrap_cleanup(void)
 	}
 
 DEF_ALLOCWRAP(nvlist);
+DEF_ALLOCWRAP(attrlist);
+
+/************************************************************/
+
+/*
+ * Data constructors
+ */
+
+static struct attrlist *
+mk_attrlist(struct attrlist *next, struct attr *a)
+{
+	return attrlist_cons(next, a);
+}
 
 /************************************************************/
 

Index: src/usr.bin/config/lint.c
diff -u src/usr.bin/config/lint.c:1.8 src/usr.bin/config/lint.c:1.9
--- src/usr.bin/config/lint.c:1.8	Sun Aug 30 21:07:41 2009
+++ src/usr.bin/config/lint.c	Sun Mar 11 07:32:41 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: lint.c,v 1.8 2009/08/30 21:07:41 cube Exp $	*/
+/*	$NetBSD: lint.c,v 1.9 2012/03/11 07:32:41 dholland Exp $	*/
 
 /*
  *  Copyright (c) 2007 The NetBSD Foundation.
@@ -102,6 +102,7 @@ static void
 do_emit_instances(struct devbase *d, struct attr *at)
 {
 	struct nvlist *nv, *nv1;
+	struct attrlist *al;
 	struct attr *a;
 	struct deva *da;
 
@@ -142,8 +143,8 @@ do_emit_instances(struct devbase *d, str
 	 * Children attachments are found the same way as in the orphan
 	 * detection code in main.c.
 	 */
-	for (nv = d->d_attrs; nv != NULL; nv = nv->nv_next) {
-		a = nv->nv_ptr;
+	for (al = d->d_attrs; al != NULL; al = al->al_next) {
+		a = al->al_this;
 		for (nv1 = a->a_devs; nv1 != NULL; nv1 = nv1->nv_next)
 			do_emit_instances(nv1->nv_ptr, a);
 	}

Index: src/usr.bin/config/main.c
diff -u src/usr.bin/config/main.c:1.43 src/usr.bin/config/main.c:1.44
--- src/usr.bin/config/main.c:1.43	Sat Jul  9 08:01:58 2011
+++ src/usr.bin/config/main.c	Sun Mar 11 07:32:41 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: main.c,v 1.43 2011/07/09 08:01:58 matt Exp $	*/
+/*	$NetBSD: main.c,v 1.44 2012/03/11 07:32:41 dholland Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -1589,7 +1589,8 @@ static void
 do_kill_orphans(struct devbase *d, struct attr *at, struct devbase *parent,
     int state)
 {
-	struct nvlist *nv, *nv1;
+	struct nvlist *nv1;
+	struct attrlist *al;
 	struct attr *a;
 	struct devi *i, *j = NULL;
 	struct pspec *p;
@@ -1677,8 +1678,8 @@ do_kill_orphans(struct devbase *d, struc
 		}
 	}
 
-	for (nv = d->d_attrs; nv != NULL; nv = nv->nv_next) {
-		a = nv->nv_ptr;
+	for (al = d->d_attrs; al != NULL; al = al->al_next) {
+		a = al->al_this;
 		for (nv1 = a->a_devs; nv1 != NULL; nv1 = nv1->nv_next)
 			do_kill_orphans(nv1->nv_ptr, a, d, active);
 	}

Index: src/usr.bin/config/mkioconf.c
diff -u src/usr.bin/config/mkioconf.c:1.19 src/usr.bin/config/mkioconf.c:1.20
--- src/usr.bin/config/mkioconf.c:1.19	Thu Mar  3 14:53:01 2011
+++ src/usr.bin/config/mkioconf.c	Sun Mar 11 07:32:41 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: mkioconf.c,v 1.19 2011/03/03 14:53:01 nakayama Exp $	*/
+/*	$NetBSD: mkioconf.c,v 1.20 2012/03/11 07:32:41 dholland Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -200,7 +200,7 @@ static void
 emitcfdrivers(FILE *fp)
 {
 	struct devbase *d;
-	struct nvlist *nv;
+	struct attrlist *al;
 	struct attr *a;
 	int has_iattrs;
 
@@ -212,8 +212,8 @@ emitcfdrivers(FILE *fp)
 		if (!devbase_has_instances(d, WILD))
 			continue;
 		has_iattrs = 0;
-		for (nv = d->d_attrs; nv != NULL; nv = nv->nv_next) {
-			a = nv->nv_ptr;
+		for (al = d->d_attrs; al != NULL; al = al->al_next) {
+			a = al->al_this;
 			if (a->a_iattr == 0)
 				continue;
 			if (has_iattrs == 0)

Index: src/usr.bin/config/sem.c
diff -u src/usr.bin/config/sem.c:1.38 src/usr.bin/config/sem.c:1.39
--- src/usr.bin/config/sem.c:1.38	Sun May  2 15:35:00 2010
+++ src/usr.bin/config/sem.c	Sun Mar 11 07:32:41 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: sem.c,v 1.38 2010/05/02 15:35:00 pooka Exp $	*/
+/*	$NetBSD: sem.c,v 1.39 2012/03/11 07:32:41 dholland Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -70,7 +70,7 @@ static struct attr errattr;
 static struct devbase errdev;
 static struct deva errdeva;
 
-static int has_errobj(struct nvlist *, void *);
+static int has_errobj(struct attrlist *, struct attr *);
 static struct nvlist *addtoattr(struct nvlist *, struct devbase *);
 static int resolve(struct nvlist **, const char *, const char *,
 		   struct nvlist *, int);
@@ -194,10 +194,11 @@ setident(const char *i)
  * all locator lists include a dummy head node, which we discard here.
  */
 int
-defattr(const char *name, struct nvlist *locs, struct nvlist *deps,
+defattr(const char *name, struct nvlist *locs, struct attrlist *deps,
     int devclass)
 {
 	struct attr *a, *dep;
+	struct attrlist *al;
 	struct nvlist *nv;
 	int len;
 
@@ -211,8 +212,8 @@ defattr(const char *name, struct nvlist 
 	 * 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;
+	for (al = deps; al != NULL; al = al->al_next) {
+		dep = al->al_this;
 		if (dep->a_iattr) {
 			cfgerror("`%s' dependency `%s' is an interface "
 			    "attribute", name, dep->a_name);
@@ -275,11 +276,11 @@ defattr(const char *name, struct nvlist 
  * pointer list.
  */
 static int
-has_errobj(struct nvlist *nv, void *obj)
+has_errobj(struct attrlist *al, struct attr *obj)
 {
 
-	for (; nv != NULL; nv = nv->nv_next)
-		if (nv->nv_ptr == obj)
+	for (; al != NULL; al = al->al_next)
+		if (al->al_this == obj)
 			return (1);
 	return (0);
 }
@@ -289,15 +290,15 @@ has_errobj(struct nvlist *nv, void *obj)
  * pointer list.
  */
 int
-has_attr(struct nvlist *nv, const char *attr)
+has_attr(struct attrlist *al, const char *attr)
 {
 	struct attr *a;
 
 	if ((a = getattr(attr)) == NULL)
 		return (0);
 
-	for (; nv != NULL; nv = nv->nv_next)
-		if (nv->nv_ptr == a)
+	for (; al != NULL; al = al->al_next)
+		if (al->al_this == a)
 			return (1);
 	return (0);
 }
@@ -321,10 +322,11 @@ addtoattr(struct nvlist *l, struct devba
  * attribute and/or refer to existing attributes.
  */
 void
-defdev(struct devbase *dev, struct nvlist *loclist, struct nvlist *attrs,
+defdev(struct devbase *dev, struct nvlist *loclist, struct attrlist *attrs,
        int ispseudo)
 {
 	struct nvlist *nv;
+	struct attrlist *al;
 	struct attr *a;
 
 	if (dev == &errdev)
@@ -349,9 +351,9 @@ defdev(struct devbase *dev, struct nvlis
 		loclist = NULL;	/* defattr disposes of them for us */
 		if (defattr(dev->d_name, nv, NULL, 0))
 			goto bad;
-		attrs = newnv(dev->d_name, NULL, getattr(dev->d_name), 0,
-		    attrs);
-
+		attrs = attrlist_cons(attrs, getattr(dev->d_name));
+		/* This used to be stored but was never used */
+		/* attrs->al_name = dev->d_name; */
 	}
 
 	/*
@@ -359,10 +361,10 @@ defdev(struct devbase *dev, struct nvlis
 	 * attaching at root.
 	 */
 	if (ispseudo) {
-		for (nv = attrs; nv != NULL; nv = nv->nv_next)
-			if (((struct attr *)(nv->nv_ptr))->a_iattr)
+		for (al = attrs; al != NULL; al = al->al_next)
+			if (al->al_this->a_iattr)
 				break;
-		if (nv != NULL) {
+		if (al != NULL) {
 			if (ispseudo < 2) {
 				if (version >= 20080610)
 					cfgerror("interface attribute on "
@@ -389,8 +391,8 @@ defdev(struct devbase *dev, struct nvlis
 	 * class if any are devclass attributes (and error out if the
 	 * device has two classes).
 	 */
-	for (nv = attrs; nv != NULL; nv = nv->nv_next) {
-		a = nv->nv_ptr;
+	for (al = attrs; al != NULL; al = al->al_next) {
+		a = al->al_this;
 		if (a->a_iattr)
 			a->a_refs = addtoattr(a->a_refs, dev);
 		if (a->a_devclass != NULL) {
@@ -406,7 +408,7 @@ defdev(struct devbase *dev, struct nvlis
 	return;
  bad:
 	nvfreel(loclist);
-	nvfreel(attrs);
+	attrlist_destroyall(attrs);
 }
 
 /*
@@ -456,9 +458,10 @@ getdevbase(const char *name)
  */
 void
 defdevattach(struct deva *deva, struct devbase *dev, struct nvlist *atlist,
-	     struct nvlist *attrs)
+	     struct attrlist *attrs)
 {
 	struct nvlist *nv;
+	struct attrlist *al;
 	struct attr *a;
 	struct deva *da;
 
@@ -484,8 +487,8 @@ defdevattach(struct deva *deva, struct d
 	deva->d_isdef = 1;
 	if (has_errobj(attrs, &errattr))
 		goto bad;
-	for (nv = attrs; nv != NULL; nv = nv->nv_next) {
-		a = nv->nv_ptr;
+	for (al = attrs; al != NULL; al = al->al_next) {
+		a = al->al_this;
 		if (a == &errattr)
 			continue;		/* already complained */
 		if (a->a_iattr || a->a_devclass != NULL)
@@ -538,7 +541,7 @@ defdevattach(struct deva *deva, struct d
 	return;
  bad:
 	nvfreel(atlist);
-	nvfreel(attrs);
+	attrlist_destroyall(attrs);
 }
 
 /*
@@ -603,7 +606,7 @@ getattr(const char *name)
 void
 expandattr(struct attr *a, void (*callback)(struct attr *))
 {
-	struct nvlist *nv;
+	struct attrlist *al;
 	struct attr *dep;
 
 	if (a->a_expanding) {
@@ -614,8 +617,8 @@ expandattr(struct attr *a, void (*callba
 	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;
+	for (al = a->a_deps; al != NULL; al = al->al_next) {
+		dep = al->al_this;
 		expandattr(dep, callback);
 	}
 
@@ -940,7 +943,7 @@ adddev(const char *name, const char *at,
 	struct attr *attr;	/* attribute that allows attach */
 	struct devbase *ib;	/* i->i_base */
 	struct devbase *ab;	/* not NULL => at another dev */
-	struct nvlist *nv;
+	struct attrlist *al;
 	struct deva *iba;	/* devbase attachment used */
 	const char *cp;
 	int atunit;
@@ -1032,8 +1035,8 @@ adddev(const char *name, const char *at,
 		 * 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;
+		for (al = ab->d_attrs; al != NULL; al = al->al_next) {
+			attr = al->al_this;
 			if (onlist(attr->a_devs, ib))
 				goto findattachment;
 		}
@@ -1461,7 +1464,7 @@ addpseudoroot(const char *name)
 		fakedev = getdevbase(intern(fakename));
 		fakedev->d_isdef = 1;
 		fakedev->d_ispseudo = 0;
-		fakedev->d_attrs = newnv(NULL, NULL, attr, 0, NULL);
+		fakedev->d_attrs = attrlist_cons(NULL, attr);
 		defdevattach(NULL, fakedev, NULL, NULL);
 
 		if (unit == STAR)
@@ -1769,17 +1772,17 @@ static void
 selectbase(struct devbase *d, struct deva *da)
 {
 	struct attr *a;
-	struct nvlist *nv;
+	struct attrlist *al;
 
 	(void)ht_insert(selecttab, d->d_name, __UNCONST(d->d_name));
-	for (nv = d->d_attrs; nv != NULL; nv = nv->nv_next) {
-		a = nv->nv_ptr;
+	for (al = d->d_attrs; al != NULL; al = al->al_next) {
+		a = al->al_this;
 		expandattr(a, selectattr);
 	}
 	if (da != NULL) {
 		(void)ht_insert(selecttab, da->d_name, __UNCONST(da->d_name));
-		for (nv = da->d_attrs; nv != NULL; nv = nv->nv_next) {
-			a = nv->nv_ptr;
+		for (al = da->d_attrs; al != NULL; al = al->al_next) {
+			a = al->al_this;
 			expandattr(a, selectattr);
 		}
 	}

Index: src/usr.bin/config/sem.h
diff -u src/usr.bin/config/sem.h:1.7 src/usr.bin/config/sem.h:1.8
--- src/usr.bin/config/sem.h:1.7	Fri Apr 30 20:47:18 2010
+++ src/usr.bin/config/sem.h	Sun Mar 11 07:32:41 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: sem.h,v 1.7 2010/04/30 20:47:18 pooka Exp $	*/
+/*	$NetBSD: sem.h,v 1.8 2012/03/11 07:32:41 dholland Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -46,10 +46,10 @@ void		setversion(int);
 void		setdefmaxusers(int, int, int);
 void		setmaxusers(int);
 void		setident(const char *);
-int		defattr(const char *, struct nvlist *, struct nvlist *, int);
-void		defdev(struct devbase *, struct nvlist *, struct nvlist *, int);
+int		defattr(const char *, struct nvlist *, struct attrlist *, int);
+void		defdev(struct devbase *, struct nvlist *, struct attrlist *, int);
 void		defdevattach(struct deva *, struct devbase *, struct nvlist *,
-			     struct nvlist *);
+			     struct attrlist *);
 struct devbase *getdevbase(const char *);
 struct deva    *getdevattach(const char *);
 struct attr    *getattr(const char *);
@@ -73,7 +73,7 @@ int		fixdevis(void);
 const char     *ref(const char *);
 const char     *starref(const char *);
 const char     *wildref(const char *);
-int		has_attr(struct nvlist *, const char *);
+int		has_attr(struct attrlist *, const char *);
 
 extern const char *s_qmark;
 extern const char *s_none;

Index: src/usr.bin/config/util.c
diff -u src/usr.bin/config/util.c:1.9 src/usr.bin/config/util.c:1.10
--- src/usr.bin/config/util.c:1.9	Sat Mar 10 21:53:38 2012
+++ src/usr.bin/config/util.c	Sun Mar 11 07:32:41 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: util.c,v 1.9 2012/03/10 21:53:38 dholland Exp $	*/
+/*	$NetBSD: util.c,v 1.10 2012/03/11 07:32:41 dholland Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -45,6 +45,7 @@
 #endif
 
 #include <sys/types.h>
+#include <assert.h>
 #include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -187,6 +188,51 @@ nvcat(struct nvlist *nv1, struct nvlist 
 	return nv1;
 }
 
+struct attrlist *
+attrlist_create(void)
+{
+	struct attrlist *al;
+
+	al = emalloc(sizeof(*al));
+	al->al_next = NULL;
+	al->al_this = NULL;
+	return al;
+}
+
+struct attrlist *
+attrlist_cons(struct attrlist *next, struct attr *a)
+{
+	struct attrlist *al;
+
+	al = attrlist_create();
+	al->al_next = next;
+	al->al_this = a;
+	return al;
+}
+
+void
+attrlist_destroy(struct attrlist *al)
+{
+	assert(al->al_next == NULL);
+	assert(al->al_this == NULL);
+	free(al);
+}
+
+void
+attrlist_destroyall(struct attrlist *al)
+{
+	struct attrlist *next;
+
+	while (al != NULL) {
+		next = al->al_next;
+		al->al_next = NULL;
+		/* XXX should we make the caller guarantee this? */
+		al->al_this = NULL;
+		attrlist_destroy(al);
+		al = next;
+	}
+}
+
 void
 cfgwarn(const char *fmt, ...)
 {

Reply via email to