							\
    head->first = NULL;								\
    head->last = NULL;								\
}										\
										\
__TK_DLIST_UNUSED								\
static void									\
LT##_ElemInit(struct ElemType *elem)						\
{										\
    assert(elem);								\
    elem->_dl_.next = NULL;							\
    elem->_dl_.prev = NULL;							\
}										\
										\
__TK_DLIST_UNUSED								\
static int									\
LT##_IsEmpty(LT *head)								\
{										\
    assert(head);								\
    return head->first == NULL;							\
}										\
										\
__TK_DLIST_UNUSED								\
static int									\
LT##_IsLinked(struct ElemType *elem)						\
{										\
    assert(elem);								\
    return elem->_dl_.next && elem->_dl_.prev;					\
}										\
										\
__TK_DLIST_UNUSED								\
static int									\
LT##_IsFirst(struct ElemType *elem)						\
{										\
    assert(LT##_IsLinked(elem));						\
    return elem->_dl_.prev->_dl_.prev == elem;					\
}										\
										\
__TK_DLIST_UNUSED								\
static int									\
LT##_IsLast(struct ElemType *elem)						\
{										\
    assert(LT##_IsLinked(elem));						\
    return elem->_dl_.next->_dl_.next == elem;					\
}										\
										\
__TK_DLIST_UNUSED								\
static struct ElemType *							\
LT##_First(LT *head)								\
{										\
    assert(head);								\
    return head->first;								\
}										\
										\
__TK_DLIST_UNUSED								\
static struct ElemType *							\
LT##_Last(LT *head)								\
{										\
    assert(head);								\
    return head->last;								\
}										\
										\
__TK_DLIST_UNUSED								\
static struct ElemType *							\
LT##_Next(struct ElemType *elem)						\
{										\
    assert(elem);								\
    return LT##_IsLast(elem) ? NULL : elem->_dl_.next;				\
}										\
										\
__TK_DLIST_UNUSED								\
static struct ElemType *							\
LT##_Prev(struct ElemType *elem)						\
{										\
    assert(elem);								\
    return LT##_IsFirst(elem) ? NULL : elem->_dl_.prev;				\
}										\
										\
__TK_DLIST_UNUSED								\
static unsigned									\
LT##_Size(const LT *head)							\
{										\
    const struct ElemType *elem;						\
    unsigned size = 0;								\
    assert(head);								\
    if ((elem = head->first)) {							\
	for ( ; elem != (void *) head; elem = elem->_dl_.next) {		\
	    ++size;								\
	}									\
    }										\
    return size;								\
}										\
										\
__TK_DLIST_UNUSED								\
static void									\
LT##_InsertAfter(struct ElemType *listElem, struct ElemType *elem)		\
{										\
    assert(listElem);								\
    assert(elem);								\
    elem->_dl_.next = listElem->_dl_.next;					\
    elem->_dl_.prev = listElem;							\
    listElem->_dl_.next->_dl_.prev = elem;					\
    listElem->_dl_.next = elem;							\
}										\
										\
__TK_DLIST_UNUSED								\
static void									\
LT##_InsertBefore(struct ElemType *listElem, struct ElemType *elem)		\
{										\
    assert(listElem);								\
    assert(elem);								\
    elem->_dl_.next = listElem;							\
    elem->_dl_.prev = listElem->_dl_.prev;;					\
    listElem->_dl_.prev->_dl_.next = elem;					\
    listElem->_dl_.prev = elem;							\
}										\
										\
__TK_DLIST_UNUSED								\
static void									\
LT##_Prepend(LT *head, struct ElemType *elem)					\
{										\
    assert(head);								\
    assert(elem);								\
    elem->_dl_.prev = (void *) head;						\
    if (!head->first) {								\
	elem->_dl_.next = (void *) head;					\
	head->last = elem;							\
    } else {									\
	elem->_dl_.next = head->first;						\
	head->first->_dl_.prev = elem;						\
    }										\
    head->first = elem;								\
}										\
										\
__TK_DLIST_UNUSED								\
static void									\
LT##_Append(LT *head, struct ElemType *elem)					\
{										\
    assert(head);								\
    assert(elem);								\
    elem->_dl_.next = (void *) head;						\
    if (!head->first) {								\
	elem->_dl_.prev = (void *) head;					\
	head->first = elem;							\
    } else {									\
	elem->_dl_.prev = head->last;						\
	head->last->_dl_.next = elem;						\
    }										\
    head->last = elem;								\
}										\
										\
__TK_DLIST_UNUSED								\
static void									\
LT##_Move(LT *dst, LT *src)							\
{										\
    assert(dst);								\
    assert(src);								\
    if (src->first) {								\
	if (dst->first) {							\
	    dst->last->_dl_.next = src->first;					\
	    src->first->_dl_.prev = dst->last;					\
	    dst->last = src->last;						\
	} else {								\
	    *dst = *src;							\
	    dst->first->_dl_.prev = (void *) dst;				\
	}									\
	dst->last->_dl_.next = (void *) dst;					\
	LT##_Init(src);								\
    }										\
}										\
										\
__TK_DLIST_UNUSED								\
static void									\
LT##_Remove(struct ElemType *elem)						\
{										\
    int isFirst, isLast;							\
    assert(LT##_IsLinked(elem));						\
    isFirst = LT##_IsFirst(elem);						\
    isLast = LT##_IsLast(elem);							\
    if (isFirst && isLast) {							\
	((LT *) elem->_dl_.prev)->first = NULL;					\
	((LT *) elem->_dl_.next)->last = NULL;					\
    } else {									\
	if (isFirst) {								\
	    ((LT *) elem->_dl_.prev)->first = elem->_dl_.next;			\
	} else {								\
	    elem->_dl_.prev->_dl_.next = elem->_dl_.next;			\
	}									\
	if (isLast) {								\
	    ((LT *) elem->_dl_.next)->last = elem->_dl_.prev;			\
	} else {								\
	    elem->_dl_.next->_dl_.prev = elem->_dl_.prev;			\
	}									\
    }										\
    LT##_ElemInit(elem);							\
}										\
										\
__TK_DLIST_UNUSED								\
static void									\
LT##_Free(struct ElemType *elem)						\
{										\
    LT##_Remove(elem);								\
    ckfree((void *) elem);							\
}										\
										\
__TK_DLIST_UNUSED								\
static void									\
LT##_RemoveHead(LT *head)							\
{										\
    assert(!LT##_IsEmpty(head));						\
    LT##_Remove(head->first);							\
}										\
										\
__TK_DLIST_UNUSED								\
static void									\
LT##_RemoveTail(LT *head)							\
{										\
    assert(!LT##_IsEmpty(head));						\
    LT##_Remove(head->last);							\
}										\
										\
__TK_DLIST_UNUSED								\
static void									\
LT##_FreeHead(LT *head)								\
{										\
    assert(!LT##_IsEmpty(head));						\
    LT##_Free(head->first);							\
}										\
										\
__TK_DLIST_UNUSED								\
static void									\
LT##_FreeTail(LT *head)								\
{										\
    assert(!LT##_IsEmpty(head));						\
    LT##_Free(head->last);							\
}										\
										\
__TK_DLIST_UNUSED								\
static void									\
LT##_SwapElems(struct ElemType *lhs, struct ElemType *rhs)			\
{										\
    assert(lhs);								\
    assert(rhs);								\
    if (lhs != rhs) {								\
	struct ElemType tmp;							\
	if (LT##_IsFirst(lhs))  {						\
	    ((LT *) lhs->_dl_.prev)->first = rhs;				\
	} else if (LT##_IsFirst(rhs)) {						\
	    ((LT *) rhs->_dl_.prev)->first = lhs;				\
	}									\
	if (LT##_IsLast(lhs))  {						\
	    ((LT *) lhs->_dl_.next)->last = rhs;				\
	} else if (LT##_IsLast(rhs)) {						\
	    ((LT *) rhs->_dl_.next)->last = lhs;				\
	}									\
	tmp._dl_ = lhs->_dl_;							\
	lhs->_dl_ = rhs->_dl_;							\
	rhs->_dl_ = tmp._dl_;							\
    }										\
}										\
										\
__TK_DLIST_UNUSED								\
static void									\
LT##_Clear(LT *head)								\
{										\
    struct ElemType *p;								\
    struct ElemType *next;							\
    assert(head);								\
    for (p = head->first; p; p = next) {					\
	next = LT##_Next(p);							\
	ckfree((void *) p);							\
    }										\
    LT##_Init(head);								\
}										\
										\
__TK_DLIST_UNUSED								\
static void									\
LT##_Traverse(LT *head, LT##_Func func)						\
{										\
    struct ElemType *next;							\
    struct ElemType *p;								\
    assert(head);								\
    for (p = head->first; p; p = next) {					\
	next = func(head, p);							\
    }										\
}										\
/* ------------------------------------------------------------------------- */

#define TK_DLIST_FOREACH(var, head)						\
    assert(head);								\
    for (var = head->first ? head->first : (void *) head; var != (void *) head; var = var->_dl_.next)

#define TK_DLIST_FOREACH_REVERSE(var, head)					\
    assert(head);								\
    for (var = head->last ? head->last : (void *) head; var != (void *) head; var = var->_dl_.prev)
