0
  #   mˆl–ßi~” TÔD¨ 	¥íÆŸ¸ÔÅ£íƒ}æAìÄê &f    m/* slist.c -- generalised singly linked lists

   Copyright (C) 2000, 2004, 2007-2009, 2011-2015 Free Software
   Foundation, Inc.
   Written by Gary V. Vaughan, 2000

   NOTE: The canonical source of this file is maintained with the
   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.

GNU Libltdl is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.

As a special exception to the GNU Lesser General Public License,
if you distribute this file as part of a program or library that
is built using GNU Libtool, you may include this file under the
same distribution terms that you use for the rest of that program.

GNU Libltdl is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
copy can be downloaded from  http://www.gnu.org/licenses/lgpl.html,
or obtained by writing to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

#include <assert.h>

#include "slist.h"
#include <stdlib.h>

static SList *	slist_sort_merge    (SList *left, SList *right,
				     SListCompare *compare, void *userdata);


/* Call DELETE repeatedly on each element of HEAD.

   CAVEAT: If you call this when HEAD is the start of a list of boxed
           items, you must remember that each item passed back to your
	   DELETE function will be a boxed item that must be slist_unbox()ed
	   before operating on its contents.

   e.g. void boxed_delete (void *item) { item_free (slist_unbox (item)); }
        ...
	  slist = slist_delete (slist, boxed_delete);
	...
*/
SList *
slist_delete (SList *head, void (*delete_fct) (void *item))
{
  assert (delete_fct);

  while (head)
    {
      SList *next = head->next;
      (*delete_fct) (head);
      head = next;
    }

  return 0;
}

/* Call FIND repeatedly with MATCHDATA and each item of *PHEAD, until
   FIND returns non-NULL, or the list is exhausted.  If a match is found
   the matching item is destructively removed from *PHEAD, and the value
   returned by the matching call to FIND is returned.

   CAVEAT: To avoid memory leaks, unless you already have the address of
           the stale item, you should probably return that from FIND if
	   it makes a successful match.  Don't forget to slist_unbox()
	   every item in a boxed list before operating on its contents.   */
SList *
slist_remove (SList **phead, SListCallback *find, void *matchdata)
{
  SList *stale = 0;
  void *result = 0;

  assert (find);

  if (!phead || !*phead)
    return 0;

  /* Does the head of the passed list match? */
  result = (*find) (*phead, matchdata);
  if (result)
    {
      stale = *phead;
      *phead = stale->next;
    }
  /* what about the rest of the elements? */
  else
    {
      SList *head;
      for (head = *phead; head->next; head = head->next)
	{
	  result = (*find) (head->next, matchdata);
	  if (result)
	    {
	      stale		= head->next;
	      head->next	= stale->next;
	      break;
	    }
	}
    }

  return (SList *) result;
}

/* Call FIND repeatedly with each element of SLIST and MATCHDATA, until
   FIND returns non-NULL, or the list is exhausted.  If a match is found
   the value returned by the matching call to FIND is returned. */
void *
slist_find (SList *slist, SListCallback *find, void *matchdata)
{
  void *result = 0;

  assert (find);

  for (; slist; slist = slist->next)
    {
      result = (*find) (slist, matchdata);
      if (result)
	break;
    }

  return result;
}

/* Return a single list, composed by destructively concatenating the
   items in HEAD and TAIL.  The values of HEAD and TAIL are undefined
   after call