struct slist { struct slist *next; }; void slist_init(struct slist* self); bool slist_null(struct slist* self); bool slist_non_null(struct slist* self); size_t slist_length(struct slist* self); void slist_extend(struct slist* self, struct slist* rhs); #define container_of(PTR, TYPE, MEMBER) \ (TYPE *)((char *)(PTR) - ((ptrdiff_t) &((TYPE*)0)->MEMBER)) /* FUN should return false to break iteration. */ /* NB: Comma-swallowing paste of gnu-style named variadic macro argument. */ #define slist_metafor(TYPE, MEMBER, PTR, BODY) { \ struct slist *__slist_head = &((PTR)->MEMBER); \ struct slist *__slist_iter = __slist_head->next; \ struct slist *__slist_next; \ while(__slist_iter != __slist_head) { \ __slist_next = __slist_iter->next; \ TYPE* __value_ptr = container_of(__slist_iter, TYPE, MEMBER); \ BODY; \ __slist_iter = __slist_next; \ } \ } #define slist_search(TYPE, MEMBER, PTR, FOUND_LABEL, NOTFOUND_LABEL, FUN, \ COOKIE...) \ slist_metafor(TYPE, MEMBER, PTR, \ { if(!(FUN)(__value_ptr, ##COOKIE)) goto FOUND_LABEL; } \ ) \ goto NOTFOUND_LABEL; #define slist_while(TYPE, MEMBER, PTR, ERR_LABEL, FUN, COOKIE...) \ slist_metafor(TYPE, MEMBER, PTR, \ { if((FUN)(__value_ptr, ##COOKIE)) goto ERR_LABEL; }) \ #define slist_for(TYPE, MEMBER, PTR, FUN, COOKIE...) \ slist_metafor(TYPE, MEMBER, PTR, { (FUN)(__value_ptr, ##COOKIE); })