332 lines
6.2 KiB
C
332 lines
6.2 KiB
C
/*
|
|
* Copyright (C) 1992, Board of Trustees of the University of Illinois.
|
|
*
|
|
* Permission is granted to copy and distribute source with out fee.
|
|
* Commercialization of this product requires prior licensing
|
|
* from the National Center for Supercomputing Applications of the
|
|
* University of Illinois. Commercialization includes the integration of this
|
|
* code in part or whole into a product for resale. Free distribution of
|
|
* unmodified source and use of NCSA software is not considered
|
|
* commercialization.
|
|
*
|
|
*/
|
|
|
|
|
|
/*
|
|
* list.c: This module contains list manipulation routines that cunstruct
|
|
* and maintain a linked list of data items. The record at the head of each
|
|
* list contains pointers to the head, tail, and current list position.
|
|
* the list itsself is doubly linked with both next and previous pointers.
|
|
*
|
|
* ddt
|
|
*/
|
|
#include <stdio.h>
|
|
#include "listP.h"
|
|
#include "../config.h"
|
|
#ifndef MALLOC
|
|
#define MALLOC malloc
|
|
#define FREE free
|
|
#endif
|
|
|
|
#define NIL 0
|
|
|
|
#ifndef DISABLE_TRACE
|
|
extern int htmlwTrace;
|
|
#endif
|
|
|
|
static void ListPrintErr(s)
|
|
char *s;
|
|
{
|
|
#ifndef DISABLE_TRACE
|
|
if (htmlwTrace) {
|
|
fprintf(stderr,"%s",s);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* This function returns the data located at the head of the linked list,
|
|
* or NIL if the list is empty. As a side effect current is also set to
|
|
* the head of the list.
|
|
*/
|
|
char *ListHead(theList)
|
|
List theList;
|
|
{
|
|
if (!theList)
|
|
return(NIL);
|
|
theList->current = theList->head;
|
|
if (theList->head)
|
|
return(theList->head->value);
|
|
else
|
|
return(NIL);
|
|
}
|
|
|
|
/*
|
|
* This function returns the data located at the tail of the linked list,
|
|
* or NIL if the list is empty. As a side effect current is also set to
|
|
* the tail of the list.
|
|
*/
|
|
char *ListTail(theList)
|
|
List theList;
|
|
{
|
|
if (!theList)
|
|
return(NIL);
|
|
theList->current = theList->tail;
|
|
if (theList->tail)
|
|
return(theList->tail->value);
|
|
else
|
|
return(NIL);
|
|
}
|
|
|
|
/*
|
|
* This function returns the data located at the current position in the
|
|
* linked list, or NIL if the list is empty.
|
|
*/
|
|
char *ListCurrent(theList)
|
|
List theList;
|
|
{
|
|
if (!theList)
|
|
return(NIL);
|
|
if (theList->current)
|
|
return(theList->current->value);
|
|
else
|
|
return(NIL);
|
|
}
|
|
|
|
/*
|
|
* This function returns the data located at the next element of the linked
|
|
* list after the current position, or NIL if the list is empty, or you
|
|
* are at its end.
|
|
* As a side effect current is also set to the next entry in the list.
|
|
*/
|
|
char *ListNext(theList)
|
|
List theList;
|
|
{
|
|
if (!theList)
|
|
return(NIL);
|
|
if (theList->current) {
|
|
theList->current = theList->current->next;
|
|
return(ListCurrent(theList));
|
|
}
|
|
else
|
|
return(NIL);
|
|
}
|
|
|
|
/*
|
|
* This function returns the data located at the previous element of the linked
|
|
* list before the current position, or NIL if the list is empty.
|
|
* As a side effect current is also set to the previous entry in the list.
|
|
*/
|
|
char *ListPrev(theList)
|
|
List theList;
|
|
{
|
|
if (!theList)
|
|
return(NIL);
|
|
if (theList->current) {
|
|
theList->current = theList->current->prev;
|
|
return(ListCurrent(theList));
|
|
}
|
|
else
|
|
return(NIL);
|
|
}
|
|
|
|
/*
|
|
* Create a list head and initialize it to NIL.
|
|
*/
|
|
List ListCreate()
|
|
{
|
|
List retVal;
|
|
|
|
if (!(retVal = (List) MALLOC(sizeof(struct LISTSTRUCT)))) {
|
|
ListPrintErr("Out of Memory\n");
|
|
return((List) 0);
|
|
}
|
|
retVal->head = NIL;
|
|
retVal->tail = NIL;
|
|
retVal->current = NIL;
|
|
retVal->listCount = 0;
|
|
return(retVal);
|
|
}
|
|
|
|
/*
|
|
* Destroy a list head, and free all associated memory.
|
|
*/
|
|
void ListDestroy(theList)
|
|
List theList;
|
|
{
|
|
struct LISTINSTANCE *l;
|
|
struct LISTINSTANCE *m;
|
|
|
|
if (!theList)
|
|
return;
|
|
l = theList->head;
|
|
while(l) {
|
|
m = l;
|
|
l = l->next;
|
|
FREE(m);
|
|
}
|
|
FREE(theList);
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* Add an entry to the end of the linked list. Current is changed to point to
|
|
* the added element.
|
|
*/
|
|
int ListAddEntry(theList,v)
|
|
/* return 0 on failure */
|
|
List theList;
|
|
char *v; /* data to be added */
|
|
{
|
|
struct LISTINSTANCE *l;
|
|
|
|
if (!(l =(struct LISTINSTANCE *) MALLOC(sizeof(struct LISTINSTANCE)))){
|
|
ListPrintErr("Out of Memory\n");
|
|
return(0);
|
|
}
|
|
|
|
l->value = v;
|
|
|
|
l->next = NIL;
|
|
l->prev = NIL;
|
|
|
|
if (theList->head == NIL)
|
|
theList->tail = theList->head = l;
|
|
else {
|
|
theList->tail->next = l;
|
|
l->prev = theList->tail;
|
|
theList->tail = l;
|
|
}
|
|
|
|
theList->current = l;
|
|
|
|
theList->listCount++;
|
|
|
|
return(1);
|
|
}
|
|
|
|
/*
|
|
* Search the list for an entry with a matching value field, and return
|
|
* a pointer to that list element. Current is changed to point to the
|
|
* element returned.
|
|
*/
|
|
static struct LISTINSTANCE *SearchListByValue(theList,v)
|
|
List theList;
|
|
char *v;
|
|
{
|
|
struct LISTINSTANCE *l;
|
|
|
|
l = theList->head;
|
|
while (l != NIL) {
|
|
if (l->value == v) {
|
|
theList->current = l;
|
|
return(l);
|
|
}
|
|
else {
|
|
l = l->next;
|
|
}
|
|
}
|
|
theList->current = l;
|
|
|
|
return(NIL);
|
|
|
|
}
|
|
|
|
/*
|
|
* Find the list entry with a matching value field, and delete it
|
|
* from the list. Set current to point to the element after the deleted
|
|
* element in the list.
|
|
*/
|
|
int ListDeleteEntry(theList,v)
|
|
/* removes the first occurance of v from the list */
|
|
/* return 0 if value not in list else 1 */
|
|
List theList;
|
|
char *v;
|
|
{
|
|
struct LISTINSTANCE *l;
|
|
char *retV;
|
|
|
|
if (!(l = SearchListByValue(theList,v)))
|
|
return(0);
|
|
|
|
if (l->prev)
|
|
l->prev->next = l->next;
|
|
else
|
|
theList->head = l->next;
|
|
|
|
if (l->next)
|
|
l->next->prev = l->prev;
|
|
else
|
|
theList->tail = l->prev;
|
|
|
|
theList->current = l->next;
|
|
|
|
retV = l->value;
|
|
FREE(l);
|
|
|
|
theList->listCount--;
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
int ListMakeEntryCurrent(theList,entry)
|
|
/* return 0 on failure */
|
|
List theList;
|
|
char *entry;
|
|
{
|
|
struct LISTINSTANCE *l;
|
|
|
|
if (theList) {
|
|
if (!(l = SearchListByValue(theList,entry)))
|
|
return(0);
|
|
theList->current = l;
|
|
return(1);
|
|
}
|
|
return(0);
|
|
|
|
}
|
|
|
|
int ListCount(theList)
|
|
/* return the number of elements in the list */
|
|
/* current position pointer is not affected */
|
|
List theList;
|
|
{
|
|
/*
|
|
char *entry;
|
|
int count;
|
|
struct LISTINSTANCE *saveCurrent;
|
|
*/
|
|
if (theList) {
|
|
return(theList->listCount);
|
|
}
|
|
else {
|
|
return(0);
|
|
}
|
|
}
|
|
|
|
|
|
/* return indexed entry. Index starts at 0 */
|
|
/* the current list pointer will be set to this entry */
|
|
/* return 0 on failure */
|
|
char *ListGetIndexedEntry(theList,number)
|
|
List theList;
|
|
int number;
|
|
{
|
|
char *entry;
|
|
register int x;
|
|
|
|
if (!theList) {
|
|
return(0);
|
|
}
|
|
entry = ListHead(theList);
|
|
for (x = 0; x < number; x++) {
|
|
if (!entry) {
|
|
return(0);
|
|
}
|
|
entry = ListNext(theList);
|
|
}
|
|
return(entry);
|
|
}
|