--- old/usr/src/cmd/sgs/tools/common/alist.c	2019-07-14 19:11:53.988683900 +0000
+++ /dev/null	2019-07-14 19:11:50.000000000 +0000
@@ -1,465 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-#include <sgs.h>
-#include <string.h>
-#include <stdio.h>
-#include <sys/debug.h>
-
-/*
- * Alist manipulation.  An Alist is a list of elements formed into an array.
- * Traversal of the list is an array scan, which because of the locality of
- * each reference is probably more efficient than a link-list traversal.
- *
- * See alist.h for more background information about array lists.
- */
-
-/*
- * Insert a value into an array at a specified index:
- *
- *	alist_insert(): Insert an item into an Alist at the specified index
- *	alist_insert_by_offset(): Insert an item into an Alist at the
- *		specified offset relative to the list address.
- *	aplist_insert() Insert a pointer into an APlist at the specified index
- *
- * entry:
- *	Note: All the arguments for all three routines are listed here.
- *	The routine to which a given argument applies is given with
- *	each description.
- *
- *	llp [all] - Address of a pointer to an Alist/APlist. The pointer should
- *		be initialized to NULL before its first use.
- *	datap [alist_insert / aplist_insert] - Pointer to item data, or
- *		NULL. If non-null the data referenced is copied into the
- *		Alist item. Otherwise, the list item is zeroed, and
- *		further initialization is left to the caller.
- *	ptr [aplist_insert] - Pointer to be inserted.
- *	size [alist_insert / alist_insert_by_offset] - Size of an item
- *		in the array list, in bytes. As with any array, A given
- *		Alist can support any item size, but every item in that
- *		list must have the same size.
- *	init_arritems [all] - Initial allocation size: On the first insertion
- *		into the array list, room for init_arritems items is allocated.
- *	idx [alist_insert / aplist_insert] - Index at which to insert the
- *		new item. This index must lie within the existing list,
- *		or be the next index following.
- *	off [alist_insert_by_offset] - Offset at which  to insert the new
- *		item, based from the start of the Alist. The offset of
- *		the first item is ALIST_OFF_DATA.
- *
- * exit:
- *	The item is inserted at the specified position. This operation
- *	can cause memory for the list to be allocated, or reallocated,
- *	either of which will cause the value of the list pointer
- *	to change.
- *
- *	These routines can only fail if unable to allocate memory,
- *	in which case NULL is returned.
- *
- *	If a pointer list (aplist_insert), then the pointer
- *	is stored in the requested index. On success, the address
- *	of the pointer within the list is returned.
- *
- *	If the list contains arbitrary data (not aplist_insert): If datap
- *	is non-NULL, the data it references is copied into the item at
- *	the index. If datap is NULL, the specified item is zeroed.
- *	On success, a pointer to the inserted item is returned.
- *
- *	The  caller must not retain the returned pointer from this
- *	routine across calls to the list module. It is only safe to use
- *	it until the next call to this module for the given list.
- *
- */
-void *
-alist_insert(Alist **lpp, const void *datap, size_t size,
-    Aliste init_arritems, Aliste idx)
-{
-	Alist	*lp = *lpp;
-	char	*addr;
-
-	/* The size and initial array count need to be non-zero */
-	ASSERT(init_arritems != 0);
-	ASSERT(size != 0);
-
-	if (lp == NULL) {
-		Aliste bsize;
-
-		/*
-		 * First time here, allocate a new Alist.  Note that the
-		 * Alist al_desc[] entry is defined for 1 element,
-		 * but we actually allocate the number we need.
-		 */
-		bsize = size * init_arritems;
-		bsize = S_ROUND(bsize, sizeof (void *));
-		bsize = ALIST_OFF_DATA + bsize;
-		if ((lp = malloc((size_t)bsize)) == NULL)
-			return (NULL);
-		lp->al_arritems = init_arritems;
-		lp->al_nitems = 0;
-		lp->al_next = ALIST_OFF_DATA;
-		lp->al_size = size;
-		*lpp = lp;
-	} else {
-		/* We must get the same value for size every time */
-		ASSERT(size == lp->al_size);
-
-		if (lp->al_nitems >= lp->al_arritems) {
-			/*
-			 * The list is full: Increase the memory allocation
-			 * by doubling it.
-			 */
-			Aliste	bsize;
-
-			bsize = lp->al_size * lp->al_arritems * 2;
-			bsize = S_ROUND(bsize, sizeof (void *));
-			bsize = ALIST_OFF_DATA + bsize;
-			if ((lp = realloc((void *)lp, (size_t)bsize)) == 0)
-				return (NULL);
-			lp->al_arritems *= 2;
-			*lpp = lp;
-		}
-	}
-
-	/*
-	 * The caller is not supposed to use an index that
-	 * would introduce a "hole" in the array.
-	 */
-	ASSERT(idx <= lp->al_nitems);
-
-	addr = (idx * lp->al_size) + (char *)lp->al_data;
-
-	/*
-	 * An appended item is added to the next available array element.
-	 * An insert at any other spot requires that the data items that
-	 * exist at the point of insertion be shifted down to open a slot.
-	 */
-	if (idx < lp->al_nitems)
-		(void) memmove(addr + lp->al_size, addr,
-		    (lp->al_nitems - idx) * lp->al_size);
-
-	lp->al_nitems++;
-	lp->al_next += lp->al_size;
-	if (datap != NULL)
-		(void) memcpy(addr, datap, lp->al_size);
-	else
-		(void) memset(addr, 0, lp->al_size);
-	return (addr);
-}
-
-void *
-alist_insert_by_offset(Alist **lpp, const void *datap, size_t size,
-    Aliste init_arritems, Aliste off)
-{
-	Aliste idx;
-
-	if (*lpp == NULL) {
-		ASSERT(off == ALIST_OFF_DATA);
-		idx = 0;
-	} else {
-		idx = (off - ALIST_OFF_DATA) / (*lpp)->al_size;
-	}
-
-	return (alist_insert(lpp, datap, size, init_arritems, idx));
-}
-
-void *
-aplist_insert(APlist **lpp, const void *ptr, Aliste init_arritems, Aliste idx)
-{
-	APlist	*lp = *lpp;
-
-	/* The initial array count needs to be non-zero */
-	ASSERT(init_arritems != 0);
-
-	if (lp == NULL) {
-		Aliste bsize;
-
-		/*
-		 * First time here, allocate a new APlist.  Note that the
-		 * APlist apl_desc[] entry is defined for 1 element,
-		 * but we actually allocate the number we need.
-		 */
-		bsize = APLIST_OFF_DATA + (sizeof (void *) * init_arritems);
-		if ((lp = malloc((size_t)bsize)) == NULL)
-			return (NULL);
-		lp->apl_arritems = init_arritems;
-		lp->apl_nitems = 0;
-		*lpp = lp;
-	} else if (lp->apl_nitems >= lp->apl_arritems) {
-		/*
-		 * The list is full: Increase the memory allocation
-		 * by doubling it.
-		 */
-		Aliste	bsize;
-
-		bsize = APLIST_OFF_DATA +
-		    (2 * sizeof (void *) * lp->apl_arritems);
-		if ((lp = realloc((void *)lp, (size_t)bsize)) == 0)
-			return (NULL);
-		lp->apl_arritems *= 2;
-		*lpp = lp;
-	}
-
-	/*
-	 * The caller is not supposed to use an index that
-	 * would introduce a "hole" in the array.
-	 */
-	ASSERT(idx <= lp->apl_nitems);
-
-	/*
-	 * An appended item is added to the next available array element.
-	 * An insert at any other spot requires that the data items that
-	 * exist at the point of insertion be shifted down to open a slot.
-	 */
-	if (idx < lp->apl_nitems)
-		(void) memmove((char *)&lp->apl_data[idx + 1],
-		    (char *)&lp->apl_data[idx],
-		    (lp->apl_nitems - idx) * sizeof (void *));
-
-	lp->apl_nitems++;
-	lp->apl_data[idx] = (void *)ptr;
-	return (&lp->apl_data[idx]);
-}
-
-/*
- * Append a value to a list. These are convenience wrappers on top
- * of the insert operation. See the description of those routine above
- * for details.
- */
-void *
-alist_append(Alist **lpp, const void *datap, size_t size,
-    Aliste init_arritems)
-{
-	Aliste ndx = ((*lpp) == NULL) ? 0 : (*lpp)->al_nitems;
-
-	return (alist_insert(lpp, datap, size, init_arritems, ndx));
-}
-
-void *
-aplist_append(APlist **lpp, const void *ptr, Aliste init_arritems)
-{
-	Aliste ndx = ((*lpp) == NULL) ? 0 : (*lpp)->apl_nitems;
-
-	return (aplist_insert(lpp, ptr, init_arritems, ndx));
-}
-
-/*
- * Delete the item at a specified index/offset, and decrement the variable
- * containing the index:
- *
- *	alist_delete - Delete an item from an Alist at the specified
- *		index.
- *	alist_delete_by_offset - Delete an item from an Alist at the
- *		specified offset from the list pointer.
- *	aplist_delete - Delete a pointer from an APlist at the specified
- *		index.
- *
- * entry:
- *	alp - List to delete item from
- *	idxp - Address of variable containing the index of the
- *		item to delete.
- *	offp - Address of variable containing the offset of the
- *		item to delete.
- *
- * exit:
- *	The item at the position given by (*idxp) or (*offp), depending
- *	on the routine, is removed from the list. Then, the position
- *	variable (*idxp or *offp) is decremented by one item. This is done
- *	to facilitate use of this routine within a TRAVERSE loop.
- *
- * note:
- *	Deleting the last element in an array list is cheap, but
- *	deleting any other item causes a memory copy to occur to
- *	move the following items up. If you intend to traverse the
- *	entire list, deleting every item as you go, it will be cheaper
- *	to omit the delete within the traverse, and then call
- *	the reset function reset() afterwards.
- */
-void
-alist_delete(Alist *lp, Aliste *idxp)
-{
-	Aliste	idx = *idxp;
-
-
-	/* The list must be allocated and the index in range */
-	ASSERT(lp != NULL);
-	ASSERT(idx < lp->al_nitems);
-
-	/*
-	 * If the element to be removed is not the last entry of the array,
-	 * slide the following elements over the present element.
-	 */
-	if (idx < --lp->al_nitems) {
-		char *addr = (idx * lp->al_size) + (char *)lp->al_data;
-
-		(void) memmove(addr, addr + lp->al_size,
-		    (lp->al_nitems - idx) * lp->al_size);
-	}
-	lp->al_next -= lp->al_size;
-
-	/* Decrement the callers index variable */
-	(*idxp)--;
-}
-
-void
-alist_delete_by_offset(Alist *lp, Aliste *offp)
-{
-	Aliste idx;
-
-	ASSERT(lp != NULL);
-	idx = (*offp - ALIST_OFF_DATA) / lp->al_size;
-
-	alist_delete(lp, &idx);
-	*offp -= lp->al_size;
-}
-
-void
-aplist_delete(APlist *lp, Aliste *idxp)
-{
-	Aliste	idx = *idxp;
-
-
-	/* The list must be allocated and the index in range */
-	ASSERT(lp != NULL);
-	ASSERT(idx < lp->apl_nitems);
-
-	/*
-	 * If the element to be removed is not the last entry of the array,
-	 * slide the following elements over the present element.
-	 */
-	if (idx < --lp->apl_nitems)
-		(void) memmove(&lp->apl_data[idx], &lp->apl_data[idx + 1],
-		    (lp->apl_nitems - idx) * sizeof (void *));
-
-	/* Decrement the callers index variable */
-	(*idxp)--;
-}
-
-/*
- * Delete the pointer with a specified value from the APlist.
- *
- * entry:
- *	lp - Initialized APlist to delete item from
- *	ptr - Pointer to be deleted.
- *
- * exit:
- *	The list is searched for an item containing the given pointer,
- *	and if a match is found, that item is delted and True (1) returned.
- *	If no match is found, then False (0) is returned.
- *
- * note:
- *	See note for delete operation, above.
- */
-int
-aplist_delete_value(APlist *lp, const void *ptr)
-{
-	size_t	idx;
-
-	/*
-	 * If the pointer is found in the list, use aplist_delete to
-	 * remove it, and we're done.
-	 */
-	for (idx = 0; idx < lp->apl_nitems; idx++)
-		if (ptr == lp->apl_data[idx]) {
-			aplist_delete(lp, &idx);
-			return (1);
-		}
-
-	/* If we get here, the item was not in the list */
-	return (0);
-}
-
-/*
- * Search the APlist for an element with a given value, and
- * if not found, optionally append the element to the end of the list.
- *
- * entry:
- *	lpp, ptr - As per aplist_insert().
- *	init_arritems - As per aplist_insert() if a non-zero value.
- *		A value of zero is special, and is taken to indicate
- *		that no insert operation should be performed if
- *		the item is not found in the list.
- *
- * exit
- *	The given item is compared to every item in the given APlist.
- *	If it is found, ALE_EXISTS is returned.
- *
- *	If it is not found: If init_arr_items is False (0), then
- *	ALE_NOTFOUND is returned. If init_arr_items is True, then
- *	the item is appended to the list, and ALE_CREATE returned on success.
- *
- *	On failure, which can only occur due to memory allocation failure,
- *	ALE_ALLOCFAIL is returned.
- *
- * note:
- *	The test operation used by this routine is a linear
- *	O(N) operation, and is not efficient for more than a
- *	few items.
- */
-aplist_test_t
-aplist_test(APlist **lpp, const void *ptr, Aliste init_arritems)
-{
-	APlist	*lp = *lpp;
-	size_t	idx;
-
-	/* Is the pointer already in the list? */
-	if (lp != NULL)
-		for (idx = 0; idx < lp->apl_nitems; idx++)
-			if (ptr == lp->apl_data[idx])
-				return (ALE_EXISTS);
-
-	/* Is this a no-insert case? If so, report that the item is not found */
-	if (init_arritems == 0)
-		return (ALE_NOTFND);
-
-	/* Add it to the end of the list */
-	if (aplist_append(lpp, ptr, init_arritems) == NULL)
-		return (ALE_ALLOCFAIL);
-	return (ALE_CREATE);
-}
-
-/*
- * Reset the given list to its empty state. Any memory allocated by the
- * list is preserved, ready for reuse, but the list is set to its
- * empty state, equivalent to having called the delete operation for
- * every item.
- *
- * Note that no cleanup of the discarded items is done. The caller must
- * take care of any necessary cleanup before calling aplist_reset().
- */
-void
-alist_reset(Alist *lp)
-{
-	if (lp != NULL) {
-		lp->al_nitems = 0;
-		lp->al_next = ALIST_OFF_DATA;
-	}
-}
-
-void
-aplist_reset(APlist *lp)
-{
-	if (lp != NULL)
-		lp->apl_nitems = 0;
-}
--- /dev/null	2019-07-14 19:11:50.000000000 +0000
+++ new/usr/src/cmd/sgs/common/alist.c	2019-07-14 19:11:54.005390270 +0000
@@ -0,0 +1,465 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+#include <sgs.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/debug.h>
+
+/*
+ * Alist manipulation.  An Alist is a list of elements formed into an array.
+ * Traversal of the list is an array scan, which because of the locality of
+ * each reference is probably more efficient than a link-list traversal.
+ *
+ * See alist.h for more background information about array lists.
+ */
+
+/*
+ * Insert a value into an array at a specified index:
+ *
+ *	alist_insert(): Insert an item into an Alist at the specified index
+ *	alist_insert_by_offset(): Insert an item into an Alist at the
+ *		specified offset relative to the list address.
+ *	aplist_insert() Insert a pointer into an APlist at the specified index
+ *
+ * entry:
+ *	Note: All the arguments for all three routines are listed here.
+ *	The routine to which a given argument applies is given with
+ *	each description.
+ *
+ *	llp [all] - Address of a pointer to an Alist/APlist. The pointer should
+ *		be initialized to NULL before its first use.
+ *	datap [alist_insert / aplist_insert] - Pointer to item data, or
+ *		NULL. If non-null the data referenced is copied into the
+ *		Alist item. Otherwise, the list item is zeroed, and
+ *		further initialization is left to the caller.
+ *	ptr [aplist_insert] - Pointer to be inserted.
+ *	size [alist_insert / alist_insert_by_offset] - Size of an item
+ *		in the array list, in bytes. As with any array, A given
+ *		Alist can support any item size, but every item in that
+ *		list must have the same size.
+ *	init_arritems [all] - Initial allocation size: On the first insertion
+ *		into the array list, room for init_arritems items is allocated.
+ *	idx [alist_insert / aplist_insert] - Index at which to insert the
+ *		new item. This index must lie within the existing list,
+ *		or be the next index following.
+ *	off [alist_insert_by_offset] - Offset at which  to insert the new
+ *		item, based from the start of the Alist. The offset of
+ *		the first item is ALIST_OFF_DATA.
+ *
+ * exit:
+ *	The item is inserted at the specified position. This operation
+ *	can cause memory for the list to be allocated, or reallocated,
+ *	either of which will cause the value of the list pointer
+ *	to change.
+ *
+ *	These routines can only fail if unable to allocate memory,
+ *	in which case NULL is returned.
+ *
+ *	If a pointer list (aplist_insert), then the pointer
+ *	is stored in the requested index. On success, the address
+ *	of the pointer within the list is returned.
+ *
+ *	If the list contains arbitrary data (not aplist_insert): If datap
+ *	is non-NULL, the data it references is copied into the item at
+ *	the index. If datap is NULL, the specified item is zeroed.
+ *	On success, a pointer to the inserted item is returned.
+ *
+ *	The  caller must not retain the returned pointer from this
+ *	routine across calls to the list module. It is only safe to use
+ *	it until the next call to this module for the given list.
+ *
+ */
+void *
+alist_insert(Alist **lpp, const void *datap, size_t size,
+    Aliste init_arritems, Aliste idx)
+{
+	Alist	*lp = *lpp;
+	char	*addr;
+
+	/* The size and initial array count need to be non-zero */
+	ASSERT(init_arritems != 0);
+	ASSERT(size != 0);
+
+	if (lp == NULL) {
+		Aliste bsize;
+
+		/*
+		 * First time here, allocate a new Alist.  Note that the
+		 * Alist al_desc[] entry is defined for 1 element,
+		 * but we actually allocate the number we need.
+		 */
+		bsize = size * init_arritems;
+		bsize = S_ROUND(bsize, sizeof (void *));
+		bsize = ALIST_OFF_DATA + bsize;
+		if ((lp = malloc((size_t)bsize)) == NULL)
+			return (NULL);
+		lp->al_arritems = init_arritems;
+		lp->al_nitems = 0;
+		lp->al_next = ALIST_OFF_DATA;
+		lp->al_size = size;
+		*lpp = lp;
+	} else {
+		/* We must get the same value for size every time */
+		ASSERT(size == lp->al_size);
+
+		if (lp->al_nitems >= lp->al_arritems) {
+			/*
+			 * The list is full: Increase the memory allocation
+			 * by doubling it.
+			 */
+			Aliste	bsize;
+
+			bsize = lp->al_size * lp->al_arritems * 2;
+			bsize = S_ROUND(bsize, sizeof (void *));
+			bsize = ALIST_OFF_DATA + bsize;
+			if ((lp = realloc((void *)lp, (size_t)bsize)) == 0)
+				return (NULL);
+			lp->al_arritems *= 2;
+			*lpp = lp;
+		}
+	}
+
+	/*
+	 * The caller is not supposed to use an index that
+	 * would introduce a "hole" in the array.
+	 */
+	ASSERT(idx <= lp->al_nitems);
+
+	addr = (idx * lp->al_size) + (char *)lp->al_data;
+
+	/*
+	 * An appended item is added to the next available array element.
+	 * An insert at any other spot requires that the data items that
+	 * exist at the point of insertion be shifted down to open a slot.
+	 */
+	if (idx < lp->al_nitems)
+		(void) memmove(addr + lp->al_size, addr,
+		    (lp->al_nitems - idx) * lp->al_size);
+
+	lp->al_nitems++;
+	lp->al_next += lp->al_size;
+	if (datap != NULL)
+		(void) memcpy(addr, datap, lp->al_size);
+	else
+		(void) memset(addr, 0, lp->al_size);
+	return (addr);
+}
+
+void *
+alist_insert_by_offset(Alist **lpp, const void *datap, size_t size,
+    Aliste init_arritems, Aliste off)
+{
+	Aliste idx;
+
+	if (*lpp == NULL) {
+		ASSERT(off == ALIST_OFF_DATA);
+		idx = 0;
+	} else {
+		idx = (off - ALIST_OFF_DATA) / (*lpp)->al_size;
+	}
+
+	return (alist_insert(lpp, datap, size, init_arritems, idx));
+}
+
+void *
+aplist_insert(APlist **lpp, const void *ptr, Aliste init_arritems, Aliste idx)
+{
+	APlist	*lp = *lpp;
+
+	/* The initial array count needs to be non-zero */
+	ASSERT(init_arritems != 0);
+
+	if (lp == NULL) {
+		Aliste bsize;
+
+		/*
+		 * First time here, allocate a new APlist.  Note that the
+		 * APlist apl_desc[] entry is defined for 1 element,
+		 * but we actually allocate the number we need.
+		 */
+		bsize = APLIST_OFF_DATA + (sizeof (void *) * init_arritems);
+		if ((lp = malloc((size_t)bsize)) == NULL)
+			return (NULL);
+		lp->apl_arritems = init_arritems;
+		lp->apl_nitems = 0;
+		*lpp = lp;
+	} else if (lp->apl_nitems >= lp->apl_arritems) {
+		/*
+		 * The list is full: Increase the memory allocation
+		 * by doubling it.
+		 */
+		Aliste	bsize;
+
+		bsize = APLIST_OFF_DATA +
+		    (2 * sizeof (void *) * lp->apl_arritems);
+		if ((lp = realloc((void *)lp, (size_t)bsize)) == 0)
+			return (NULL);
+		lp->apl_arritems *= 2;
+		*lpp = lp;
+	}
+
+	/*
+	 * The caller is not supposed to use an index that
+	 * would introduce a "hole" in the array.
+	 */
+	ASSERT(idx <= lp->apl_nitems);
+
+	/*
+	 * An appended item is added to the next available array element.
+	 * An insert at any other spot requires that the data items that
+	 * exist at the point of insertion be shifted down to open a slot.
+	 */
+	if (idx < lp->apl_nitems)
+		(void) memmove((char *)&lp->apl_data[idx + 1],
+		    (char *)&lp->apl_data[idx],
+		    (lp->apl_nitems - idx) * sizeof (void *));
+
+	lp->apl_nitems++;
+	lp->apl_data[idx] = (void *)ptr;
+	return (&lp->apl_data[idx]);
+}
+
+/*
+ * Append a value to a list. These are convenience wrappers on top
+ * of the insert operation. See the description of those routine above
+ * for details.
+ */
+void *
+alist_append(Alist **lpp, const void *datap, size_t size,
+    Aliste init_arritems)
+{
+	Aliste ndx = ((*lpp) == NULL) ? 0 : (*lpp)->al_nitems;
+
+	return (alist_insert(lpp, datap, size, init_arritems, ndx));
+}
+
+void *
+aplist_append(APlist **lpp, const void *ptr, Aliste init_arritems)
+{
+	Aliste ndx = ((*lpp) == NULL) ? 0 : (*lpp)->apl_nitems;
+
+	return (aplist_insert(lpp, ptr, init_arritems, ndx));
+}
+
+/*
+ * Delete the item at a specified index/offset, and decrement the variable
+ * containing the index:
+ *
+ *	alist_delete - Delete an item from an Alist at the specified
+ *		index.
+ *	alist_delete_by_offset - Delete an item from an Alist at the
+ *		specified offset from the list pointer.
+ *	aplist_delete - Delete a pointer from an APlist at the specified
+ *		index.
+ *
+ * entry:
+ *	alp - List to delete item from
+ *	idxp - Address of variable containing the index of the
+ *		item to delete.
+ *	offp - Address of variable containing the offset of the
+ *		item to delete.
+ *
+ * exit:
+ *	The item at the position given by (*idxp) or (*offp), depending
+ *	on the routine, is removed from the list. Then, the position
+ *	variable (*idxp or *offp) is decremented by one item. This is done
+ *	to facilitate use of this routine within a TRAVERSE loop.
+ *
+ * note:
+ *	Deleting the last element in an array list is cheap, but
+ *	deleting any other item causes a memory copy to occur to
+ *	move the following items up. If you intend to traverse the
+ *	entire list, deleting every item as you go, it will be cheaper
+ *	to omit the delete within the traverse, and then call
+ *	the reset function reset() afterwards.
+ */
+void
+alist_delete(Alist *lp, Aliste *idxp)
+{
+	Aliste	idx = *idxp;
+
+
+	/* The list must be allocated and the index in range */
+	ASSERT(lp != NULL);
+	ASSERT(idx < lp->al_nitems);
+
+	/*
+	 * If the element to be removed is not the last entry of the array,
+	 * slide the following elements over the present element.
+	 */
+	if (idx < --lp->al_nitems) {
+		char *addr = (idx * lp->al_size) + (char *)lp->al_data;
+
+		(void) memmove(addr, addr + lp->al_size,
+		    (lp->al_nitems - idx) * lp->al_size);
+	}
+	lp->al_next -= lp->al_size;
+
+	/* Decrement the callers index variable */
+	(*idxp)--;
+}
+
+void
+alist_delete_by_offset(Alist *lp, Aliste *offp)
+{
+	Aliste idx;
+
+	ASSERT(lp != NULL);
+	idx = (*offp - ALIST_OFF_DATA) / lp->al_size;
+
+	alist_delete(lp, &idx);
+	*offp -= lp->al_size;
+}
+
+void
+aplist_delete(APlist *lp, Aliste *idxp)
+{
+	Aliste	idx = *idxp;
+
+
+	/* The list must be allocated and the index in range */
+	ASSERT(lp != NULL);
+	ASSERT(idx < lp->apl_nitems);
+
+	/*
+	 * If the element to be removed is not the last entry of the array,
+	 * slide the following elements over the present element.
+	 */
+	if (idx < --lp->apl_nitems)
+		(void) memmove(&lp->apl_data[idx], &lp->apl_data[idx + 1],
+		    (lp->apl_nitems - idx) * sizeof (void *));
+
+	/* Decrement the callers index variable */
+	(*idxp)--;
+}
+
+/*
+ * Delete the pointer with a specified value from the APlist.
+ *
+ * entry:
+ *	lp - Initialized APlist to delete item from
+ *	ptr - Pointer to be deleted.
+ *
+ * exit:
+ *	The list is searched for an item containing the given pointer,
+ *	and if a match is found, that item is delted and True (1) returned.
+ *	If no match is found, then False (0) is returned.
+ *
+ * note:
+ *	See note for delete operation, above.
+ */
+int
+aplist_delete_value(APlist *lp, const void *ptr)
+{
+	size_t	idx;
+
+	/*
+	 * If the pointer is found in the list, use aplist_delete to
+	 * remove it, and we're done.
+	 */
+	for (idx = 0; idx < lp->apl_nitems; idx++)
+		if (ptr == lp->apl_data[idx]) {
+			aplist_delete(lp, &idx);
+			return (1);
+		}
+
+	/* If we get here, the item was not in the list */
+	return (0);
+}
+
+/*
+ * Search the APlist for an element with a given value, and
+ * if not found, optionally append the element to the end of the list.
+ *
+ * entry:
+ *	lpp, ptr - As per aplist_insert().
+ *	init_arritems - As per aplist_insert() if a non-zero value.
+ *		A value of zero is special, and is taken to indicate
+ *		that no insert operation should be performed if
+ *		the item is not found in the list.
+ *
+ * exit
+ *	The given item is compared to every item in the given APlist.
+ *	If it is found, ALE_EXISTS is returned.
+ *
+ *	If it is not found: If init_arr_items is False (0), then
+ *	ALE_NOTFOUND is returned. If init_arr_items is True, then
+ *	the item is appended to the list, and ALE_CREATE returned on success.
+ *
+ *	On failure, which can only occur due to memory allocation failure,
+ *	ALE_ALLOCFAIL is returned.
+ *
+ * note:
+ *	The test operation used by this routine is a linear
+ *	O(N) operation, and is not efficient for more than a
+ *	few items.
+ */
+aplist_test_t
+aplist_test(APlist **lpp, const void *ptr, Aliste init_arritems)
+{
+	APlist	*lp = *lpp;
+	size_t	idx;
+
+	/* Is the pointer already in the list? */
+	if (lp != NULL)
+		for (idx = 0; idx < lp->apl_nitems; idx++)
+			if (ptr == lp->apl_data[idx])
+				return (ALE_EXISTS);
+
+	/* Is this a no-insert case? If so, report that the item is not found */
+	if (init_arritems == 0)
+		return (ALE_NOTFND);
+
+	/* Add it to the end of the list */
+	if (aplist_append(lpp, ptr, init_arritems) == NULL)
+		return (ALE_ALLOCFAIL);
+	return (ALE_CREATE);
+}
+
+/*
+ * Reset the given list to its empty state. Any memory allocated by the
+ * list is preserved, ready for reuse, but the list is set to its
+ * empty state, equivalent to having called the delete operation for
+ * every item.
+ *
+ * Note that no cleanup of the discarded items is done. The caller must
+ * take care of any necessary cleanup before calling aplist_reset().
+ */
+void
+alist_reset(Alist *lp)
+{
+	if (lp != NULL) {
+		lp->al_nitems = 0;
+		lp->al_next = ALIST_OFF_DATA;
+	}
+}
+
+void
+aplist_reset(APlist *lp)
+{
+	if (lp != NULL)
+		lp->apl_nitems = 0;
+}
