Files
ldc/tk/list.c
Alexey Prokhin caad8cde58 Squashed 'dmd2/' content from commit 10017d5
git-subtree-dir: dmd2
git-subtree-split: 10017d50eaaff4ecdc37a0153b6c37ea0b004c81
2012-04-05 11:10:48 +04:00

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