1/*	$NetBSD: lstRemove.c,v 1.14 2008/12/13 15:19:29 dsl Exp $	*/
2
3/*
4 * Copyright (c) 1988, 1989, 1990, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 *    may be used to endorse or promote products derived from this software
20 *    without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#ifndef MAKE_NATIVE
36static char rcsid[] = "$NetBSD: lstRemove.c,v 1.14 2008/12/13 15:19:29 dsl Exp $";
37#else
38#include <sys/cdefs.h>
39#ifndef lint
40#if 0
41static char sccsid[] = "@(#)lstRemove.c	8.1 (Berkeley) 6/6/93";
42#else
43__RCSID("$NetBSD: lstRemove.c,v 1.14 2008/12/13 15:19:29 dsl Exp $");
44#endif
45#endif /* not lint */
46#endif
47
48/*-
49 * LstRemove.c --
50 *	Remove an element from a list
51 */
52
53#include	"lstInt.h"
54
55/*-
56 *-----------------------------------------------------------------------
57 * Lst_Remove --
58 *	Remove the given node from the given list.
59 *
60 * Results:
61 *	SUCCESS or FAILURE.
62 *
63 * Side Effects:
64 *	The list's firstPtr will be set to NULL if ln is the last
65 *	node on the list. firsPtr and lastPtr will be altered if ln is
66 *	either the first or last node, respectively, on the list.
67 *
68 *-----------------------------------------------------------------------
69 */
70ReturnStatus
71Lst_Remove(Lst l, LstNode ln)
72{
73    List 	list = l;
74    ListNode	lNode = ln;
75
76    if (!LstValid (l) ||
77	!LstNodeValid (ln, l)) {
78	    return (FAILURE);
79    }
80
81    /*
82     * unlink it from the list
83     */
84    if (lNode->nextPtr != NULL) {
85	lNode->nextPtr->prevPtr = lNode->prevPtr;
86    }
87    if (lNode->prevPtr != NULL) {
88	lNode->prevPtr->nextPtr = lNode->nextPtr;
89    }
90
91    /*
92     * if either the firstPtr or lastPtr of the list point to this node,
93     * adjust them accordingly
94     */
95    if (list->firstPtr == lNode) {
96	list->firstPtr = lNode->nextPtr;
97    }
98    if (list->lastPtr == lNode) {
99	list->lastPtr = lNode->prevPtr;
100    }
101
102    /*
103     * Sequential access stuff. If the node we're removing is the current
104     * node in the list, reset the current node to the previous one. If the
105     * previous one was non-existent (prevPtr == NULL), we set the
106     * end to be Unknown, since it is.
107     */
108    if (list->isOpen && (list->curPtr == lNode)) {
109	list->curPtr = list->prevPtr;
110	if (list->curPtr == NULL) {
111	    list->atEnd = Unknown;
112	}
113    }
114
115    /*
116     * the only way firstPtr can still point to ln is if ln is the last
117     * node on the list (the list is circular, so lNode->nextptr == lNode in
118     * this case). The list is, therefore, empty and is marked as such
119     */
120    if (list->firstPtr == lNode) {
121	list->firstPtr = NULL;
122    }
123
124    /*
125     * note that the datum is unmolested. The caller must free it as
126     * necessary and as expected.
127     */
128    if (lNode->useCount == 0) {
129	free(ln);
130    } else {
131	lNode->flags |= LN_DELETED;
132    }
133
134    return (SUCCESS);
135}
136
137