1236769Sobrien/*	$NetBSD: lstForEachFrom.c,v 1.17 2009/01/23 21:26:30 dsl Exp $	*/
2236769Sobrien
3236769Sobrien/*
4236769Sobrien * Copyright (c) 1988, 1989, 1990, 1993
5236769Sobrien *	The Regents of the University of California.  All rights reserved.
6236769Sobrien *
7236769Sobrien * This code is derived from software contributed to Berkeley by
8236769Sobrien * Adam de Boor.
9236769Sobrien *
10236769Sobrien * Redistribution and use in source and binary forms, with or without
11236769Sobrien * modification, are permitted provided that the following conditions
12236769Sobrien * are met:
13236769Sobrien * 1. Redistributions of source code must retain the above copyright
14236769Sobrien *    notice, this list of conditions and the following disclaimer.
15236769Sobrien * 2. Redistributions in binary form must reproduce the above copyright
16236769Sobrien *    notice, this list of conditions and the following disclaimer in the
17236769Sobrien *    documentation and/or other materials provided with the distribution.
18236769Sobrien * 3. Neither the name of the University nor the names of its contributors
19236769Sobrien *    may be used to endorse or promote products derived from this software
20236769Sobrien *    without specific prior written permission.
21236769Sobrien *
22236769Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23236769Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24236769Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25236769Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26236769Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27236769Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28236769Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29236769Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30236769Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31236769Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32236769Sobrien * SUCH DAMAGE.
33236769Sobrien */
34236769Sobrien
35236769Sobrien#ifndef MAKE_NATIVE
36236769Sobrienstatic char rcsid[] = "$NetBSD: lstForEachFrom.c,v 1.17 2009/01/23 21:26:30 dsl Exp $";
37236769Sobrien#else
38236769Sobrien#include <sys/cdefs.h>
39236769Sobrien#ifndef lint
40236769Sobrien#if 0
41236769Sobrienstatic char sccsid[] = "@(#)lstForEachFrom.c	8.1 (Berkeley) 6/6/93";
42236769Sobrien#else
43236769Sobrien__RCSID("$NetBSD: lstForEachFrom.c,v 1.17 2009/01/23 21:26:30 dsl Exp $");
44236769Sobrien#endif
45236769Sobrien#endif /* not lint */
46236769Sobrien#endif
47236769Sobrien
48236769Sobrien/*-
49236769Sobrien * lstForEachFrom.c --
50236769Sobrien *	Perform a given function on all elements of a list starting from
51236769Sobrien *	a given point.
52236769Sobrien */
53236769Sobrien
54236769Sobrien#include	"lstInt.h"
55236769Sobrien
56236769Sobrien/*-
57236769Sobrien *-----------------------------------------------------------------------
58236769Sobrien * Lst_ForEachFrom --
59236769Sobrien *	Apply the given function to each element of the given list. The
60236769Sobrien *	function should return 0 if traversal should continue and non-
61236769Sobrien *	zero if it should abort.
62236769Sobrien *
63236769Sobrien * Results:
64236769Sobrien *	None.
65236769Sobrien *
66236769Sobrien * Side Effects:
67236769Sobrien *	Only those created by the passed-in function.
68236769Sobrien *
69236769Sobrien *-----------------------------------------------------------------------
70236769Sobrien */
71236769Sobrien/*VARARGS2*/
72236769Sobrienint
73236769SobrienLst_ForEachFrom(Lst l, LstNode ln, int (*proc)(void *, void *),
74236769Sobrien		void *d)
75236769Sobrien{
76236769Sobrien    ListNode	tln = ln;
77236769Sobrien    List 	list = l;
78236769Sobrien    ListNode	next;
79236769Sobrien    Boolean 	    	done;
80236769Sobrien    int     	    	result;
81236769Sobrien
82236769Sobrien    if (!LstValid (list) || LstIsEmpty (list)) {
83236769Sobrien	return 0;
84236769Sobrien    }
85236769Sobrien
86236769Sobrien    do {
87236769Sobrien	/*
88236769Sobrien	 * Take care of having the current element deleted out from under
89236769Sobrien	 * us.
90236769Sobrien	 */
91236769Sobrien
92236769Sobrien	next = tln->nextPtr;
93236769Sobrien
94236769Sobrien	/*
95236769Sobrien	 * We're done with the traversal if
96236769Sobrien	 *  - the next node to examine is the first in the queue or
97236769Sobrien	 *    doesn't exist and
98236769Sobrien	 *  - nothing's been added after the current node (check this
99236769Sobrien	 *    after proc() has been called).
100236769Sobrien	 */
101236769Sobrien	done = (next == NULL || next == list->firstPtr);
102236769Sobrien
103236769Sobrien	(void) tln->useCount++;
104236769Sobrien	result = (*proc) (tln->datum, d);
105236769Sobrien	(void) tln->useCount--;
106236769Sobrien
107236769Sobrien	/*
108236769Sobrien	 * Now check whether a node has been added.
109236769Sobrien	 * Note: this doesn't work if this node was deleted before
110236769Sobrien	 *       the new node was added.
111236769Sobrien	 */
112236769Sobrien	if (next != tln->nextPtr) {
113236769Sobrien		next = tln->nextPtr;
114236769Sobrien		done = 0;
115236769Sobrien	}
116236769Sobrien
117236769Sobrien	if (tln->flags & LN_DELETED) {
118236769Sobrien	    free((char *)tln);
119236769Sobrien	}
120236769Sobrien	tln = next;
121236769Sobrien    } while (!result && !LstIsEmpty(list) && !done);
122236769Sobrien
123236769Sobrien    return result;
124236769Sobrien}
125236769Sobrien
126