Browse Source

list: implement list_check_node to check list from node rather than head

Rusty Russell 15 years ago
parent
commit
22ffb884ca
3 changed files with 49 additions and 15 deletions
  1. 21 13
      ccan/list/list.c
  2. 22 1
      ccan/list/list.h
  3. 6 1
      ccan/list/test/run.c

+ 21 - 13
ccan/list/list.c

@@ -2,32 +2,40 @@
 #include <stdlib.h>
 #include <stdlib.h>
 #include "list.h"
 #include "list.h"
 
 
-struct list_head *list_check(const struct list_head *h, const char *abortstr)
+struct list_node *list_check_node(const struct list_node *node,
+				  const char *abortstr)
 {
 {
-	const struct list_node *n, *p;
+	const struct list_node *p, *n;
 	int count = 0;
 	int count = 0;
 
 
-	if (h->n.next == &h->n) {
-		if (h->n.prev != &h->n) {
+	for (p = node, n = node->next; n != node; p = n, n = n->next) {
+		count++;
+		if (n->prev != p) {
 			if (!abortstr)
 			if (!abortstr)
 				return NULL;
 				return NULL;
-			fprintf(stderr, "%s: prev corrupt in empty %p\n",
-				abortstr, h);
+			fprintf(stderr,
+				"%s: prev corrupt in node %p (%u) of %p\n",
+				abortstr, n, count, node);
 			abort();
 			abort();
 		}
 		}
-		return (struct list_head *)h;
 	}
 	}
+	return (struct list_node *)node;
+}
 
 
-	for (p = &h->n, n = h->n.next; n != &h->n; p = n, n = n->next) {
-		count++;
-		if (n->prev != p) {
+struct list_head *list_check(const struct list_head *h, const char *abortstr)
+{
+	if (h->n.next == &h->n) {
+		if (h->n.prev != &h->n) {
 			if (!abortstr)
 			if (!abortstr)
 				return NULL;
 				return NULL;
-			fprintf(stderr,
-				"%s: prev corrupt in node %p (%u) of %p\n",
-				abortstr, n, count, h);
+			fprintf(stderr, "%s: prev corrupt in empty %p\n",
+				abortstr, h);
 			abort();
 			abort();
 		}
 		}
+		return (struct list_head *)h;
 	}
 	}
+
+	if (!list_check_node(&h->n, abortstr))
+		return NULL;
 	return (struct list_head *)h;
 	return (struct list_head *)h;
 }
 }

+ 22 - 1
ccan/list/list.h

@@ -39,7 +39,7 @@ struct list_head
 };
 };
 
 
 /**
 /**
- * list_check - check a list for consistency
+ * list_check - check head of a list for consistency
  * @h: the list_head
  * @h: the list_head
  * @abortstr: the location to print on aborting, or NULL.
  * @abortstr: the location to print on aborting, or NULL.
  *
  *
@@ -51,6 +51,8 @@ struct list_head
  * Returns the list head if the list is consistent, NULL if not (it
  * Returns the list head if the list is consistent, NULL if not (it
  * can never return NULL if @abortstr is set).
  * can never return NULL if @abortstr is set).
  *
  *
+ * See also: list_check_node()
+ *
  * Example:
  * Example:
  *	static void dump_parent(struct parent *p)
  *	static void dump_parent(struct parent *p)
  *	{
  *	{
@@ -64,6 +66,25 @@ struct list_head
  */
  */
 struct list_head *list_check(const struct list_head *h, const char *abortstr);
 struct list_head *list_check(const struct list_head *h, const char *abortstr);
 
 
+/**
+ * list_check_node - check node of a list for consistency
+ * @n: the list_node
+ * @abortstr: the location to print on aborting, or NULL.
+ *
+ * Check consistency of the list node is in (it must be in one).
+ *
+ * See also: list_check()
+ *
+ * Example:
+ *	static void dump_child(const struct child *c)
+ *	{
+ *		list_check_node(&c->list, "bad child list");
+ *		printf("%s\n", c->name);
+ *	}
+ */
+struct list_node *list_check_node(const struct list_node *n,
+				  const char *abortstr);
+
 #ifdef CCAN_LIST_DEBUG
 #ifdef CCAN_LIST_DEBUG
 #define debug_list(h) list_check((h), __func__)
 #define debug_list(h) list_check((h), __func__)
 #else
 #else

+ 6 - 1
ccan/list/test/run.c

@@ -21,7 +21,7 @@ int main(int argc, char *argv[])
 	struct child c1, c2, c3, *c, *n;
 	struct child c1, c2, c3, *c, *n;
 	unsigned int i;
 	unsigned int i;
 
 
-	plan_tests(44);
+	plan_tests(47);
 	/* Test LIST_HEAD, list_empty and check_list */
 	/* Test LIST_HEAD, list_empty and check_list */
 	ok1(list_empty(&static_list));
 	ok1(list_empty(&static_list));
 	ok1(list_check(&static_list, NULL));
 	ok1(list_check(&static_list, NULL));
@@ -71,6 +71,11 @@ int main(int argc, char *argv[])
 	/* Test list_check */
 	/* Test list_check */
 	ok1(list_check(&parent.children, NULL));
 	ok1(list_check(&parent.children, NULL));
 
 
+	/* Test list_check_node */
+	ok1(list_check_node(&c1.list, NULL));
+	ok1(list_check_node(&c2.list, NULL));
+	ok1(list_check_node(&c3.list, NULL));
+
 	/* Test list_top */
 	/* Test list_top */
 	ok1(list_top(&parent.children, struct child, list) == &c1);
 	ok1(list_top(&parent.children, struct child, list) == &c1);