/*
 * Copyright (c) 2002, 2004 Sendmail, Inc. and its suppliers.
 *	All rights reserved.
 *
 * By using this file, you agree to the terms and conditions set
 * forth in the LICENSE file which can be found at the top level of
 * the sendmail distribution.
 */

#include "sm/generic.h"
SM_RCSID("@(#)$Id: t-queue.c,v 1.6 2005/06/16 20:37:09 ca Exp $")

#include "sm/assert.h"
#include "sm/magic.h"
#include "sm/rpool.h"
#include "sm/test.h"
#include "sm/queue.h"

#include <stdio.h>

struct entry
{
	int			item;
	TAILQ_ENTRY(entry)	entries;
} *n1, *n2, *np, *nn;

struct queue
{
	sm_rpool_P	hd_rpool;
	TAILQ_HEAD(fh, entry) fh;
#if 0
struct fh {
	struct entry *tqh_first;	/* first element */
	struct entry **tqh_last;	/* addr of last next element */
} fh;
#endif /* 0 */
};

#if 0

#define TAILQ_HEAD(name, type)						\
struct name {								\
	struct type *tqh_first;	/* first element */			\
	struct type **tqh_last;	/* addr of last next element */		\

#define TAILQ_ENTRY(type)						\
struct {								\
	struct type *tqe_next;	/* next element */			\
	struct type **tqe_prev;	/* address of previous next element */	\
}

#define TAILQ_INIT(head) do {						\
	(head)->tqh_first = NULL;					\
	(head)->tqh_last = &(head)->tqh_first;				\
} while (0)

#define TAILQ_INSERT_TAIL(head, elm, field) do {			\
	(elm)->field.tqe_next = NULL;					\
	(elm)->field.tqe_prev = (head)->tqh_last;			\
	*(head)->tqh_last = (elm);					\
	(head)->tqh_last = &(elm)->field.tqe_next;			\
} while (0)
#endif /* 0 */

static void
test_lists(sm_rpool_P rp)
{
	int old, count;
	struct queue head;

	TAILQ_INIT(&(head.fh));
	SM_TEST(TAILQ_EMPTY(&(head.fh)));
	head.hd_rpool = rp;

	n1 = malloc(sizeof(*n1));
	SM_TEST(n1 != NULL);
	n1->item = 1;
	TAILQ_INSERT_HEAD(&(head.fh), n1, entries);
	SM_TEST(!TAILQ_EMPTY(&(head.fh)));
	SM_TEST(TAILQ_LAST(&(head.fh), fh) == n1);

	n1 = malloc(sizeof(*n1));
	SM_TEST(n1 != NULL);
	n1->item = 128;
	TAILQ_INSERT_TAIL(&(head.fh), n1, entries);
	SM_TEST(TAILQ_LAST(&(head.fh), fh) == n1);
#if 0
	(*(((struct fh *)((&(head.fh)->tqh_last))->tqh_last))
#endif /* 0 */

	n2 = malloc(sizeof(*n2));
	SM_TEST(n2 != NULL);
	n2->item = 196;
	TAILQ_INSERT_AFTER(&(head.fh), n1, n2, entries);
	SM_TEST(TAILQ_LAST(&(head.fh), fh) == n2);

	n2 = malloc(sizeof(*n2));
	SM_TEST(n2 != NULL);
	n2->item = 64;
	TAILQ_INSERT_BEFORE(n1, n2, entries);
	SM_TEST(TAILQ_LAST(&(head.fh), fh) != n2);

	old = -1;
	count = 0;
	TAILQ_FOREACH(np, &(head.fh), entries)
	{
		if (SmTestVerbose)
		{
			printf("Element\t%d: %4d\n", count, np->item);
		}
		SM_TEST(old < np->item);
		old = np->item;
		++count;
	}
	SM_TEST(count == 4);

	for (np = TAILQ_FIRST(&(head.fh)); np != TAILQ_END(&(head.fh)); np = nn)
	{
		nn = TAILQ_NEXT(np, entries);
		free(np);
	}
}

int
main(int argc, char *argv[])
{
	sm_rpool_P rp;

	sm_test_begin(argc, argv, "test lists");
	test_lists(NULL);
	rp = sm_rpool_new(NULL);
	SM_TEST(rp != NULL);
	if (rp != NULL)
	{
		test_lists(rp);
		sm_rpool_delete(rp);
	}
	return sm_test_end();
}


syntax highlighted by Code2HTML, v. 0.9.1