new file mode 100644
@@ -0,0 +1,26 @@
+skiboot/ccan/ is a minimally modified version of upstream ccan that is
+hosted at github.com/rustyrussell/ccan.git
+
+This version is taken from ccan.git commit ca7c5a9e04f3 ("ccan: make tal_dump()
+format more regular.") with these modules:
+
+ array_size
+ check_type
+ container_of
+ heap
+ short_types
+ build_assert
+ endian
+ list
+ str
+
+Generated with `./tools/create-ccan-tree -b make ...` and replacing the
+corresponding directories in skiboot/ccan/, then skiboot/ccan/skiboot.patch
+is applied.
+
+The only other differences from upstream are the additions under the ccan/
+directory of this file README.skiboot, Makefile.inc, Makefile.check, config.h,
+tap/tap.h, skiboot.patch.
+
+Local ccan changes should be kept to a minimum, documented here as necessary,
+and submitted upstream if possible.
@@ -1,6 +1,6 @@
+#include "config.h"
#include <stdio.h>
#include <string.h>
-#include "config.h"
/**
* array_size - routine for safely deriving the size of a visible array.
@@ -12,7 +12,7 @@
* macro or constant.
*
* Example:
- * // Outputs "Initialized 32 values"
+ * // Outputs "Initialized 32 values\n"
* #include <ccan/array_size/array_size.h>
* #include <stdlib.h>
* #include <stdio.h>
@@ -5,8 +5,8 @@ struct foo {
unsigned int a, b;
};
-int check_parameter(const struct foo array[4]);
-int check_parameter(const struct foo array[4])
+int check_parameter(const struct foo *array);
+int check_parameter(const struct foo *array)
{
#ifdef FAIL
return (ARRAY_SIZE(array) == 4);
@@ -18,7 +18,7 @@ int check_parameter(const struct foo array[4])
#endif
}
-int main(int argc, char *argv[])
+int main(void)
{
return check_parameter(NULL);
}
@@ -2,6 +2,8 @@
int main(int argc, char *argv[8])
{
+ (void)argc;
+ (void)argv;
char array[100];
#ifdef FAIL
return ARRAY_SIZE(argv) + ARRAY_SIZE(array);
@@ -16,11 +16,8 @@ static int array2_size = ARRAY_SIZE(array2);
static int array3_size = ARRAY_SIZE(array3);
static int array4_size = ARRAY_SIZE(array4);
-int __attribute__((const)) main(int argc, char *argv[])
+int main(void)
{
- (void)argc;
- (void)argv;
-
plan_tests(8);
ok1(array1_size == 1);
ok1(array2_size == 2);
@@ -1,6 +1,6 @@
+#include "config.h"
#include <stdio.h>
#include <string.h>
-#include "config.h"
/**
* build_assert - routines for build-time assertions
@@ -1,6 +1,6 @@
#include <ccan/build_assert/build_assert.h>
-int main(int argc, char *argv[])
+int main(void)
{
#ifdef FAIL
return BUILD_ASSERT_OR_ZERO(1 == 0);
@@ -1,6 +1,6 @@
#include <ccan/build_assert/build_assert.h>
-int main(int argc, char *argv[])
+int main(void)
{
#ifdef FAIL
BUILD_ASSERT(1 == 0);
@@ -1,6 +1,6 @@
#include <ccan/build_assert/build_assert.h>
-int main(int argc, char *argv[])
+int main(void)
{
BUILD_ASSERT(1 == 1);
return 0;
@@ -1,11 +1,8 @@
#include <ccan/build_assert/build_assert.h>
#include <ccan/tap/tap.h>
-int __attribute__((const)) main(int argc, char *argv[])
+int main(void)
{
- (void)argc;
- (void)argv;
-
plan_tests(1);
ok1(BUILD_ASSERT_OR_ZERO(1 == 1) == 0);
return exit_status();
@@ -1,6 +1,6 @@
+#include "config.h"
#include <stdio.h>
#include <string.h>
-#include "config.h"
/**
* check_type - routines for compile time type checking
@@ -43,7 +43,7 @@
* #define container_of(mbr_ptr, encl_type, mbr) \
* (check_types_match((mbr_ptr), &((encl_type *)0)->mbr), \
* ((encl_type *) \
- * ((char *)(mbr_ptr) - offsetof(enclosing_type, mbr))))
+ * ((char *)(mbr_ptr) - offsetof(encl_type, mbr))))
*/
#if HAVE_TYPEOF
#define check_type(expr, type) \
@@ -2,6 +2,8 @@
int main(int argc, char *argv[])
{
+ (void)argc;
+ (void)argv;
#ifdef FAIL
check_type(argc, char);
#endif
@@ -2,6 +2,8 @@
int main(int argc, char *argv[])
{
+ (void)argc;
+ (void)argv;
#ifdef FAIL
#if HAVE_TYPEOF
check_type(argc, unsigned int);
@@ -3,6 +3,7 @@
int main(int argc, char *argv[])
{
unsigned char x = argc;
+ (void)argv;
#ifdef FAIL
check_types_match(argc, x);
#endif
@@ -1,13 +1,11 @@
#include <ccan/check_type/check_type.h>
#include <ccan/tap/tap.h>
-int __attribute__((const)) main(int argc, char *argv[])
+int main(int argc, char *argv[])
{
int x = 0, y = 0;
- (void)argc;
(void)argv;
-
plan_tests(9);
ok1(check_type(argc, int) == 0);
@@ -14,17 +14,26 @@
* limitations under the License.
*/
/* Dummy config.h for CCAN test suite */
+#ifndef CCAN_CONFIG_H
+#define CCAN_CONFIG_H
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE /* Always use GNU extensions. */
+#endif
-#define HAVE_BUILTIN_TYPES_COMPATIBLE_P 1
-#define HAVE_TYPEOF 1
+#include <endian.h>
-#ifndef HAVE_BIG_ENDIAN
-#define HAVE_BIG_ENDIAN 0
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define HAVE_BIG_ENDIAN 0
+#define HAVE_LITTLE_ENDIAN 1
+#else
+#define HAVE_BIG_ENDIAN 1
+#define HAVE_LITTLE_ENDIAN 0
#endif
-#ifndef HAVE_LITTLE_ENDIAN
-#define HAVE_LITTLE_ENDIAN 0
-#endif
+#define HAVE_BUILTIN_TYPES_COMPATIBLE_P 1
+#define HAVE_TYPEOF 1
+
+#define HAVE_BYTESWAP_H 1
+#define HAVE_BSWAP_64 1
-#define HAVE_BYTESWAP_H 0
-#define HAVE_BSWAP_64 0
+#endif /* CCAN_CONFIG_H */
@@ -1,6 +1,6 @@
+#include "config.h"
#include <stdio.h>
#include <string.h>
-#include "config.h"
/**
* container_of - routine for upcasting
@@ -26,17 +26,19 @@
* struct timer timer;
* };
*
- * static void register_timer(struct timer *timer)
- * {
- * //...
- * }
- *
* static void my_timer_callback(struct timer *timer)
* {
* struct info *info = container_of(timer, struct info, timer);
* printf("my_stuff is %u\n", info->my_stuff);
* }
*
+ * static void register_timer(struct timer *timer)
+ * {
+ * (void)timer;
+ * (void)my_timer_callback;
+ * //...
+ * }
+ *
* int main(void)
* {
* struct info info = { .my_stuff = 1 };
@@ -36,6 +36,42 @@
- container_off(containing_type, member)) \
+ check_types_match(*(member_ptr), ((containing_type *)0)->member))
+
+/**
+ * container_of_or_null - get pointer to enclosing structure, or NULL
+ * @member_ptr: pointer to the structure member
+ * @containing_type: the type this member is within
+ * @member: the name of this member within the structure.
+ *
+ * Given a pointer to a member of a structure, this macro does pointer
+ * subtraction to return the pointer to the enclosing type, unless it
+ * is given NULL, in which case it also returns NULL.
+ *
+ * Example:
+ * struct foo {
+ * int fielda, fieldb;
+ * // ...
+ * };
+ * struct info {
+ * int some_other_field;
+ * struct foo my_foo;
+ * };
+ *
+ * static struct info *foo_to_info_allowing_null(struct foo *foo)
+ * {
+ * return container_of_or_null(foo, struct info, my_foo);
+ * }
+ */
+static inline char *container_of_or_null_(void *member_ptr, size_t offset)
+{
+ return member_ptr ? (char *)member_ptr - offset : NULL;
+}
+#define container_of_or_null(member_ptr, containing_type, member) \
+ ((containing_type *) \
+ container_of_or_null_(member_ptr, \
+ container_off(containing_type, member)) \
+ + check_types_match(*(member_ptr), ((containing_type *)0)->member))
+
/**
* container_off - get offset to enclosing structure
* @containing_type: the type this member is within
@@ -103,7 +139,7 @@
container_off(typeof(*var), member)
#else
#define container_off_var(var, member) \
- ((char *)&(var)->member - (char *)(var))
+ ((const char *)&(var)->member - (const char *)(var))
#endif
#endif /* CCAN_CONTAINER_OF_H */
@@ -6,7 +6,7 @@ struct foo {
char b;
};
-int main(int argc, char *argv[])
+int main(void)
{
struct foo foo = { .a = 1, .b = 2 };
int *intp = &foo.a;
@@ -6,7 +6,7 @@ struct foo {
char b;
};
-int main(int argc, char *argv[])
+int main(void)
{
struct foo foo = { .a = 1, .b = 2 }, *foop;
int *intp = &foo.a;
@@ -6,7 +6,7 @@ struct foo {
char b;
};
-int main(int argc, char *argv[])
+int main(void)
{
struct foo foo = { .a = 1, .b = 2 }, *foop;
int *intp = &foo.a;
@@ -6,22 +6,25 @@ struct foo {
char b;
};
-int __attribute__((const)) main(int argc, char *argv[])
+int main(void)
{
struct foo foo = { .a = 1, .b = 2 };
int *intp = &foo.a;
char *charp = &foo.b;
- (void)argc;
- (void)argv;
-
- plan_tests(6);
+ plan_tests(12);
ok1(container_of(intp, struct foo, a) == &foo);
ok1(container_of(charp, struct foo, b) == &foo);
+ ok1(container_of_or_null(intp, struct foo, a) == &foo);
+ ok1(container_of_or_null(charp, struct foo, b) == &foo);
+ ok1(container_of_or_null((int *)NULL, struct foo, a) == NULL);
+ ok1(container_of_or_null((char *)NULL, struct foo, b) == NULL);
ok1(container_of_var(intp, &foo, a) == &foo);
ok1(container_of_var(charp, &foo, b) == &foo);
ok1(container_off(struct foo, a) == 0);
ok1(container_off(struct foo, b) == offsetof(struct foo, b));
+ ok1(container_off_var(&foo, a) == 0);
+ ok1(container_off_var(&foo, b) == offsetof(struct foo, b));
return exit_status();
}
deleted file mode 100644
@@ -113,9 +113,17 @@ static inline uint64_t bswap_64(uint64_t val)
#elif HAVE_LITTLE_ENDIAN && HAVE_BIG_ENDIAN
#error "Can't compile for both big and little endian."
#elif HAVE_LITTLE_ENDIAN
+#ifndef __BYTE_ORDER
#define __BYTE_ORDER __LITTLE_ENDIAN
+#elif __BYTE_ORDER != __LITTLE_ENDIAN
+#error "__BYTE_ORDER already defined, but not equal to __LITTLE_ENDIAN"
+#endif
#elif HAVE_BIG_ENDIAN
+#ifndef __BYTE_ORDER
#define __BYTE_ORDER __BIG_ENDIAN
+#elif __BYTE_ORDER != __BIG_ENDIAN
+#error "__BYTE_ORDER already defined, but not equal to __BIG_ENDIAN"
+#endif
#endif
@@ -3,7 +3,7 @@
#include <stddef.h>
#include <ccan/tap/tap.h>
-int main(int argc, char *argv[])
+int main(void)
{
union {
uint64_t u64;
@@ -18,9 +18,6 @@ int main(int argc, char *argv[])
unsigned char u16_bytes[2];
} u16;
- (void)argc;
- (void)argv;
-
plan_tests(48);
/* Straight swap tests. */
@@ -82,7 +82,7 @@ static bool some_test(size_t n, bool is_less)
item = &items[i];
item->v = rand();
- /* printf("pushing %d\n", item->v); */
+ printf("pushing %d\n", item->v);
heap_push(h, item);
if (!heap_ok(h, is_less ? __less : __more, 0))
return false;
@@ -104,7 +104,7 @@ static bool some_test(size_t n, bool is_less)
item = heap_pop(h);
if (!heap_ok(h, is_less ? __less : __more, 0))
return false;
- /* printf("popped %d\n", item->v); */
+ printf("popped %d\n", item->v);
if (i > 0) {
if (is_less) {
if (less(item, prev))
@@ -1,6 +1,6 @@
+#include "config.h"
#include <stdio.h>
#include <string.h>
-#include "config.h"
/**
* list - double linked list routines
@@ -31,7 +31,7 @@
* {
* struct parent p;
* struct child *c;
- * unsigned int i;
+ * int i;
*
* if (argc < 2)
* errx(1, "Usage: %s parent children...", argv[0]);
@@ -62,7 +62,9 @@ int main(int argc, char *argv[])
return 1;
if (strcmp(argv[1], "depends") == 0) {
+ printf("ccan/str\n");
printf("ccan/container_of\n");
+ printf("ccan/check_type\n");
return 0;
}
@@ -1,8 +1,10 @@
/* Licensed under BSD-MIT - see LICENSE file for details */
#ifndef CCAN_LIST_H
#define CCAN_LIST_H
+//#define CCAN_LIST_DEBUG 1
#include <stdbool.h>
#include <assert.h>
+#include <ccan/str/str.h>
#include <ccan/container_of/container_of.h>
#include <ccan/check_type/check_type.h>
@@ -88,12 +90,13 @@ struct list_head *list_check(const struct list_head *h, const char *abortstr);
struct list_node *list_check_node(const struct list_node *n,
const char *abortstr);
+#define LIST_LOC __FILE__ ":" stringify(__LINE__)
#ifdef CCAN_LIST_DEBUG
-#define list_debug(h) list_check((h), __func__)
-#define list_debug_node(n) list_check_node((n), __func__)
+#define list_debug(h, loc) list_check((h), loc)
+#define list_debug_node(n, loc) list_check_node((n), loc)
#else
-#define list_debug(h) (h)
-#define list_debug_node(n) (n)
+#define list_debug(h, loc) ((void)loc, h)
+#define list_debug_node(n, loc) ((void)loc, n)
#endif
/**
@@ -108,7 +111,7 @@ struct list_node *list_check_node(const struct list_node *n,
* Example:
* static struct list_head my_list = LIST_HEAD_INIT(my_list);
*/
-#define LIST_HEAD_INIT(name) { { &name.n, &name.n } }
+#define LIST_HEAD_INIT(name) { { &(name).n, &(name).n } }
/**
* LIST_HEAD - define and initialize an empty list_head
@@ -142,6 +145,48 @@ static inline void list_head_init(struct list_head *h)
h->n.next = h->n.prev = &h->n;
}
+/**
+ * list_node_init - initialize a list_node
+ * @n: the list_node to link to itself.
+ *
+ * You don't need to use this normally! But it lets you list_del(@n)
+ * safely.
+ */
+static inline void list_node_init(struct list_node *n)
+{
+ n->next = n->prev = n;
+}
+
+/**
+ * list_add_after - add an entry after an existing node in a linked list
+ * @h: the list_head to add the node to (for debugging)
+ * @p: the existing list_node to add the node after
+ * @n: the new list_node to add to the list.
+ *
+ * The existing list_node must already be a member of the list.
+ * The new list_node does not need to be initialized; it will be overwritten.
+ *
+ * Example:
+ * struct child c1, c2, c3;
+ * LIST_HEAD(h);
+ *
+ * list_add_tail(&h, &c1.list);
+ * list_add_tail(&h, &c3.list);
+ * list_add_after(&h, &c1.list, &c2.list);
+ */
+#define list_add_after(h, p, n) list_add_after_(h, p, n, LIST_LOC)
+static inline void list_add_after_(struct list_head *h,
+ struct list_node *p,
+ struct list_node *n,
+ const char *abortstr)
+{
+ n->next = p->next;
+ n->prev = p;
+ p->next->prev = n;
+ p->next = n;
+ (void)list_debug(h, abortstr);
+}
+
/**
* list_add - add an entry at the start of a linked list.
* @h: the list_head to add the node to
@@ -155,51 +200,40 @@ static inline void list_head_init(struct list_head *h)
* list_add(&parent->children, &child->list);
* parent->num_children++;
*/
-static inline void list_add(struct list_head *h, struct list_node *n)
+#define list_add(h, n) list_add_(h, n, LIST_LOC)
+static inline void list_add_(struct list_head *h,
+ struct list_node *n,
+ const char *abortstr)
{
- n->next = h->n.next;
- n->prev = &h->n;
- h->n.next->prev = n;
- h->n.next = n;
- (void)list_debug(h);
+ list_add_after_(h, &h->n, n, abortstr);
}
/**
- * list_add_before - add an entry before another entry.
- * @h: the list_head to add the node to (we use it for debug purposes, can be NULL)
- * @p: the list_node of the other entry
- * @n: the list_node to add to the list.
+ * list_add_before - add an entry before an existing node in a linked list
+ * @h: the list_head to add the node to (for debugging)
+ * @p: the existing list_node to add the node before
+ * @n: the new list_node to add to the list.
*
- * The list_node does not need to be initialized; it will be overwritten.
+ * The existing list_node must already be a member of the list.
+ * The new list_node does not need to be initialized; it will be overwritten.
+ *
+ * Example:
+ * list_head_init(&h);
+ * list_add_tail(&h, &c1.list);
+ * list_add_tail(&h, &c3.list);
+ * list_add_before(&h, &c3.list, &c2.list);
*/
-static inline void list_add_before(struct list_head *h, struct list_node *p,
- struct list_node *n)
+#define list_add_before(h, p, n) list_add_before_(h, p, n, LIST_LOC)
+static inline void list_add_before_(struct list_head *h,
+ struct list_node *p,
+ struct list_node *n,
+ const char *abortstr)
{
n->next = p;
n->prev = p->prev;
+ p->prev->next = n;
p->prev = n;
- n->prev->next = n;
- if (h)
- (void)list_debug(h);
-}
-
-/**
- * list_add_after - add an entry after another entry.
- * @h: the list_head to add the node to (we use it for debug purposes, can be NULL)
- * @p: the list_node of the other entry
- * @n: the list_node to add to the list.
- *
- * The list_node does not need to be initialized; it will be overwritten.
- */
-static inline void list_add_after(struct list_head *h, struct list_node *p,
- struct list_node *n)
-{
- n->next = p->next;
- n->prev = p;
- p->next = n;
- n->next->prev = n;
- if (h)
- (void)list_debug(h);
+ (void)list_debug(h, abortstr);
}
/**
@@ -212,13 +246,12 @@ static inline void list_add_after(struct list_head *h, struct list_node *p,
* list_add_tail(&parent->children, &child->list);
* parent->num_children++;
*/
-static inline void list_add_tail(struct list_head *h, struct list_node *n)
+#define list_add_tail(h, n) list_add_tail_(h, n, LIST_LOC)
+static inline void list_add_tail_(struct list_head *h,
+ struct list_node *n,
+ const char *abortstr)
{
- n->next = &h->n;
- n->prev = h->n.prev;
- h->n.prev->next = n;
- h->n.prev = n;
- (void)list_debug(h);
+ list_add_before_(h, &h->n, n, abortstr);
}
/**
@@ -230,11 +263,33 @@ static inline void list_add_tail(struct list_head *h, struct list_node *n)
* Example:
* assert(list_empty(&parent->children) == (parent->num_children == 0));
*/
-static inline bool list_empty(const struct list_head *h)
+#define list_empty(h) list_empty_(h, LIST_LOC)
+static inline bool list_empty_(const struct list_head *h, const char* abortstr)
+{
+ (void)list_debug(h, abortstr);
+ return h->n.next == &h->n;
+}
+
+/**
+ * list_empty_nodebug - is a list empty (and don't perform debug checks)?
+ * @h: the list_head
+ *
+ * If the list is empty, returns true.
+ * This differs from list_empty() in that if CCAN_LIST_DEBUG is set it
+ * will NOT perform debug checks. Only use this function if you REALLY
+ * know what you're doing.
+ *
+ * Example:
+ * assert(list_empty_nodebug(&parent->children) == (parent->num_children == 0));
+ */
+#ifndef CCAN_LIST_DEBUG
+#define list_empty_nodebug(h) list_empty(h)
+#else
+static inline bool list_empty_nodebug(const struct list_head *h)
{
- (void)list_debug(h);
return h->n.next == &h->n;
}
+#endif
/**
* list_empty_nocheck - is a list empty?
@@ -259,15 +314,16 @@ static inline bool list_empty_nocheck(const struct list_head *h)
* another list, but not deleted again.
*
* See also:
- * list_del_from()
+ * list_del_from(), list_del_init()
*
* Example:
* list_del(&child->list);
* parent->num_children--;
*/
-static inline void list_del(struct list_node *n)
+#define list_del(n) list_del_(n, LIST_LOC)
+static inline void list_del_(struct list_node *n, const char* abortstr)
{
- (void)list_debug_node(n);
+ (void)list_debug_node(n, abortstr);
n->next->prev = n->prev;
n->prev->next = n->next;
#ifdef CCAN_LIST_DEBUG
@@ -276,6 +332,27 @@ static inline void list_del(struct list_node *n)
#endif
}
+/**
+ * list_del_init - delete a node, and reset it so it can be deleted again.
+ * @n: the list_node to be deleted.
+ *
+ * list_del(@n) or list_del_init() again after this will be safe,
+ * which can be useful in some cases.
+ *
+ * See also:
+ * list_del_from(), list_del()
+ *
+ * Example:
+ * list_del_init(&child->list);
+ * parent->num_children--;
+ */
+#define list_del_init(n) list_del_init_(n, LIST_LOC)
+static inline void list_del_init_(struct list_node *n, const char *abortstr)
+{
+ list_del_(n, abortstr);
+ list_node_init(n);
+}
+
/**
* list_del_from - delete an entry from a known linked list.
* @h: the list_head the node is in.
@@ -306,6 +383,39 @@ static inline void list_del_from(struct list_head *h, struct list_node *n)
list_del(n);
}
+/**
+ * list_swap - swap out an entry from an (unknown) linked list for a new one.
+ * @o: the list_node to replace from the list.
+ * @n: the list_node to insert in place of the old one.
+ *
+ * Note that this leaves @o in an undefined state; it can be added to
+ * another list, but not deleted/swapped again.
+ *
+ * See also:
+ * list_del()
+ *
+ * Example:
+ * struct child x1, x2;
+ * LIST_HEAD(xh);
+ *
+ * list_add(&xh, &x1.list);
+ * list_swap(&x1.list, &x2.list);
+ */
+#define list_swap(o, n) list_swap_(o, n, LIST_LOC)
+static inline void list_swap_(struct list_node *o,
+ struct list_node *n,
+ const char* abortstr)
+{
+ (void)list_debug_node(o, abortstr);
+ *n = *o;
+ n->next->prev = n;
+ n->prev->next = n;
+#ifdef CCAN_LIST_DEBUG
+ /* Catch use-after-del. */
+ o->next = o->prev = NULL;
+#endif
+}
+
/**
* list_entry - convert a list_node back into the structure containing it.
* @n: the list_node
@@ -346,14 +456,23 @@ static inline const void *list_top_(const struct list_head *h, size_t off)
}
/**
- * list_pop - get the first entry in a list and dequeue it
+ * list_pop - remove the first entry in a list
* @h: the list_head
* @type: the type of the entry
* @member: the list_node member of the type
+ *
+ * If the list is empty, returns NULL.
+ *
+ * Example:
+ * struct child *one;
+ * one = list_pop(&parent->children, struct child, list);
+ * if (!one)
+ * printf("Empty list!\n");
*/
#define list_pop(h, type, member) \
((type *)list_pop_((h), list_off_(type, member)))
-static inline const void *list_pop_(struct list_head *h, size_t off)
+
+static inline const void *list_pop_(const struct list_head *h, size_t off)
{
struct list_node *n;
@@ -418,9 +537,29 @@ static inline const void *list_tail_(const struct list_head *h, size_t off)
* printf("Name: %s\n", child->name);
*/
#define list_for_each_rev(h, i, member) \
- for (i = container_of_var(list_debug(h)->n.prev, i, member); \
- &i->member != &(h)->n; \
- i = container_of_var(i->member.prev, i, member))
+ list_for_each_rev_off(h, i, list_off_var_(i, member))
+
+/**
+ * list_for_each_rev_safe - iterate through a list backwards,
+ * maybe during deletion
+ * @h: the list_head
+ * @i: the structure containing the list_node
+ * @nxt: the structure containing the list_node
+ * @member: the list_node member of the structure
+ *
+ * This is a convenient wrapper to iterate @i over the entire list backwards.
+ * It's a for loop, so you can break and continue as normal. The extra
+ * variable * @nxt is used to hold the next element, so you can delete @i
+ * from the list.
+ *
+ * Example:
+ * struct child *next;
+ * list_for_each_rev_safe(&parent->children, child, next, list) {
+ * printf("Name: %s\n", child->name);
+ * }
+ */
+#define list_for_each_rev_safe(h, i, nxt, member) \
+ list_for_each_rev_safe_off(h, i, nxt, list_off_var_(i, member))
/**
* list_for_each_safe - iterate through a list, maybe during deletion
@@ -434,7 +573,6 @@ static inline const void *list_tail_(const struct list_head *h, size_t off)
* @nxt is used to hold the next element, so you can delete @i from the list.
*
* Example:
- * struct child *next;
* list_for_each_safe(&parent->children, child, next, list) {
* list_del(&child->list);
* parent->num_children--;
@@ -443,6 +581,130 @@ static inline const void *list_tail_(const struct list_head *h, size_t off)
#define list_for_each_safe(h, i, nxt, member) \
list_for_each_safe_off(h, i, nxt, list_off_var_(i, member))
+/**
+ * list_next - get the next entry in a list
+ * @h: the list_head
+ * @i: a pointer to an entry in the list.
+ * @member: the list_node member of the structure
+ *
+ * If @i was the last entry in the list, returns NULL.
+ *
+ * Example:
+ * struct child *second;
+ * second = list_next(&parent->children, first, list);
+ * if (!second)
+ * printf("No second child!\n");
+ */
+#define list_next(h, i, member) \
+ ((list_typeof(i))list_entry_or_null(list_debug(h, \
+ __FILE__ ":" stringify(__LINE__)), \
+ (i)->member.next, \
+ list_off_var_((i), member)))
+
+/**
+ * list_prev - get the previous entry in a list
+ * @h: the list_head
+ * @i: a pointer to an entry in the list.
+ * @member: the list_node member of the structure
+ *
+ * If @i was the first entry in the list, returns NULL.
+ *
+ * Example:
+ * first = list_prev(&parent->children, second, list);
+ * if (!first)
+ * printf("Can't go back to first child?!\n");
+ */
+#define list_prev(h, i, member) \
+ ((list_typeof(i))list_entry_or_null(list_debug(h, \
+ __FILE__ ":" stringify(__LINE__)), \
+ (i)->member.prev, \
+ list_off_var_((i), member)))
+
+/**
+ * list_append_list - empty one list onto the end of another.
+ * @to: the list to append into
+ * @from: the list to empty.
+ *
+ * This takes the entire contents of @from and moves it to the end of
+ * @to. After this @from will be empty.
+ *
+ * Example:
+ * struct list_head adopter;
+ *
+ * list_append_list(&adopter, &parent->children);
+ * assert(list_empty(&parent->children));
+ * parent->num_children = 0;
+ */
+#define list_append_list(t, f) list_append_list_(t, f, \
+ __FILE__ ":" stringify(__LINE__))
+static inline void list_append_list_(struct list_head *to,
+ struct list_head *from,
+ const char *abortstr)
+{
+ struct list_node *from_tail = list_debug(from, abortstr)->n.prev;
+ struct list_node *to_tail = list_debug(to, abortstr)->n.prev;
+
+ /* Sew in head and entire list. */
+ to->n.prev = from_tail;
+ from_tail->next = &to->n;
+ to_tail->next = &from->n;
+ from->n.prev = to_tail;
+
+ /* Now remove head. */
+ list_del(&from->n);
+ list_head_init(from);
+}
+
+/**
+ * list_prepend_list - empty one list into the start of another.
+ * @to: the list to prepend into
+ * @from: the list to empty.
+ *
+ * This takes the entire contents of @from and moves it to the start
+ * of @to. After this @from will be empty.
+ *
+ * Example:
+ * list_prepend_list(&adopter, &parent->children);
+ * assert(list_empty(&parent->children));
+ * parent->num_children = 0;
+ */
+#define list_prepend_list(t, f) list_prepend_list_(t, f, LIST_LOC)
+static inline void list_prepend_list_(struct list_head *to,
+ struct list_head *from,
+ const char *abortstr)
+{
+ struct list_node *from_tail = list_debug(from, abortstr)->n.prev;
+ struct list_node *to_head = list_debug(to, abortstr)->n.next;
+
+ /* Sew in head and entire list. */
+ to->n.next = &from->n;
+ from->n.prev = &to->n;
+ to_head->prev = from_tail;
+ from_tail->next = to_head;
+
+ /* Now remove head. */
+ list_del(&from->n);
+ list_head_init(from);
+}
+
+/* internal macros, do not use directly */
+#define list_for_each_off_dir_(h, i, off, dir) \
+ for (i = list_node_to_off_(list_debug(h, LIST_LOC)->n.dir, \
+ (off)); \
+ list_node_from_off_((void *)i, (off)) != &(h)->n; \
+ i = list_node_to_off_(list_node_from_off_((void *)i, (off))->dir, \
+ (off)))
+
+#define list_for_each_safe_off_dir_(h, i, nxt, off, dir) \
+ for (i = list_node_to_off_(list_debug(h, LIST_LOC)->n.dir, \
+ (off)), \
+ nxt = list_node_to_off_(list_node_from_off_(i, (off))->dir, \
+ (off)); \
+ list_node_from_off_(i, (off)) != &(h)->n; \
+ i = nxt, \
+ nxt = list_node_to_off_(list_node_from_off_(i, (off))->dir, \
+ (off)))
+
/**
* list_for_each_off - iterate through a list of memory regions.
* @h: the list_head
@@ -454,9 +716,9 @@ static inline const void *list_tail_(const struct list_head *h, size_t off)
* so you can break and continue as normal.
*
* WARNING! Being the low-level macro that it is, this wrapper doesn't know
- * nor care about the type of @i. The only assumtion made is that @i points
+ * nor care about the type of @i. The only assumption made is that @i points
* to a chunk of memory that at some @offset, relative to @i, contains a
- * properly filled `struct node_list' which in turn contains pointers to
+ * properly filled `struct list_node' which in turn contains pointers to
* memory chunks and it's turtles all the way down. With all that in mind
* remember that given the wrong pointer/offset couple this macro will
* happily churn all you memory until SEGFAULT stops it, in other words
@@ -473,10 +735,18 @@ static inline const void *list_tail_(const struct list_head *h, size_t off)
* printf("Name: %s\n", child->name);
*/
#define list_for_each_off(h, i, off) \
- for (i = list_node_to_off_(list_debug(h)->n.next, (off)); \
- list_node_from_off_((void *)i, (off)) != &(h)->n; \
- i = list_node_to_off_(list_node_from_off_((void *)i, (off))->next, \
- (off)))
+ list_for_each_off_dir_((h),(i),(off),next)
+
+/**
+ * list_for_each_rev_off - iterate through a list of memory regions backwards
+ * @h: the list_head
+ * @i: the pointer to a memory region which contains list node data.
+ * @off: offset(relative to @i) at which list node data resides.
+ *
+ * See list_for_each_off for details
+ */
+#define list_for_each_rev_off(h, i, off) \
+ list_for_each_off_dir_((h),(i),(off),prev)
/**
* list_for_each_safe_off - iterate through a list of memory regions, maybe
@@ -495,14 +765,26 @@ static inline const void *list_tail_(const struct list_head *h, size_t off)
* printf("Name: %s\n", child->name);
*/
#define list_for_each_safe_off(h, i, nxt, off) \
- for (i = list_node_to_off_(list_debug(h)->n.next, (off)), \
- nxt = list_node_to_off_(list_node_from_off_(i, (off))->next, \
- (off)); \
- list_node_from_off_(i, (off)) != &(h)->n; \
- i = nxt, \
- nxt = list_node_to_off_(list_node_from_off_(i, (off))->next, \
- (off)))
+ list_for_each_safe_off_dir_((h),(i),(nxt),(off),next)
+/**
+ * list_for_each_rev_safe_off - iterate backwards through a list of
+ * memory regions, maybe during deletion
+ * @h: the list_head
+ * @i: the pointer to a memory region which contains list node data.
+ * @nxt: the structure containing the list_node
+ * @off: offset(relative to @i) at which list node data resides.
+ *
+ * For details see `list_for_each_rev_off' and `list_for_each_rev_safe'
+ * descriptions.
+ *
+ * Example:
+ * list_for_each_rev_safe_off(&parent->children, child,
+ * next, offsetof(struct child, list))
+ * printf("Name: %s\n", child->name);
+ */
+#define list_for_each_rev_safe_off(h, i, nxt, off) \
+ list_for_each_safe_off_dir_((h),(i),(nxt),(off),prev)
/* Other -off variants. */
#define list_entry_off(n, type, off) \
@@ -542,42 +824,19 @@ static inline struct list_node *list_node_from_off_(void *ptr, size_t off)
(container_off_var(var, member) + \
check_type(var->member, struct list_node))
-
#if HAVE_TYPEOF
#define list_typeof(var) typeof(var)
#else
#define list_typeof(var) void *
#endif
-
/* Returns member, or NULL if at end of list. */
static inline void *list_entry_or_null(const struct list_head *h,
- const struct list_node *n,
- size_t off)
+ const struct list_node *n,
+ size_t off)
{
- if (n == &h->n)
- return NULL;
- return (char *)n - off;
+ if (n == &h->n)
+ return NULL;
+ return (char *)n - off;
}
-
-/**
- * list_next - get the next entry in a list
- * @h: the list_head
- * @i: a pointer to an entry in the list.
- * @member: the list_node member of the structure
- *
- * If @i was the last entry in the list, returns NULL.
- *
- * Example:
- * struct child *second;
- * second = list_next(&parent->children, first, list);
- * if (!second)
- * printf("No second child!\n");
- */
-#define list_next(h, i, member) \
- ((list_typeof(i))list_entry_or_null(list_debug(h), \
- (i)->member.next, \
- list_off_var_((i), member)))
-
-
#endif /* CCAN_LIST_H */
new file mode 100644
@@ -0,0 +1,60 @@
+/* Check that CCAN_LIST_DEBUG works */
+#include <setjmp.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <err.h>
+
+/* We don't actually want it to exit... */
+static jmp_buf aborted;
+#define abort() longjmp(aborted, 1)
+
+#define fprintf my_fprintf
+static char printf_buffer[1000];
+
+static int my_fprintf(FILE *stream, const char *format, ...)
+{
+ va_list ap;
+ int ret;
+ (void)stream;
+ va_start(ap, format);
+ ret = vsprintf(printf_buffer, format, ap);
+ va_end(ap);
+ return ret;
+}
+
+#define CCAN_LIST_DEBUG 1
+#include <ccan/list/list.h>
+#include <ccan/tap/tap.h>
+#include <ccan/list/list.c>
+
+int main(void)
+{
+ struct list_head list;
+ struct list_node n1;
+ char expect[100];
+
+ plan_tests(2);
+ /* Empty list. */
+ list.n.next = &list.n;
+ list.n.prev = &list.n;
+ ok1(list_check(&list, NULL) == &list);
+
+ /* Bad back ptr */
+ list.n.prev = &n1;
+
+ /* Aborting version. */
+ sprintf(expect, "run-CCAN_LIST_DEBUG.c:51: prev corrupt in node %p (0) of %p\n",
+ &list, &list);
+ if (setjmp(aborted) == 0) {
+ assert(list_empty(&list));
+ fail("list_empty on empty with bad back ptr didn't fail!");
+ } else {
+ /* __FILE__ might give full path. */
+ int prep = strlen(printf_buffer) - strlen(expect);
+ ok1(prep >= 0 && strcmp(printf_buffer + prep, expect) == 0);
+ }
+
+ return exit_status();
+}
@@ -16,11 +16,9 @@ static int my_fprintf(FILE *stream, const char *format, ...)
{
va_list ap;
int ret;
-
(void)stream;
-
va_start(ap, format);
- ret = vsnprintf(printf_buffer, sizeof(printf_buffer), format, ap);
+ ret = vsprintf(printf_buffer, format, ap);
va_end(ap);
return ret;
}
@@ -29,15 +27,12 @@ static int my_fprintf(FILE *stream, const char *format, ...)
#include <ccan/tap/tap.h>
#include <ccan/list/list.c>
-int main(int argc, char *argv[])
+int main(void)
{
struct list_head list;
struct list_node n1;
char expect[100];
- (void)argc;
- (void)argv;
-
plan_tests(9);
/* Empty list. */
list.n.next = &list.n;
new file mode 100644
@@ -0,0 +1,27 @@
+#include <ccan/list/list.h>
+#include <ccan/tap/tap.h>
+#include <ccan/list/list.c>
+#include "helper.h"
+
+struct child {
+ const char *name;
+ struct list_node list;
+};
+
+int main(void)
+{
+ struct child c1, c2;
+ struct list_head list = LIST_HEAD_INIT(list);
+
+ plan_tests(1);
+
+ list_add(&list, &c1.list);
+ list_add_tail(list_check(&list, "Bad list!"), &c2.list);
+ list_del_from(list_check(&list, "Bad list!"),
+ list_check_node(&c2.list, "Bad node!"));
+ list_del_from(list_check(&list, "Bad list!"),
+ list_check_node(&c1.list, "Bad node!"));
+ ok1(list_empty(list_check(&list, "Bad emptied list")));
+
+ return exit_status();
+}
@@ -7,16 +7,13 @@
#include <unistd.h>
#include <signal.h>
-int main(int argc, char *argv[])
+int main(void)
{
struct list_head list1, list2;
struct list_node n1, n2, n3;
pid_t child;
int status;
- (void)argc;
- (void)argv;
-
plan_tests(1);
list_head_init(&list1);
list_head_init(&list2);
@@ -28,7 +25,6 @@ int main(int argc, char *argv[])
if (child) {
wait(&status);
} else {
- close(2); /* Close stderr so we don't print confusing assert */
/* This should abort. */
list_del_from(&list1, &n3);
exit(0);
new file mode 100644
@@ -0,0 +1,65 @@
+#include <ccan/list/list.h>
+#include <ccan/tap/tap.h>
+#include <ccan/list/list.c>
+#include "helper.h"
+
+struct parent {
+ const char *name;
+ unsigned int num_children;
+ struct list_head children;
+};
+
+struct child {
+ const char *name;
+ struct list_node list;
+};
+
+int main(void)
+{
+ struct parent parent;
+ struct child c1, c2, c3;
+ const struct parent *p;
+ const struct child *c;
+
+ plan_tests(20);
+ parent.num_children = 0;
+ list_head_init(&parent.children);
+
+ c1.name = "c1";
+ list_add(&parent.children, &c1.list);
+
+ ok1(list_next(&parent.children, &c1, list) == NULL);
+ ok1(list_prev(&parent.children, &c1, list) == NULL);
+
+ c2.name = "c2";
+ list_add_tail(&parent.children, &c2.list);
+
+ ok1(list_next(&parent.children, &c1, list) == &c2);
+ ok1(list_prev(&parent.children, &c1, list) == NULL);
+ ok1(list_next(&parent.children, &c2, list) == NULL);
+ ok1(list_prev(&parent.children, &c2, list) == &c1);
+
+ c3.name = "c3";
+ list_add_tail(&parent.children, &c3.list);
+
+ ok1(list_next(&parent.children, &c1, list) == &c2);
+ ok1(list_prev(&parent.children, &c1, list) == NULL);
+ ok1(list_next(&parent.children, &c2, list) == &c3);
+ ok1(list_prev(&parent.children, &c2, list) == &c1);
+ ok1(list_next(&parent.children, &c3, list) == NULL);
+ ok1(list_prev(&parent.children, &c3, list) == &c2);
+
+ /* Const variants */
+ p = &parent;
+ c = &c2;
+ ok1(list_next(&p->children, &c1, list) == &c2);
+ ok1(list_prev(&p->children, &c1, list) == NULL);
+ ok1(list_next(&p->children, c, list) == &c3);
+ ok1(list_prev(&p->children, c, list) == &c1);
+ ok1(list_next(&parent.children, c, list) == &c3);
+ ok1(list_prev(&parent.children, c, list) == &c1);
+ ok1(list_next(&p->children, &c3, list) == NULL);
+ ok1(list_prev(&p->children, &c3, list) == &c2);
+
+ return exit_status();
+}
new file mode 100644
@@ -0,0 +1,111 @@
+#include <ccan/list/list.h>
+#include <ccan/tap/tap.h>
+#include <ccan/list/list.c>
+#include <stdarg.h>
+
+static bool list_expect(struct list_head *h, ...)
+{
+ va_list ap;
+ struct list_node *n = &h->n, *expected;
+
+ va_start(ap, h);
+ while ((expected = va_arg(ap, struct list_node *)) != NULL) {
+ n = n->next;
+ if (n != expected)
+ return false;
+ }
+ return (n->next == &h->n);
+}
+
+int main(void)
+{
+ struct list_head h1, h2;
+ struct list_node n[4];
+
+ plan_tests(40);
+
+ list_head_init(&h1);
+ list_head_init(&h2);
+
+ /* Append an empty list to an empty list. */
+ list_append_list(&h1, &h2);
+ ok1(list_empty(&h1));
+ ok1(list_empty(&h2));
+ ok1(list_check(&h1, NULL));
+ ok1(list_check(&h2, NULL));
+
+ /* Prepend an empty list to an empty list. */
+ list_prepend_list(&h1, &h2);
+ ok1(list_empty(&h1));
+ ok1(list_empty(&h2));
+ ok1(list_check(&h1, NULL));
+ ok1(list_check(&h2, NULL));
+
+ /* Append an empty list to a non-empty list */
+ list_add(&h1, &n[0]);
+ list_append_list(&h1, &h2);
+ ok1(list_empty(&h2));
+ ok1(list_check(&h1, NULL));
+ ok1(list_check(&h2, NULL));
+ ok1(list_expect(&h1, &n[0], NULL));
+
+ /* Prepend an empty list to a non-empty list */
+ list_prepend_list(&h1, &h2);
+ ok1(list_empty(&h2));
+ ok1(list_check(&h1, NULL));
+ ok1(list_check(&h2, NULL));
+ ok1(list_expect(&h1, &n[0], NULL));
+
+ /* Append a non-empty list to an empty list. */
+ list_append_list(&h2, &h1);
+ ok1(list_empty(&h1));
+ ok1(list_check(&h1, NULL));
+ ok1(list_check(&h2, NULL));
+ ok1(list_expect(&h2, &n[0], NULL));
+
+ /* Prepend a non-empty list to an empty list. */
+ list_prepend_list(&h1, &h2);
+ ok1(list_empty(&h2));
+ ok1(list_check(&h1, NULL));
+ ok1(list_check(&h2, NULL));
+ ok1(list_expect(&h1, &n[0], NULL));
+
+ /* Prepend a non-empty list to non-empty list. */
+ list_add(&h2, &n[1]);
+ list_prepend_list(&h1, &h2);
+ ok1(list_empty(&h2));
+ ok1(list_check(&h1, NULL));
+ ok1(list_check(&h2, NULL));
+ ok1(list_expect(&h1, &n[1], &n[0], NULL));
+
+ /* Append a non-empty list to non-empty list. */
+ list_add(&h2, &n[2]);
+ list_append_list(&h1, &h2);
+ ok1(list_empty(&h2));
+ ok1(list_check(&h1, NULL));
+ ok1(list_check(&h2, NULL));
+ ok1(list_expect(&h1, &n[1], &n[0], &n[2], NULL));
+
+ /* Prepend a 2-entry list to a 2-entry list. */
+ list_del_from(&h1, &n[2]);
+ list_add(&h2, &n[2]);
+ list_add_tail(&h2, &n[3]);
+ list_prepend_list(&h1, &h2);
+ ok1(list_empty(&h2));
+ ok1(list_check(&h1, NULL));
+ ok1(list_check(&h2, NULL));
+ ok1(list_expect(&h1, &n[2], &n[3], &n[1], &n[0], NULL));
+
+ /* Append a 2-entry list to a 2-entry list. */
+ list_del_from(&h1, &n[2]);
+ list_del_from(&h1, &n[3]);
+ list_add(&h2, &n[2]);
+ list_add_tail(&h2, &n[3]);
+ list_append_list(&h1, &h2);
+ ok1(list_empty(&h2));
+ ok1(list_check(&h1, NULL));
+ ok1(list_check(&h2, NULL));
+ ok1(list_expect(&h1, &n[1], &n[0], &n[2], &n[3], NULL));
+
+ return exit_status();
+}
@@ -19,7 +19,7 @@ static LIST_HEAD(static_list);
#define ref(obj, counter) ((counter)++, (obj))
-int main(int argc, char *argv[])
+int main(void)
{
struct parent parent;
struct child c1, c2, c3, *c, *n;
@@ -28,9 +28,6 @@ int main(int argc, char *argv[])
node_count = 0;
struct list_head list = LIST_HEAD_INIT(list);
- (void)argc;
- (void)argv;
-
plan_tests(74);
/* Test LIST_HEAD, LIST_HEAD_INIT, list_empty and check_list */
ok1(list_empty(ref(&static_list, static_count)));
@@ -17,19 +17,17 @@ struct child {
static LIST_HEAD(static_list);
-int main(int argc, char *argv[])
+int main(void)
{
struct parent parent;
- struct child c1, c2, c3, *c, *n;
+ struct child c1, c2, c3, x1, *c, *n;
unsigned int i;
struct list_head list = LIST_HEAD_INIT(list);
opaque_t *q, *nq;
struct list_head opaque_list = LIST_HEAD_INIT(opaque_list);
+ LIST_HEAD(rev);
- (void)argc;
- (void)argv;
-
- plan_tests(65);
+ plan_tests(92);
/* Test LIST_HEAD, LIST_HEAD_INIT, list_empty and check_list */
ok1(list_empty(&static_list));
ok1(list_check(&static_list, NULL));
@@ -89,6 +87,11 @@ int main(int argc, char *argv[])
/* Test list_top */
ok1(list_top(&parent.children, struct child, list) == &c1);
+ /* Test list_pop */
+ ok1(list_pop(&parent.children, struct child, list) == &c1);
+ ok1(list_top(&parent.children, struct child, list) == &c2);
+ list_add(&parent.children, &c1.list);
+
/* Test list_tail */
ok1(list_tail(&parent.children, struct child, list) == &c3);
@@ -147,6 +150,10 @@ int main(int argc, char *argv[])
list_del_from(&parent.children, &c->list);
break;
}
+
+ /* prepare for list_for_each_rev_safe test */
+ list_add(&rev, &c->list);
+
ok1(list_check(&parent.children, NULL));
if (i > 2)
break;
@@ -154,6 +161,43 @@ int main(int argc, char *argv[])
ok1(i == 3);
ok1(list_empty(&parent.children));
+ /* Test list_for_each_rev_safe, list_del and list_del_from. */
+ i = 0;
+ list_for_each_rev_safe(&rev, c, n, list) {
+ switch (i++) {
+ case 0:
+ ok1(c == &c1);
+ list_del(&c->list);
+ break;
+ case 1:
+ ok1(c == &c2);
+ list_del_from(&rev, &c->list);
+ break;
+ case 2:
+ ok1(c == &c3);
+ list_del_from(&rev, &c->list);
+ break;
+ }
+ ok1(list_check(&rev, NULL));
+ if (i > 2)
+ break;
+ }
+ ok1(i == 3);
+ ok1(list_empty(&rev));
+
+ /* Test list_node_init: safe to list_del after this. */
+ list_node_init(&c->list);
+ list_del(&c->list);
+
+ /* Test list_del_init */
+ list_add(&parent.children, &c->list);
+ ok1(!list_empty(&parent.children));
+ list_del_init(&c->list);
+ ok1(list_empty(&parent.children));
+ /* We can call this as many times as we like. */
+ list_del_init(&c->list);
+ list_del_init(&c->list);
+
/* Test list_for_each_off. */
list_add_tail(&opaque_list,
(struct list_node *)create_opaque_blob());
@@ -197,8 +241,66 @@ int main(int argc, char *argv[])
ok1(i == 3);
ok1(list_empty(&opaque_list));
- /* Test list_top/list_tail on empty list. */
+ /* Test list_top/list_tail/list_pop on empty list. */
ok1(list_top(&parent.children, struct child, list) == NULL);
ok1(list_tail(&parent.children, struct child, list) == NULL);
+ ok1(list_pop(&parent.children, struct child, list) == NULL);
+
+ /* Test list_add_before and list_add_after */
+ list_add(&parent.children, &c1.list);
+ list_add_after(&parent.children, &c1.list, &c2.list);
+ ok1(list_check(&parent.children, "list_add_after"));
+
+ i = 0;
+ list_for_each(&parent.children, c, list) {
+ switch (i++) {
+ case 0:
+ ok1(c == &c1);
+ break;
+ case 1:
+ ok1(c == &c2);
+ break;
+ }
+ }
+ ok1(i == 2);
+
+ list_add_before(&parent.children, &c2.list, &c3.list);
+ ok1(list_check(&parent.children, "list_add_before"));
+
+ i = 0;
+ list_for_each(&parent.children, c, list) {
+ switch (i++) {
+ case 0:
+ ok1(c == &c1);
+ break;
+ case 1:
+ ok1(c == &c3);
+ break;
+ case 2:
+ ok1(c == &c2);
+ break;
+ }
+ }
+ ok1(i == 3);
+
+ /* test list_swap */
+ list_swap(&c3.list, &x1.list);
+ ok1(list_check(&parent.children, "list_swap"));
+ i = 0;
+ list_for_each(&parent.children, c, list) {
+ switch (i++) {
+ case 0:
+ ok1(c == &c1);
+ break;
+ case 1:
+ ok1(c == &x1);
+ break;
+ case 2:
+ ok1(c == &c2);
+ break;
+ }
+ }
+ ok1(i == 3);
+
return exit_status();
}
@@ -4,7 +4,7 @@
#include <stdlib.h>
#include <err.h>
-int __attribute__((const)) main(void)
+int main(void)
{
plan_tests(6);
@@ -3,7 +3,7 @@
#include <stdlib.h>
#include <err.h>
-int __attribute__((const)) main(void)
+int main(void)
{
plan_tests(16);
@@ -1,6 +1,6 @@
+#include "config.h"
#include <stdio.h>
#include <string.h>
-#include "config.h"
/**
* str - string helper routines
@@ -26,11 +26,11 @@
*
* int main(int argc, char *argv[])
* {
- * if (argv[1] && streq(argv[1], "--verbose"))
+ * if (argc > 1 && streq(argv[1], "--verbose"))
* printf("verbose set\n");
- * if (argv[1] && strstarts(argv[1], "--"))
+ * if (argc > 1 && strstarts(argv[1], "--"))
* printf("Some option set\n");
- * if (argv[1] && strends(argv[1], "cow-powers"))
+ * if (argc > 1 && strends(argv[1], "cow-powers"))
* printf("Magic option set\n");
* return 0;
* }
new file mode 100644
@@ -0,0 +1,108 @@
+/* CC0 (Public domain) - see LICENSE file for details */
+#include "config.h"
+#include <ccan/str/str_debug.h>
+#include <assert.h>
+#include <ctype.h>
+#include <string.h>
+
+#ifdef CCAN_STR_DEBUG
+/* Because we mug the real ones with macros, we need our own wrappers. */
+int str_isalnum(int i)
+{
+ assert(i >= -1 && i < 256);
+ return isalnum(i);
+}
+
+int str_isalpha(int i)
+{
+ assert(i >= -1 && i < 256);
+ return isalpha(i);
+}
+
+int str_isascii(int i)
+{
+ assert(i >= -1 && i < 256);
+ return isascii(i);
+}
+
+#if HAVE_ISBLANK
+int str_isblank(int i)
+{
+ assert(i >= -1 && i < 256);
+ return isblank(i);
+}
+#endif
+
+int str_iscntrl(int i)
+{
+ assert(i >= -1 && i < 256);
+ return iscntrl(i);
+}
+
+int str_isdigit(int i)
+{
+ assert(i >= -1 && i < 256);
+ return isdigit(i);
+}
+
+int str_isgraph(int i)
+{
+ assert(i >= -1 && i < 256);
+ return isgraph(i);
+}
+
+int str_islower(int i)
+{
+ assert(i >= -1 && i < 256);
+ return islower(i);
+}
+
+int str_isprint(int i)
+{
+ assert(i >= -1 && i < 256);
+ return isprint(i);
+}
+
+int str_ispunct(int i)
+{
+ assert(i >= -1 && i < 256);
+ return ispunct(i);
+}
+
+int str_isspace(int i)
+{
+ assert(i >= -1 && i < 256);
+ return isspace(i);
+}
+
+int str_isupper(int i)
+{
+ assert(i >= -1 && i < 256);
+ return isupper(i);
+}
+
+int str_isxdigit(int i)
+{
+ assert(i >= -1 && i < 256);
+ return isxdigit(i);
+}
+
+#undef strstr
+#undef strchr
+#undef strrchr
+
+char *str_strstr(const char *haystack, const char *needle)
+{
+ return strstr(haystack, needle);
+}
+
+char *str_strchr(const char *haystack, int c)
+{
+ return strchr(haystack, c);
+}
+
+char *str_strrchr(const char *haystack, int c)
+{
+ return strrchr(haystack, c);
+}
+#endif
@@ -94,13 +94,27 @@ size_t strcount(const char *haystack, const char *needle);
#if HAVE_TYPEOF
/* Only a simple type can have 0 assigned, so test that. */
#define STR_MAX_CHARS_TCHECK_(type_or_expr) \
- ({ typeof(type_or_expr) x = 0; (void)x; 0; })
+ (sizeof(({ typeof(type_or_expr) x = 0; x; }))*0)
#else
#define STR_MAX_CHARS_TCHECK_(type_or_expr) 0
#endif
+#include <ccan/str/str_debug.h>
+
/* These checks force things out of line, hence they are under DEBUG. */
#ifdef CCAN_STR_DEBUG
+#include <ccan/build_assert/build_assert.h>
+
+/* You can use a char if char is unsigned. */
+#if HAVE_BUILTIN_TYPES_COMPATIBLE_P && HAVE_TYPEOF
+#define str_check_arg_(i) \
+ ((i) + BUILD_ASSERT_OR_ZERO(!__builtin_types_compatible_p(typeof(i), \
+ char) \
+ || (char)255 > 0))
+#else
+#define str_check_arg_(i) (i)
+#endif
+
#if HAVE_TYPEOF
/* With GNU magic, we can make const-respecting standard string functions. */
#undef strstr
new file mode 100644
@@ -0,0 +1,30 @@
+/* CC0 (Public domain) - see LICENSE file for details */
+#ifndef CCAN_STR_DEBUG_H
+#define CCAN_STR_DEBUG_H
+
+/* #define CCAN_STR_DEBUG 1 */
+
+#ifdef CCAN_STR_DEBUG
+/* Because we mug the real ones with macros, we need our own wrappers. */
+int str_isalnum(int i);
+int str_isalpha(int i);
+int str_isascii(int i);
+#if HAVE_ISBLANK
+int str_isblank(int i);
+#endif
+int str_iscntrl(int i);
+int str_isdigit(int i);
+int str_isgraph(int i);
+int str_islower(int i);
+int str_isprint(int i);
+int str_ispunct(int i);
+int str_isspace(int i);
+int str_isupper(int i);
+int str_isxdigit(int i);
+
+char *str_strstr(const char *haystack, const char *needle);
+char *str_strchr(const char *s, int c);
+char *str_strrchr(const char *s, int c);
+#endif /* CCAN_STR_DEBUG */
+
+#endif /* CCAN_STR_DEBUG_H */
@@ -4,7 +4,7 @@ struct s {
int val;
};
-int main(int argc, char *argv[])
+int main(void)
{
struct s
#ifdef FAIL
@@ -3,6 +3,7 @@
int main(int argc, char *argv[])
{
+ (void)argc;
#ifdef FAIL
#if !HAVE_BUILTIN_TYPES_COMPATIBLE_P || !HAVE_TYPEOF
#error We need typeof to check isalnum.
@@ -3,6 +3,7 @@
int main(int argc, char *argv[])
{
+ (void)argc;
#ifdef FAIL
#if !HAVE_BUILTIN_TYPES_COMPATIBLE_P || !HAVE_TYPEOF
#error We need typeof to check isalpha.
@@ -3,6 +3,7 @@
int main(int argc, char *argv[])
{
+ (void)argc;
#ifdef FAIL
#if !HAVE_BUILTIN_TYPES_COMPATIBLE_P || !HAVE_TYPEOF
#error We need typeof to check isascii.
@@ -3,6 +3,7 @@
int main(int argc, char *argv[])
{
+ (void)argc;
#ifdef FAIL
#if !HAVE_BUILTIN_TYPES_COMPATIBLE_P || !HAVE_TYPEOF || !HAVE_ISBLANK
#error We need typeof to check isblank.
@@ -3,6 +3,7 @@
int main(int argc, char *argv[])
{
+ (void)argc;
#ifdef FAIL
#if !HAVE_BUILTIN_TYPES_COMPATIBLE_P || !HAVE_TYPEOF
#error We need typeof to check iscntrl.
@@ -3,6 +3,7 @@
int main(int argc, char *argv[])
{
+ (void)argc;
#ifdef FAIL
#if !HAVE_BUILTIN_TYPES_COMPATIBLE_P || !HAVE_TYPEOF
#error We need typeof to check isdigit.
@@ -3,6 +3,7 @@
int main(int argc, char *argv[])
{
+ (void)argc;
#ifdef FAIL
#if !HAVE_BUILTIN_TYPES_COMPATIBLE_P || !HAVE_TYPEOF
#error We need typeof to check islower.
@@ -3,6 +3,7 @@
int main(int argc, char *argv[])
{
+ (void)argc;
#ifdef FAIL
#if !HAVE_BUILTIN_TYPES_COMPATIBLE_P || !HAVE_TYPEOF
#error We need typeof to check isprint.
@@ -3,6 +3,7 @@
int main(int argc, char *argv[])
{
+ (void)argc;
#ifdef FAIL
#if !HAVE_BUILTIN_TYPES_COMPATIBLE_P || !HAVE_TYPEOF
#error We need typeof to check ispunct.
@@ -3,6 +3,7 @@
int main(int argc, char *argv[])
{
+ (void)argc;
#ifdef FAIL
#if !HAVE_BUILTIN_TYPES_COMPATIBLE_P || !HAVE_TYPEOF
#error We need typeof to check isspace.
@@ -3,6 +3,7 @@
int main(int argc, char *argv[])
{
+ (void)argc;
#ifdef FAIL
#if !HAVE_BUILTIN_TYPES_COMPATIBLE_P || !HAVE_TYPEOF
#error We need typeof to check isupper.
@@ -3,6 +3,7 @@
int main(int argc, char *argv[])
{
+ (void)argc;
#ifdef FAIL
#if !HAVE_BUILTIN_TYPES_COMPATIBLE_P || !HAVE_TYPEOF
#error We need typeof to check isxdigit.
@@ -1,7 +1,7 @@
#define CCAN_STR_DEBUG 1
#include <ccan/str/str.h>
-int main(int argc, char *argv[])
+int main(void)
{
#ifdef FAIL
#if !HAVE_TYPEOF
@@ -1,7 +1,7 @@
#define CCAN_STR_DEBUG 1
#include <ccan/str/str.h>
-int main(int argc, char *argv[])
+int main(void)
{
#ifdef FAIL
#if !HAVE_TYPEOF
@@ -1,7 +1,7 @@
#define CCAN_STR_DEBUG 1
#include <ccan/str/str.h>
-int main(int argc, char *argv[])
+int main(void)
{
#ifdef FAIL
#if !HAVE_TYPEOF
new file mode 100644
@@ -0,0 +1,8 @@
+#include <ccan/str/str.h>
+
+int main(void)
+{
+ static char str[STR_MAX_CHARS(int)];
+
+ return str[0] ? 0 : 1;
+}
@@ -4,9 +4,9 @@
#include <ccan/tap/tap.h>
#include <stdint.h>
-int main(int argc, char *argv[])
+int main(void)
{
- char *str = (char*)malloc(sizeof(char)*1000);
+ char str[1000];
struct {
uint8_t u1byte;
int8_t s1byte;
@@ -19,11 +19,6 @@ int main(int argc, char *argv[])
void *ptr;
} types;
- (void)argc;
- (void)argv;
-
- assert(str);
-
plan_tests(13);
memset(&types, 0xFF, sizeof(types));
@@ -60,7 +55,5 @@ int main(int argc, char *argv[])
sprintf(str, "%p", types.ptr);
ok1(strlen(str) < STR_MAX_CHARS(types.ptr));
- free(str);
-
return exit_status();
}
@@ -21,13 +21,10 @@ static char *strdup_rev(const char *s)
return ret;
}
-int main(int argc, char *argv[])
+int main(void)
{
unsigned int i, j, n;
char *strings[NUM_SUBSTRINGS * NUM_SUBSTRINGS];
-
- (void)argc;
- (void)argv;
n = 0;
for (i = 0; i < NUM_SUBSTRINGS; i++) {
sync to upstream ccan.git commit ca7c5a9e04f3 ("ccan: make tal_dump() format more regular."). The recipe used to sync upstream is: $ cd ccan $ ./tools/create-ccan-tree -b make tmp \ array_size check_type container_of heap \ short_types build_assert endian list str $ # replace directories in skiboot/ccan/ with those in tmp/ccan/ $ cd ../skiboot $ patch -p1 < ccan/skiboot.patch This also adds a README.skiboot to help with future updates. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> --- ccan/README.skiboot | 26 + ccan/array_size/_info | 4 +- .../test/compile_fail-function-param.c | 6 +- ccan/array_size/test/compile_fail.c | 2 + ccan/array_size/test/run.c | 5 +- ccan/build_assert/_info | 2 +- ccan/build_assert/test/compile_fail-expr.c | 2 +- ccan/build_assert/test/compile_fail.c | 2 +- ccan/build_assert/test/compile_ok.c | 2 +- .../test/run-BUILD_ASSERT_OR_ZERO.c | 5 +- ccan/check_type/_info | 2 +- ccan/check_type/check_type.h | 2 +- .../check_type/test/compile_fail-check_type.c | 2 + .../test/compile_fail-check_type_unsigned.c | 2 + .../test/compile_fail-check_types_match.c | 1 + ccan/check_type/test/run.c | 4 +- ccan/config.h | 27 +- ccan/container_of/_info | 14 +- ccan/container_of/container_of.h | 38 +- .../container_of/test/compile_fail-bad-type.c | 2 +- ccan/container_of/test/compile_fail-types.c | 2 +- .../test/compile_fail-var-types.c | 2 +- ccan/container_of/test/run.c | 13 +- ccan/endian/.depends | 0 ccan/endian/endian.h | 8 + ccan/endian/test/run.c | 5 +- ccan/heap/test/run.c | 4 +- ccan/list/_info | 6 +- ccan/list/list.h | 455 ++++++++++++++---- ccan/list/test/run-CCAN_LIST_DEBUG.c | 60 +++ ccan/list/test/run-check-corrupt.c | 9 +- ccan/list/test/run-check-nonconst.c | 27 ++ ccan/list/test/run-list_del_from-assert.c | 6 +- ccan/list/test/run-list_prev-list_next.c | 65 +++ ccan/list/test/run-prepend_list.c | 111 +++++ ccan/list/test/run-single-eval.c | 5 +- ccan/list/test/run.c | 116 ++++- ccan/short_types/test/run-endian.c | 2 +- ccan/short_types/test/run.c | 2 +- ccan/str/_info | 8 +- ccan/str/debug.c | 108 +++++ ccan/str/str.h | 16 +- ccan/str/str_debug.h | 30 ++ ccan/str/test/compile_fail-STR_MAX_CHARS.c | 2 +- ccan/str/test/compile_fail-isalnum.c | 1 + ccan/str/test/compile_fail-isalpha.c | 1 + ccan/str/test/compile_fail-isascii.c | 1 + ccan/str/test/compile_fail-isblank.c | 1 + ccan/str/test/compile_fail-iscntrl.c | 1 + ccan/str/test/compile_fail-isdigit.c | 1 + ccan/str/test/compile_fail-islower.c | 1 + ccan/str/test/compile_fail-isprint.c | 1 + ccan/str/test/compile_fail-ispunct.c | 1 + ccan/str/test/compile_fail-isspace.c | 1 + ccan/str/test/compile_fail-isupper.c | 1 + ccan/str/test/compile_fail-isxdigit.c | 1 + ccan/str/test/compile_fail-strchr.c | 2 +- ccan/str/test/compile_fail-strrchr.c | 2 +- ccan/str/test/compile_fail-strstr.c | 2 +- .../test/compile_ok-STR_MAX_CHARS-static.c | 8 + ccan/str/test/run-STR_MAX_CHARS.c | 11 +- ccan/str/test/run.c | 5 +- 62 files changed, 1055 insertions(+), 199 deletions(-) create mode 100644 ccan/README.skiboot delete mode 100644 ccan/endian/.depends create mode 100644 ccan/list/test/run-CCAN_LIST_DEBUG.c create mode 100644 ccan/list/test/run-check-nonconst.c create mode 100644 ccan/list/test/run-list_prev-list_next.c create mode 100644 ccan/list/test/run-prepend_list.c create mode 100644 ccan/str/debug.c create mode 100644 ccan/str/str_debug.h create mode 100644 ccan/str/test/compile_ok-STR_MAX_CHARS-static.c