mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-16 06:14:59 +00:00
Estimated hours taken: 0.5 Branches: main runtime/*.c: Convert all remaining C source files to four-space indentation. Fix some deviations from our style guide.
250 lines
5.3 KiB
C
250 lines
5.3 KiB
C
/*
|
|
** vim: ts=4 sw=4 expandtab
|
|
*/
|
|
/*
|
|
** Copyright (C) 1995, 1997, 1999-2000, 2004-2006 The University of Melbourne.
|
|
** This file may only be copied under the terms of the GNU Library General
|
|
** Public License - see the file COPYING.LIB in the Mercury distribution.
|
|
*/
|
|
|
|
/*
|
|
** Linked list module.
|
|
*/
|
|
|
|
#include "mercury_imp.h"
|
|
#include <stdio.h>
|
|
#include "mercury_memory.h"
|
|
#include "mercury_dlist.h"
|
|
|
|
MR_Dlist *
|
|
MR_dlist_makelist0(void)
|
|
{
|
|
MR_Dlist *list;
|
|
|
|
list = MR_GC_NEW(MR_Dlist);
|
|
MR_dlist_data(list) = NULL;
|
|
MR_dlist_next(list) = list;
|
|
MR_dlist_prev(list) = list;
|
|
|
|
return list;
|
|
}
|
|
|
|
MR_Dlist *
|
|
MR_dlist_makelist(const void *data)
|
|
{
|
|
MR_Dlist *list;
|
|
|
|
MR_assert(data != NULL);
|
|
list = MR_dlist_makelist0();
|
|
MR_dlist_addhead(list, data);
|
|
return list;
|
|
}
|
|
|
|
MR_Dlist *
|
|
MR_dlist_addhead(MR_Dlist *list, const void *data)
|
|
{
|
|
MR_Dlist *item;
|
|
|
|
if (list == NULL) {
|
|
list = MR_dlist_makelist0();
|
|
}
|
|
|
|
item = MR_GC_NEW(MR_Dlist);
|
|
MR_dlist_data(item) = data;
|
|
MR_dlist_length_field(list)++;
|
|
|
|
/* item's pointers */
|
|
MR_dlist_next(item) = MR_dlist_next(list);
|
|
MR_dlist_prev(item) = list;
|
|
/* neighbours' pointers */
|
|
MR_dlist_next(MR_dlist_prev(item)) = item;
|
|
MR_dlist_prev(MR_dlist_next(item)) = item;
|
|
|
|
return list;
|
|
}
|
|
|
|
MR_Dlist *
|
|
MR_dlist_addtail(MR_Dlist *list, const void *data)
|
|
{
|
|
MR_Dlist *item;
|
|
|
|
if (list == NULL) {
|
|
list = MR_dlist_makelist0();
|
|
}
|
|
|
|
item = MR_GC_NEW(MR_Dlist);
|
|
MR_dlist_data(item) = data;
|
|
MR_dlist_length_field(list)++;
|
|
|
|
/* item's pointers */
|
|
MR_dlist_next(item) = list;
|
|
MR_dlist_prev(item) = MR_dlist_prev(list);
|
|
/* neighbours' pointers */
|
|
MR_dlist_next(MR_dlist_prev(item)) = item;
|
|
MR_dlist_prev(MR_dlist_next(item)) = item;
|
|
|
|
return list;
|
|
}
|
|
|
|
MR_Dlist *
|
|
MR_dlist_addlist(MR_Dlist *list1, MR_Dlist *list2)
|
|
{
|
|
if (list1 == NULL) {
|
|
list1 = MR_dlist_makelist0();
|
|
}
|
|
|
|
if (list2 == NULL) {
|
|
list2 = MR_dlist_makelist0();
|
|
}
|
|
|
|
if (MR_dlist_length(list2) > 0) {
|
|
if (MR_dlist_length(list1) == 0) {
|
|
MR_dlist_data(list1) = MR_dlist_data(list2);
|
|
/* pointers from header */
|
|
MR_dlist_next(list1) = MR_dlist_next(list2);
|
|
MR_dlist_prev(list1) = MR_dlist_prev(list2);
|
|
/* pointers to header */
|
|
MR_dlist_prev(MR_dlist_next(list1)) = list1;
|
|
MR_dlist_next(MR_dlist_prev(list1)) = list1;
|
|
} else {
|
|
MR_dlist_length_field(list1) = MR_dlist_length(list1)
|
|
+ MR_dlist_length(list2);
|
|
/* end of list 1 to start of list 2 */
|
|
MR_dlist_next(MR_dlist_prev(list1)) = MR_dlist_next(list2);
|
|
MR_dlist_prev(MR_dlist_next(list2)) = MR_dlist_prev(list1);
|
|
/* end of list 2 to start of list 1 */
|
|
MR_dlist_next(MR_dlist_prev(list2)) = list1;
|
|
MR_dlist_prev(list1) = MR_dlist_prev(list2);
|
|
}
|
|
}
|
|
|
|
MR_GC_free(list2);
|
|
return list1;
|
|
}
|
|
|
|
MR_Dlist *
|
|
MR_dlist_addndlist(MR_Dlist *list1, MR_Dlist *list2)
|
|
{
|
|
MR_Dlist *ptr;
|
|
|
|
if (list1 == NULL) {
|
|
list1 = MR_dlist_makelist0();
|
|
}
|
|
|
|
if (list2 == NULL) {
|
|
list2 = MR_dlist_makelist0();
|
|
}
|
|
|
|
MR_for_dlist (ptr, list2) {
|
|
MR_dlist_addtail(list1, MR_dlist_data(ptr));
|
|
}
|
|
|
|
return list1;
|
|
}
|
|
|
|
void
|
|
MR_dlist_insert_before(MR_Dlist *list, MR_Dlist *where, const void *data)
|
|
{
|
|
MR_Dlist *item;
|
|
|
|
item = MR_GC_NEW(MR_Dlist);
|
|
MR_dlist_data(item) = data;
|
|
MR_dlist_length_field(list)++;
|
|
|
|
/* item's pointers */
|
|
MR_dlist_next(item) = where;
|
|
MR_dlist_prev(item) = MR_dlist_prev(where);
|
|
/* neighbour's pointers */
|
|
MR_dlist_next(MR_dlist_prev(item)) = item;
|
|
MR_dlist_prev(MR_dlist_next(item)) = item;
|
|
}
|
|
|
|
void
|
|
MR_dlist_insert_after(MR_Dlist *list, MR_Dlist *where, const void *data)
|
|
{
|
|
MR_Dlist *item;
|
|
|
|
item = MR_GC_NEW(MR_Dlist);
|
|
MR_dlist_data(item) = data;
|
|
MR_dlist_length_field(list)++;
|
|
|
|
/* item's pointers */
|
|
MR_dlist_next(item) = MR_dlist_next(where);
|
|
MR_dlist_prev(item) = where;
|
|
/* neighbour's pointers */
|
|
MR_dlist_next(MR_dlist_prev(item)) = item;
|
|
MR_dlist_prev(MR_dlist_next(item)) = item;
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
** Return the length of a given list.
|
|
*/
|
|
|
|
int
|
|
MR_dlist_maybe_null_length(const MR_Dlist *list)
|
|
{
|
|
if (list == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
return MR_dlist_length(list);
|
|
}
|
|
|
|
/*
|
|
** Delete an item from its linked list, and free the node,
|
|
** and maybe the data.
|
|
*/
|
|
|
|
void
|
|
MR_dlist_delete(MR_Dlist *list, MR_Dlist *item, void (* func)(const void *))
|
|
{
|
|
if (list == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (item == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (func != NULL) {
|
|
func(MR_dlist_data(item));
|
|
}
|
|
|
|
MR_dlist_length_field(list)--;
|
|
MR_dlist_next(MR_dlist_prev(item)) = MR_dlist_next(item);
|
|
MR_dlist_prev(MR_dlist_next(item)) = MR_dlist_prev(item);
|
|
|
|
MR_GC_free(item);
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
MR_dlist_oldlist(MR_Dlist *list, void (* func)(const void *))
|
|
{
|
|
MR_Dlist *ptr;
|
|
MR_Dlist *item;
|
|
|
|
if (list == NULL) {
|
|
return;
|
|
}
|
|
|
|
ptr = MR_dlist_next(list);
|
|
while (ptr != list) {
|
|
item = ptr;
|
|
ptr = MR_dlist_next(ptr);
|
|
|
|
if (func != NULL) {
|
|
func(MR_dlist_data(item));
|
|
}
|
|
|
|
MR_GC_free(item);
|
|
}
|
|
|
|
MR_GC_free(list);
|
|
|
|
return;
|
|
}
|