1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29/*
30 * Embedded Linked Lists
31 *
32 * Simple doubly-linked list implementation.  This implementation assumes that
33 * each list element contains an embedded cmd_list_t (previous and next
34 * pointers), which is typically the first member of the element struct.
35 * An additional cmd_list_t is used to store the head (l_next) and tail
36 * (l_prev) pointers.  The current head and tail list elements have their
37 * previous and next pointers set to NULL, respectively.
38 */
39
40#include <cmd_list.h>
41#include <cmd.h>
42
43void
44cmd_list_append(cmd_list_t *lp, void *new)
45{
46	cmd_list_t *p = lp->l_prev;	/* p = tail list element */
47	cmd_list_t *q = new;		/* q = new list element */
48
49	lp->l_prev = q;
50	q->l_prev = p;
51	q->l_next = NULL;
52
53	if (p != NULL)
54		p->l_next = q;
55	else
56		lp->l_next = q;
57}
58
59void
60cmd_list_prepend(cmd_list_t *lp, void *new)
61{
62	cmd_list_t *p = new;		/* p = new list element */
63	cmd_list_t *q = lp->l_next;	/* q = head list element */
64
65	lp->l_next = p;
66	p->l_prev = NULL;
67	p->l_next = q;
68
69	if (q != NULL)
70		q->l_prev = p;
71	else
72		lp->l_prev = p;
73}
74
75void
76cmd_list_insert_before(cmd_list_t *lp, void *before_me, void *new)
77{
78	cmd_list_t *p = before_me;
79	cmd_list_t *q = new;
80
81	if (p == NULL || p->l_prev == NULL) {
82		cmd_list_prepend(lp, new);
83		return;
84	}
85
86	q->l_prev = p->l_prev;
87	q->l_next = p;
88	p->l_prev = q;
89	q->l_prev->l_next = q;
90}
91
92void
93cmd_list_insert_after(cmd_list_t *lp, void *after_me, void *new)
94{
95	cmd_list_t *p = after_me;
96	cmd_list_t *q = new;
97
98	if (p == NULL || p->l_next == NULL) {
99		cmd_list_append(lp, new);
100		return;
101	}
102
103	q->l_next = p->l_next;
104	q->l_prev = p;
105	p->l_next = q;
106	q->l_next->l_prev = q;
107}
108
109void
110cmd_list_delete(cmd_list_t *lp, void *existing)
111{
112	cmd_list_t *p = existing;
113
114	if (p->l_prev != NULL)
115		p->l_prev->l_next = p->l_next;
116	else
117		lp->l_next = p->l_next;
118
119	if (p->l_next != NULL)
120		p->l_next->l_prev = p->l_prev;
121	else
122		lp->l_prev = p->l_prev;
123}
124