mirror of
git://git.code.sf.net/p/zsh/code
synced 2024-11-18 21:14:11 +01:00
301 lines
6.0 KiB
C
301 lines
6.0 KiB
C
/*
|
|
* linklist.c - linked lists
|
|
*
|
|
* This file is part of zsh, the Z shell.
|
|
*
|
|
* Copyright (c) 1992-1997 Paul Falstad
|
|
* All rights reserved.
|
|
*
|
|
* Permission is hereby granted, without written agreement and without
|
|
* license or royalty fees, to use, copy, modify, and distribute this
|
|
* software and to distribute modified versions of this software for any
|
|
* purpose, provided that the above copyright notice and the following
|
|
* two paragraphs appear in all copies of this software.
|
|
*
|
|
* In no event shall Paul Falstad or the Zsh Development Group be liable
|
|
* to any party for direct, indirect, special, incidental, or consequential
|
|
* damages arising out of the use of this software and its documentation,
|
|
* even if Paul Falstad and the Zsh Development Group have been advised of
|
|
* the possibility of such damage.
|
|
*
|
|
* Paul Falstad and the Zsh Development Group specifically disclaim any
|
|
* warranties, including, but not limited to, the implied warranties of
|
|
* merchantability and fitness for a particular purpose. The software
|
|
* provided hereunder is on an "as is" basis, and Paul Falstad and the
|
|
* Zsh Development Group have no obligation to provide maintenance,
|
|
* support, updates, enhancements, or modifications.
|
|
*
|
|
*/
|
|
|
|
#include "zsh.mdh"
|
|
#include "linklist.pro"
|
|
|
|
/* Get an empty linked list header */
|
|
|
|
/**/
|
|
mod_export LinkList
|
|
newlinklist(void)
|
|
{
|
|
LinkList list;
|
|
|
|
list = (LinkList) zhalloc(sizeof *list);
|
|
list->list.first = NULL;
|
|
list->list.last = &list->node;
|
|
list->list.flags = 0;
|
|
return list;
|
|
}
|
|
|
|
/**/
|
|
mod_export LinkList
|
|
znewlinklist(void)
|
|
{
|
|
LinkList list;
|
|
|
|
list = (LinkList) zalloc(sizeof *list);
|
|
list->list.first = NULL;
|
|
list->list.last = &list->node;
|
|
list->list.flags = 0;
|
|
return list;
|
|
}
|
|
|
|
/* Insert a node in a linked list after a given node */
|
|
|
|
/**/
|
|
mod_export LinkNode
|
|
insertlinknode(LinkList list, LinkNode node, void *dat)
|
|
{
|
|
LinkNode tmp, new;
|
|
|
|
tmp = node->next;
|
|
node->next = new = (LinkNode) zhalloc(sizeof *tmp);
|
|
new->prev = node;
|
|
new->dat = dat;
|
|
new->next = tmp;
|
|
if (tmp)
|
|
tmp->prev = new;
|
|
else
|
|
list->list.last = new;
|
|
return new;
|
|
}
|
|
|
|
/**/
|
|
mod_export LinkNode
|
|
zinsertlinknode(LinkList list, LinkNode node, void *dat)
|
|
{
|
|
LinkNode tmp, new;
|
|
|
|
tmp = node->next;
|
|
node->next = new = (LinkNode) zalloc(sizeof *tmp);
|
|
new->prev = node;
|
|
new->dat = dat;
|
|
new->next = tmp;
|
|
if (tmp)
|
|
tmp->prev = new;
|
|
else
|
|
list->list.last = new;
|
|
return new;
|
|
}
|
|
|
|
/* Insert an already-existing node into a linked list after a given node */
|
|
|
|
/**/
|
|
mod_export LinkNode
|
|
uinsertlinknode(LinkList list, LinkNode node, LinkNode new)
|
|
{
|
|
LinkNode tmp = node->next;
|
|
node->next = new;
|
|
new->prev = node;
|
|
new->next = tmp;
|
|
if (tmp)
|
|
tmp->prev = new;
|
|
else
|
|
list->list.last = new;
|
|
return new;
|
|
}
|
|
|
|
/* Insert a list in another list */
|
|
|
|
/**/
|
|
mod_export void
|
|
insertlinklist(LinkList l, LinkNode where, LinkList x)
|
|
{
|
|
LinkNode nx;
|
|
|
|
nx = where->next;
|
|
if (!firstnode(l))
|
|
return;
|
|
where->next = firstnode(l);
|
|
l->list.last->next = nx;
|
|
l->list.first->prev = where;
|
|
if (nx)
|
|
nx->prev = lastnode(l);
|
|
else
|
|
x->list.last = lastnode(l);
|
|
}
|
|
|
|
/* Pop the top node off a linked list and free it. */
|
|
|
|
/**/
|
|
mod_export void *
|
|
getlinknode(LinkList list)
|
|
{
|
|
void *dat;
|
|
LinkNode node;
|
|
|
|
if (!(node = firstnode(list)))
|
|
return NULL;
|
|
dat = node->dat;
|
|
list->list.first = node->next;
|
|
if (node->next)
|
|
node->next->prev = &list->node;
|
|
else
|
|
list->list.last = &list->node;
|
|
zfree(node, sizeof *node);
|
|
return dat;
|
|
}
|
|
|
|
/* Pop the top node off a linked list without freeing it. */
|
|
|
|
/**/
|
|
mod_export void *
|
|
ugetnode(LinkList list)
|
|
{
|
|
void *dat;
|
|
LinkNode node;
|
|
|
|
if (!(node = firstnode(list)))
|
|
return NULL;
|
|
dat = node->dat;
|
|
list->list.first = node->next;
|
|
if (node->next)
|
|
node->next->prev = &list->node;
|
|
else
|
|
list->list.last = &list->node;
|
|
return dat;
|
|
}
|
|
|
|
/* Remove a node from a linked list */
|
|
|
|
/**/
|
|
mod_export void *
|
|
remnode(LinkList list, LinkNode nd)
|
|
{
|
|
void *dat;
|
|
|
|
nd->prev->next = nd->next;
|
|
if (nd->next)
|
|
nd->next->prev = nd->prev;
|
|
else
|
|
list->list.last = nd->prev;
|
|
dat = nd->dat;
|
|
zfree(nd, sizeof *nd);
|
|
|
|
return dat;
|
|
}
|
|
|
|
/* Remove a node from a linked list without freeing */
|
|
|
|
/**/
|
|
mod_export void *
|
|
uremnode(LinkList list, LinkNode nd)
|
|
{
|
|
void *dat;
|
|
|
|
nd->prev->next = nd->next;
|
|
if (nd->next)
|
|
nd->next->prev = nd->prev;
|
|
else
|
|
list->list.last = nd->prev;
|
|
dat = nd->dat;
|
|
return dat;
|
|
}
|
|
|
|
/* Free a linked list */
|
|
|
|
/**/
|
|
mod_export void
|
|
freelinklist(LinkList list, FreeFunc freefunc)
|
|
{
|
|
LinkNode node, next;
|
|
|
|
for (node = firstnode(list); node; node = next) {
|
|
next = node->next;
|
|
if (freefunc)
|
|
freefunc(node->dat);
|
|
zfree(node, sizeof *node);
|
|
}
|
|
zfree(list, sizeof *list);
|
|
}
|
|
|
|
/* Count the number of nodes in a linked list */
|
|
|
|
/**/
|
|
mod_export int
|
|
countlinknodes(LinkList list)
|
|
{
|
|
LinkNode nd;
|
|
int ct = 0;
|
|
|
|
for (nd = firstnode(list); nd; incnode(nd), ct++);
|
|
return ct;
|
|
}
|
|
|
|
/**/
|
|
mod_export void
|
|
rolllist(LinkList l, LinkNode nd)
|
|
{
|
|
l->list.last->next = firstnode(l);
|
|
l->list.first->prev = lastnode(l);
|
|
l->list.first = nd;
|
|
l->list.last = nd->prev;
|
|
nd->prev = &l->node;
|
|
l->list.last->next = 0;
|
|
}
|
|
|
|
/**/
|
|
mod_export LinkList
|
|
newsizedlist(int size)
|
|
{
|
|
LinkList list;
|
|
LinkNode node;
|
|
|
|
list = (LinkList) zhalloc(sizeof *list + (size * sizeof *node));
|
|
|
|
list->list.first = &list[1].node;
|
|
for (node = firstnode(list); size; size--, node++) {
|
|
node->prev = node - 1;
|
|
node->next = node + 1;
|
|
}
|
|
list->list.last = node - 1;
|
|
list->list.first->prev = &list->node;
|
|
node[-1].next = NULL;
|
|
|
|
return list;
|
|
}
|
|
|
|
/**/
|
|
mod_export int
|
|
listcontains(LinkList list, void *dat)
|
|
{
|
|
LinkNode node;
|
|
|
|
for (node = firstnode(list); node; incnode(node))
|
|
if (getdata(node) == dat)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**/
|
|
mod_export LinkNode
|
|
linknodebydatum(LinkList list, void *dat)
|
|
{
|
|
LinkNode node;
|
|
|
|
for (node = firstnode(list); node; incnode(node))
|
|
if (getdata(node) == dat)
|
|
return node;
|
|
|
|
return NULL;
|
|
}
|