Files
mercury/runtime/mercury_dlist.h
Mark Brown d465fa53cb Update the COPYING.LIB file and references to it.
Discussion of these changes can be found on the Mercury developers
mailing list archives from June 2018.

COPYING.LIB:
    Add a special linking exception to the LGPL.

*:
    Update references to COPYING.LIB.

    Clean up some minor errors that have accumulated in copyright
    messages.
2018-06-09 17:43:12 +10:00

120 lines
4.8 KiB
C

// vim: ts=4 sw=4 expandtab ft=c
// Copyright (C) 1995-1997,2000, 2004-2005 The University of Melbourne.
// Copyright (C) 2016, 2018 The Mercury team.
// This file is distributed under the terms specified in COPYING.LIB.
// mercury_dlist.h - defines a doubly-linked list type.
#ifndef MERCURY_DLIST_H
#define MERCURY_DLIST_H
// The lists we use are doubly-linked.
// They each have a header node, and we store the length of the list
// in the header node.
typedef struct MR_Dlist_Struct MR_Dlist;
struct MR_Dlist_Struct {
union {
const void *MR_dlist_data;
int MR_dlist_length;
} MR_dlist_union;
MR_Dlist *MR_dlist_prev;
MR_Dlist *MR_dlist_next;
};
// Make an empty list.
extern MR_Dlist *MR_dlist_makelist0(void);
// Make a list with "data" as its only element.
extern MR_Dlist *MR_dlist_makelist(const void *data);
// Add "data" to the head of "list".
extern MR_Dlist *MR_dlist_addhead(MR_Dlist *list, const void *data);
// Add "data" to the tail of "list".
extern MR_Dlist *MR_dlist_addtail(MR_Dlist *list, const void *data);
// Destructively append list2 to list1. Since the header of list2 is not
// meaningful after the operation, it is freed.
extern MR_Dlist *MR_dlist_addlist(MR_Dlist *list1, MR_Dlist *list2);
// (Semi-) nondestructively append list2 to list1. The header of list1 is
// indeed altered, but only the data pointers of list2 are used.
extern MR_Dlist *MR_dlist_addndlist(MR_Dlist *list1, MR_Dlist *list2);
// Insert "data" into "list" before the element given by "where".
extern void MR_dlist_insert_before(MR_Dlist *list, MR_Dlist *where,
const void *data);
// Insert "data" into "list" after the element given by "where".
extern void MR_dlist_insert_after(MR_Dlist *list, MR_Dlist *where,
const void *data);
// Return the length of "list".
extern int MR_dlist_maybe_null_length(const MR_Dlist *list);
// Delete the node given by "item" from its linked list "list". Free this node,
// and, if "func" is non-NULL, use it to free the data item in that node.
extern void MR_dlist_delete(MR_Dlist *list, MR_Dlist *item,
void (* func)(const void *));
// Free the whole list, including the header. If func is non-NULL, then use it
// to free the data items pointed to by the list nodes.
extern void MR_dlist_oldlist(MR_Dlist *list,
void (* func)(const void *));
// Macros to make programming with this module easier.
#define MR_dlist_next(ptr) (ptr)->MR_dlist_next
#define MR_dlist_prev(ptr) (ptr)->MR_dlist_prev
#define MR_dlist_data(ptr) (ptr)->MR_dlist_union.MR_dlist_data
#define MR_dlist_length_field(list) ((list)->MR_dlist_union. \
MR_dlist_length)
#define MR_dlist_length(list) ((list) != NULL ? \
MR_dlist_length_field(list) \
: 0)
#define MR_dlist_first_ptr(list) ((list)->MR_dlist_next)
#define MR_dlist_last_ptr(list) ((list)->MR_dlist_prev)
#define MR_dlist_first(list) ((list)->MR_dlist_next-> \
MR_dlist_union.MR_dlist_data)
#define MR_dlist_last(list) ((list)->MR_dlist_prev-> \
MR_dlist_union.MR_dlist_data)
#define MR_for_dlist(p, l) \
for ( \
(p) = ((l)? MR_dlist_next((l)): NULL); \
(p) != (l) && (p) != NULL; \
(p) = MR_dlist_next((p)) \
)
#define MR_for_2dlist(p1, p2, l1, l2) \
for ( \
(p1) = ((l1)? MR_dlist_next((l1)): NULL), \
(p2) = ((l2)? MR_dlist_next((l2)): NULL); \
(p1) != (l1) && (p1) != NULL && (p2) != (l2) && (p2) != NULL; \
(p1) = MR_dlist_next((p1)), (p2) = MR_dlist_next((p2)) \
)
#define MR_for_undlist(p, np, l) \
for ( \
(p) = ((l)? MR_dlist_next((l)): NULL), \
(np) = ((p)? MR_dlist_next((p)): NULL); \
(p) != (l) && (p) != NULL; \
(p) = (np), (np) = ((p)? MR_dlist_next((p)): NULL) \
)
#define MR_end_dlist(p, l) \
((p) == (l) || (p) == NULL)
#endif // not MERCURY_DLIST_H