Skip to content

Instantly share code, notes, and snippets.

@nnathan
Created January 3, 2019 06:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nnathan/ce79b21797513fc41b9e71a350a1ae0b to your computer and use it in GitHub Desktop.
Save nnathan/ce79b21797513fc41b9e71a350a1ae0b to your computer and use it in GitHub Desktop.
Understanding BSD queue.h single linked list implementation
/*
* See queue(3) or https://www.freebsd.org/cgi/man.cgi?query=queue&sektion=3 for reference.
*/
#include <stdio.h>
#include <sys/queue.h>
struct Pattern {
char name[100];
/* Following expands to:
* struct { struct Pattern *sle_next; } entries;
*/
SLIST_ENTRY(Pattern) entries;
};
int main(int argc, char **argv) {
/* Following expands to
* struct yylisthead { struct Pattern *slh_first; } head = { ((void *)0) };
*/
SLIST_HEAD(yylisthead, Pattern) head = SLIST_HEAD_INITIALIZER(head);
/* Following expands to
* do { (((&head))->slh_first) = ((void *)0); } while (0);
* which can be simplified to:
* (&head)->slh_first = NULL;
*/
SLIST_INIT(&head);
struct Pattern p1 = { .name = "A", .entries = { NULL } };
/* Following expands to
* do { (((&p1))->entries.sle_next) = (((&head))->slh_first); (((&head))->slh_first) = (&p1); } while (0);
* which can be simplified to:
* (&p1)->entries.sle_next = (&head)->slh_first; (&head)->slh_first = (&p1)
*/
SLIST_INSERT_HEAD(&head, &p1, entries);
struct Pattern *e;
/* Following expands to
* for ((e) = (((&head))->slh_first); (e); (e) = (((e))->entries.sle_next))
* which can be simplified to:
* for (e = (&head)->slh_first; e != NULL; e = e->entries.sle_next)
*/
SLIST_FOREACH(e, &head, entries) {
printf("1\tname: %s\n", e->name);
}
puts("");
struct Pattern p3 = { .name = "C", .entries = { NULL } };
SLIST_INSERT_HEAD(&head, &p3, entries);
SLIST_FOREACH(e, &head, entries) {
printf("2\tname: %s\n", e->name);
}
puts("");
struct Pattern p2 = { .name = "B", .entries = { NULL } };
SLIST_INSERT_AFTER(&p3, &p2, entries);
SLIST_FOREACH(e, &head, entries) {
printf("3\tname: %s\n", e->name);
}
puts("");
struct Pattern *etmp;
/* Following expands to
* for ((e) = (((&head))->slh_first); (e) && ((etmp) = (((e))->entries.sle_next), 1); (e) = (etmp))
* which can be simplified to:
* for (e = (&head)->slh_first; (e != NULL) && (etmp = e->entries.sle_next, 1); e = etmp)
*/
SLIST_FOREACH_SAFE(e, &head, entries, etmp) {
if (e == &p2) {
/* Following expands to
* do {
* if ((((&head))->slh_first) == (e)) {
* do {
* ((((&head)))->slh_first) = ((((((&head)))->slh_first))->entries.sle_next);
* } while (0);
* } else {
* struct Pattern *curelm = (((&head))->slh_first);
* while (((curelm)->entries.sle_next) != (e))
* curelm = ((curelm)->entries.sle_next);
* do {
* ((curelm)->entries.sle_next) = ((((curelm)->entries.sle_next))->entries.sle_next);
* } while (0);
* };
* } while (0) ;
* which can be simplified to:
* if (&head)->slh_first == e {
* (&head)->slh_first = (&head)->slh_first->entries.sle_next;
* } else {
* struct Pattern *curelm = (&head)->slh_first;
* while (curelm->entries.sle_next != e)
* curelm = curelm->entries.sle_next;
* curelm->entries.sle_next = curelm->entries.sle_next->entries.sle_next;
* };
*/
SLIST_REMOVE(&head, &p2, Pattern, entries);
continue;
}
printf("4\tname: %s\n", e->name);
}
/* Following expands to
* while (!((&head)->slh_first == ((void *)0)))
* which can be simplified to:
* while ((&head)->slh_first != NULL)
*/
while (!SLIST_EMPTY(&head)) {
/* Following expands to
* e = ((&head)->slh_first);
* which can be simplified to:
* e = (&head)->slh_first;
*/
e = SLIST_FIRST(&head);
/* Following expands to
* do { (((&head))->slh_first) = (((((&head))->slh_first))->entries.sle_next); } while (0);
* which can be simplified to:
* (&head)->slh_first = (&head)->slh_first->entries.sle_next;
*/
SLIST_REMOVE_HEAD(&head, entries);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment