diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2020-12-30 13:33:13 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2020-12-30 13:33:13 +0000 |
commit | 46ef4a994c13568cb8b04f9e4ee468b9e03b4e4b (patch) | |
tree | 191292a462c66748b15b4046629e156e03a6f274 | |
parent | ad9fd233b790b43aabb5951e1fce9e9a815fc424 (diff) |
Add singly-linked tail queue macros from FreeBSD.
These are essentially equivalent to the simple queue macros from
NetBSD but predate them and are more widely available on other systems.
OK mpi@ denis@
-rw-r--r-- | sys/sys/queue.h | 99 |
1 files changed, 98 insertions, 1 deletions
diff --git a/sys/sys/queue.h b/sys/sys/queue.h index f28ba894609..20b78871415 100644 --- a/sys/sys/queue.h +++ b/sys/sys/queue.h @@ -1,4 +1,4 @@ -/* $OpenBSD: queue.h,v 1.45 2018/07/12 14:22:54 sashan Exp $ */ +/* $OpenBSD: queue.h,v 1.46 2020/12/30 13:33:12 millert Exp $ */ /* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ /* @@ -533,4 +533,101 @@ struct { \ } \ } while (0) +/* + * Singly-linked Tail queue declarations. + */ +#define STAILQ_HEAD(name, type) \ +struct name { \ + struct type *stqh_first; /* first element */ \ + struct type **stqh_last; /* addr of last next element */ \ +} + +#define STAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).stqh_first } + +#define STAILQ_ENTRY(type) \ +struct { \ + struct type *stqe_next; /* next element */ \ +} + +/* + * Singly-linked Tail queue access methods. + */ +#define STAILQ_FIRST(head) ((head)->stqh_first) +#define STAILQ_END(head) NULL +#define STAILQ_EMPTY(head) (STAILQ_FIRST(head) == STAILQ_END(head)) +#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) + +#define STAILQ_FOREACH(var, head, field) \ + for ((var) = STAILQ_FIRST(head); \ + (var) != STAILQ_END(head); \ + (var) = STAILQ_NEXT(var, field)) + +#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = STAILQ_FIRST(head); \ + (var) && ((tvar) = STAILQ_NEXT(var, field), 1); \ + (var) = (tvar)) + +/* + * Singly-linked Tail queue functions. + */ +#define STAILQ_INIT(head) do { \ + STAILQ_FIRST((head)) = NULL; \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_INSERT_HEAD(head, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_FIRST((head)) = (elm); \ +} while (0) + +#define STAILQ_INSERT_TAIL(head, elm, field) do { \ + STAILQ_NEXT((elm), field) = NULL; \ + *(head)->stqh_last = (elm); \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((elm), field)) == NULL)\ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_NEXT((elm), field) = (elm); \ +} while (0) + +#define STAILQ_REMOVE_HEAD(head, field) do { \ + if ((STAILQ_FIRST((head)) = \ + STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_REMOVE_AFTER(head, elm, field) do { \ + if ((STAILQ_NEXT(elm, field) = \ + STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_REMOVE(head, elm, type, field) do { \ + if (STAILQ_FIRST((head)) == (elm)) { \ + STAILQ_REMOVE_HEAD((head), field); \ + } else { \ + struct type *curelm = (head)->stqh_first; \ + while (STAILQ_NEXT(curelm, field) != (elm)) \ + curelm = STAILQ_NEXT(curelm, field); \ + STAILQ_REMOVE_AFTER(head, curelm, field); \ + } \ +} while (0) + +#define STAILQ_CONCAT(head1, head2) do { \ + if (!STAILQ_EMPTY((head2))) { \ + *(head1)->stqh_last = (head2)->stqh_first; \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_INIT((head2)); \ + } \ +} while (0) + +#define STAILQ_LAST(head, type, field) \ + (STAILQ_EMPTY((head)) ? NULL : \ + ((struct type *)(void *) \ + ((char *)((head)->stqh_last) - offsetof(struct type, field)))) + #endif /* !_SYS_QUEUE_H_ */ |