|
| 1 | +#include "platform.h" |
| 2 | + |
| 3 | +struct list_elem; |
| 4 | + |
| 5 | +struct list_entry { |
| 6 | + struct list_elem *next; |
| 7 | + struct list_elem **prevnextp; |
| 8 | +}; |
| 9 | + |
| 10 | +struct list_head { |
| 11 | + struct list_elem *first; |
| 12 | + struct list_elem **tailnextp; |
| 13 | +}; |
| 14 | + |
| 15 | +void list_head_init(struct list_head *h); |
| 16 | +void list_remove(struct list_head *h, void *elem, struct list_entry *e); |
| 17 | +void list_insert_tail(struct list_head *h, void *elem, struct list_entry *e); |
| 18 | + |
| 19 | +#define LIST_ENTRY(TYPE) \ |
| 20 | + struct { \ |
| 21 | + TYPE *next; \ |
| 22 | + TYPE **prevnextp; \ |
| 23 | + } |
| 24 | + |
| 25 | +#define LIST_HEAD(TYPE) \ |
| 26 | + struct { \ |
| 27 | + TYPE *first; \ |
| 28 | + TYPE **tailnextp; \ |
| 29 | + } |
| 30 | + |
| 31 | +#define LIST_FOREACH(VAR, HEAD, NAME) \ |
| 32 | + for (VAR = (HEAD)->first; VAR != NULL; VAR = (VAR)->NAME.next) |
| 33 | + |
| 34 | +#if defined(__clang__) |
| 35 | +#define CHECK_TYPE(a, b) \ |
| 36 | + do { \ |
| 37 | + __attribute__((__unused__)) __typeof__(a) __dummy = b; \ |
| 38 | + } while (0) |
| 39 | +#else |
| 40 | +#define CHECK_TYPE(a, b) |
| 41 | +#endif |
| 42 | + |
| 43 | +#define LIST_FIRST(HEAD) (HEAD)->first |
| 44 | + |
| 45 | +#define LIST_EMPTY(HEAD) (LIST_FIRST(HEAD) == NULL) |
| 46 | + |
| 47 | +#define LIST_REMOVE(HEAD, ELEM, NAME) \ |
| 48 | + CHECK_TYPE(&(HEAD)->first, (HEAD)->tailnextp); \ |
| 49 | + CHECK_TYPE((HEAD)->first, (ELEM)->NAME.next); \ |
| 50 | + CHECK_TYPE(&(ELEM)->NAME.next, (ELEM)->NAME.prevnextp); \ |
| 51 | + ctassert(sizeof(*(HEAD)) == sizeof(struct list_head)); \ |
| 52 | + ctassert(sizeof((ELEM)->NAME) == sizeof(struct list_entry)); \ |
| 53 | + list_remove((struct list_head *)(HEAD), (ELEM), \ |
| 54 | + (struct list_entry *)&(ELEM)->NAME) |
| 55 | + |
| 56 | +#define LIST_INSERT_TAIL(HEAD, ELEM, NAME) \ |
| 57 | + CHECK_TYPE(&(HEAD)->first, (HEAD)->tailnextp); \ |
| 58 | + CHECK_TYPE((HEAD)->first, (ELEM)->NAME.next); \ |
| 59 | + CHECK_TYPE(&(ELEM)->NAME.next, (ELEM)->NAME.prevnextp); \ |
| 60 | + ctassert(sizeof(*(HEAD)) == sizeof(struct list_head)); \ |
| 61 | + ctassert(sizeof((ELEM)->NAME) == sizeof(struct list_entry)); \ |
| 62 | + list_insert_tail((struct list_head *)(HEAD), (ELEM), \ |
| 63 | + (struct list_entry *)&(ELEM)->NAME) |
| 64 | + |
| 65 | +#define LIST_HEAD_INIT(HEAD) \ |
| 66 | + CHECK_TYPE(&(HEAD)->first, (HEAD)->tailnextp); \ |
| 67 | + ctassert(sizeof(*(HEAD)) == sizeof(struct list_head)); \ |
| 68 | + list_head_init((struct list_head *)(HEAD)) |
0 commit comments