mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-18 22:03:14 +01:00
463 lines
9.2 KiB
C
463 lines
9.2 KiB
C
/*_ list.c Mon Oct 31 1994 */
|
|
/* Copyright (C) 1986-1994 by Symantec */
|
|
/* All Rights Reserved */
|
|
/* Written by Walter Bright */
|
|
|
|
#ifndef __STDIO_H
|
|
#include <stdio.h>
|
|
#endif
|
|
#ifndef __STRING_H
|
|
#include <string.h>
|
|
#endif
|
|
#ifndef __STDARG_H
|
|
#include <stdarg.h>
|
|
#endif
|
|
#ifndef assert
|
|
#include <assert.h>
|
|
#endif
|
|
#ifndef LIST_H
|
|
#include "list.h"
|
|
#endif
|
|
#ifndef MEM_H
|
|
#include "mem.h"
|
|
#endif
|
|
|
|
#if MEM_DEBUG
|
|
#define fileline __FILE__,__LINE__
|
|
#else
|
|
#define fileline
|
|
#endif
|
|
|
|
#ifndef list_freelist
|
|
list_t list_freelist = NULL; /* list of free list entries */
|
|
#endif
|
|
static int nlist; /* number of list items created */
|
|
int list_inited = 0; /* 1 if initialized */
|
|
|
|
/* Free storage allocation */
|
|
#ifndef list_new
|
|
|
|
#if (__ZTC__ || __SC__) && !MEM_DEBUG
|
|
#define list_new() ((list_t) mem_fmalloc(sizeof(struct LIST)))
|
|
#define list_delete(list) mem_ffree(list)
|
|
#else
|
|
#if MEM_DEBUG
|
|
#define list_new() ((list_t) mem_calloc_debug(sizeof(struct LIST),file,line))
|
|
#else
|
|
#define list_new() ((list_t) mem_malloc(sizeof(struct LIST)))
|
|
#endif
|
|
#define list_delete(list) mem_free(list)
|
|
#endif
|
|
|
|
#endif
|
|
|
|
/**********************/
|
|
|
|
void list_init()
|
|
{
|
|
#ifdef DEBUG
|
|
assert(mem_inited);
|
|
#endif
|
|
if (list_inited == 0)
|
|
{ nlist = 0;
|
|
list_inited++;
|
|
}
|
|
}
|
|
|
|
/*******************/
|
|
|
|
void list_term()
|
|
{
|
|
if (list_inited)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Max # of lists = %d\n",nlist);
|
|
#endif
|
|
while (list_freelist)
|
|
{ list_t list;
|
|
|
|
list = list_next(list_freelist);
|
|
list_delete(list_freelist);
|
|
list_freelist = list;
|
|
nlist--;
|
|
}
|
|
#ifdef DEBUG
|
|
if (nlist)
|
|
printf("nlist = %d\n",nlist);
|
|
#endif
|
|
#if !MEM_DEBUG
|
|
assert(nlist == 0);
|
|
#endif
|
|
list_inited = 0;
|
|
}
|
|
}
|
|
|
|
/****************************
|
|
* Allocate list item.
|
|
*/
|
|
|
|
static list_t list_alloc
|
|
#if MEM_DEBUG
|
|
(char *file,int line)
|
|
#else
|
|
()
|
|
#endif
|
|
{ list_t list;
|
|
|
|
if (list_freelist)
|
|
{ list = list_freelist;
|
|
list_freelist = list_next(list);
|
|
#if MEM_DEBUG
|
|
mem_setnewfileline(list,file,line);
|
|
#endif
|
|
}
|
|
else
|
|
{ nlist++;
|
|
list = list_new();
|
|
}
|
|
return list;
|
|
}
|
|
|
|
/******************************/
|
|
|
|
void list_free(list_t *plist,list_free_fp freeptr)
|
|
{ list_t list,listnext;
|
|
|
|
list = *plist;
|
|
*plist = 0; /* block any circular reference bugs */
|
|
while (list && --list->count == 0)
|
|
{ listnext = list_next(list);
|
|
if (freeptr)
|
|
(*freeptr)(list_ptr(list));
|
|
#if DEBUG
|
|
memset(list,0,sizeof(*list));
|
|
#endif
|
|
#if 1
|
|
list->next = list_freelist;
|
|
list_freelist = list;
|
|
#else
|
|
list_delete(list);
|
|
nlist--;
|
|
#endif
|
|
list = listnext;
|
|
}
|
|
}
|
|
|
|
/***************************/
|
|
|
|
void *list_subtract(list_t *plist,void *ptr)
|
|
{ list_t list;
|
|
|
|
while ((list = *plist) != 0)
|
|
{
|
|
if (list_ptr(list) == ptr)
|
|
{
|
|
if (--list->count == 0)
|
|
{ *plist = list_next(list);
|
|
list->next = list_freelist;
|
|
list_freelist = list;
|
|
}
|
|
return ptr;
|
|
}
|
|
else
|
|
plist = &(list_next(list));
|
|
}
|
|
return NULL; /* it wasn't in the list */
|
|
}
|
|
|
|
/*************************/
|
|
|
|
#if MEM_DEBUG
|
|
#undef list_append
|
|
|
|
list_t list_append(list_t *plist,void *ptr)
|
|
{
|
|
return list_append_debug(plist,ptr,__FILE__,__LINE__);
|
|
}
|
|
|
|
list_t list_append_debug(list_t *plist,void *ptr,char *file,int line)
|
|
#else
|
|
list_t list_append(list_t *plist,void *ptr)
|
|
#endif
|
|
{ register list_t list;
|
|
|
|
while (*plist)
|
|
plist = &(list_next(*plist)); /* find end of list */
|
|
|
|
#if MEM_DEBUG
|
|
list = list_alloc(file,line);
|
|
#else
|
|
list = list_alloc();
|
|
#endif
|
|
if (list)
|
|
{ *plist = list;
|
|
list_next(list) = 0;
|
|
list_ptr(list) = ptr;
|
|
list->count = 1;
|
|
}
|
|
return list;
|
|
}
|
|
|
|
/*************************/
|
|
|
|
list_t list_prepend(list_t *plist,void *ptr)
|
|
{ register list_t list;
|
|
|
|
list = list_alloc(fileline);
|
|
if (list)
|
|
{ list_next(list) = *plist;
|
|
list_ptr(list) = ptr;
|
|
list->count = 1;
|
|
*plist = list;
|
|
}
|
|
return list;
|
|
}
|
|
|
|
/*************************/
|
|
|
|
#if __SC__ && __INTSIZE == 4 && _M_I86 && !_DEBUG_TRACE
|
|
|
|
__declspec(naked) int __pascal list_nitems(list_t list)
|
|
{
|
|
_asm
|
|
{
|
|
mov ECX,list-4[ESP]
|
|
xor EAX,EAX
|
|
test ECX,ECX
|
|
jz L1
|
|
L2:
|
|
mov ECX,[ECX]LIST.next
|
|
inc EAX
|
|
test ECX,ECX
|
|
jnz L2
|
|
L1:
|
|
ret 4
|
|
}
|
|
}
|
|
|
|
#else
|
|
|
|
#if __DMC__
|
|
int __pascal list_nitems(list_t list)
|
|
#else
|
|
int list_nitems(list_t list)
|
|
#endif
|
|
{ register int n;
|
|
|
|
n = 0;
|
|
while (list)
|
|
{ n++;
|
|
list = list_next(list);
|
|
}
|
|
return n;
|
|
}
|
|
|
|
#endif
|
|
|
|
/*************************/
|
|
|
|
list_t list_nth(list_t list,int n)
|
|
{ register int i;
|
|
|
|
for (i = 0; i < n; i++)
|
|
{ assert(list);
|
|
list = list_next(list);
|
|
}
|
|
return list;
|
|
}
|
|
|
|
/*************************/
|
|
|
|
list_t list_last(list_t list)
|
|
{
|
|
if (list)
|
|
while (list_next(list))
|
|
list = list_next(list);
|
|
return list;
|
|
}
|
|
|
|
/**************************/
|
|
|
|
list_t list_prev(list_t start,list_t list)
|
|
{
|
|
if (start)
|
|
{ if (start == list)
|
|
start = NULL;
|
|
else
|
|
while (list_next(start) != list)
|
|
{ start = list_next(start);
|
|
assert(start);
|
|
}
|
|
}
|
|
return start;
|
|
}
|
|
|
|
/****************************/
|
|
|
|
list_t list_copy(list_t list)
|
|
{ list_t c;
|
|
|
|
c = NULL;
|
|
for (; list; list = list_next(list))
|
|
list_append(&c,list_ptr(list));
|
|
return c;
|
|
}
|
|
|
|
/****************************/
|
|
|
|
int list_equal(list_t list1,list_t list2)
|
|
{
|
|
while (list1 && list2)
|
|
{
|
|
if (list_ptr(list1) != list_ptr(list2))
|
|
break;
|
|
list1 = list_next(list1);
|
|
list2 = list_next(list2);
|
|
}
|
|
return list1 == list2;
|
|
}
|
|
|
|
/****************************/
|
|
|
|
int list_cmp(list_t list1,list_t list2,int (*func)(void *,void *))
|
|
{ int result = 0;
|
|
|
|
while (1)
|
|
{
|
|
if (!list1)
|
|
{ if (list2)
|
|
result = -1; /* list1 < list2 */
|
|
break;
|
|
}
|
|
if (!list2)
|
|
{ result = 1; /* list1 > list2 */
|
|
break;
|
|
}
|
|
result = (*func)(list_ptr(list1),list_ptr(list2));
|
|
if (result)
|
|
break;
|
|
list1 = list_next(list1);
|
|
list2 = list_next(list2);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*****************************/
|
|
|
|
list_t list_inlist(list_t list,void *ptr)
|
|
{
|
|
for (; list; list = list_next(list))
|
|
if (list_ptr(list) == ptr)
|
|
break;
|
|
return list;
|
|
}
|
|
|
|
/******************************/
|
|
|
|
list_t list_cat(list_t *pl1,list_t l2)
|
|
{ list_t *pl;
|
|
|
|
for (pl = pl1; *pl; pl = &list_next(*pl))
|
|
;
|
|
*pl = l2;
|
|
return *pl1;
|
|
}
|
|
|
|
/******************************/
|
|
|
|
list_t list_build(void *p,...)
|
|
{ list_t alist;
|
|
list_t *pe;
|
|
va_list ap;
|
|
|
|
alist = NULL;
|
|
pe = &alist;
|
|
for (va_start(ap,p); p; p = va_arg(ap,void *))
|
|
{ list_t list;
|
|
|
|
list = list_alloc(fileline);
|
|
if (list)
|
|
{ list_next(list) = NULL;
|
|
list_ptr(list) = p;
|
|
list->count = 1;
|
|
*pe = list;
|
|
pe = &list_next(list);
|
|
}
|
|
}
|
|
va_end(ap);
|
|
return alist;
|
|
}
|
|
|
|
/***************************************
|
|
* Apply a function to each member of a list.
|
|
*/
|
|
|
|
void list_apply(list_t *plist,void (*fp)(void *))
|
|
{
|
|
list_t l;
|
|
|
|
if (fp)
|
|
for (l = *plist; l; l = list_next(l))
|
|
{
|
|
(*fp)(list_ptr(l));
|
|
}
|
|
}
|
|
|
|
/*********************************************
|
|
* Reverse a list.
|
|
*/
|
|
|
|
list_t list_reverse(list_t l)
|
|
{ list_t r;
|
|
list_t ln;
|
|
|
|
r = NULL;
|
|
while (l)
|
|
{ ln = list_next(l);
|
|
list_next(l) = r;
|
|
r = l;
|
|
l = ln;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
/**********************************************
|
|
* Copy list of pointers into an array of pointers.
|
|
*/
|
|
|
|
void list_copyinto(list_t l, void *pa)
|
|
{
|
|
void **ppa = (void **)pa;
|
|
for (; l; l = list_next(l))
|
|
*(ppa)++ = list_ptr(l);
|
|
}
|
|
|
|
/**********************************************
|
|
* Insert item into list at nth position.
|
|
*/
|
|
|
|
list_t list_insert(list_t *pl,void *ptr,int n)
|
|
{
|
|
list_t list;
|
|
|
|
while (n)
|
|
{
|
|
pl = &list_next(*pl);
|
|
n--;
|
|
}
|
|
list = list_alloc(fileline);
|
|
if (list)
|
|
{
|
|
list_next(list) = *pl;
|
|
*pl = list;
|
|
list_ptr(list) = ptr;
|
|
list->count = 1;
|
|
}
|
|
return list;
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
void list_free(list_t *l) { list_free(l,FPNULL); }
|
|
#endif
|
|
|