/* (C) Copyright International Business Machines Corporation 23 January */
/* 1990.  All Rights Reserved. */
/*  */
/* See the file USERAGREEMENT distributed with this software for full */
/* terms and conditions of use. */
/* File: t_linklist.c */
/* Author: David F. Bacon */
#ifndef lint
static char sccsinfo[] = "@(#)t_linklist.c	1.10 3/13/90";
#endif

#include <varargs.h>

#include "li.h"
#include "storage.h"
#include "tablefuncs.h"

#define ll(t, tblnum) ((t)->tbls[tblnum].rep.linklist)

/*ARGSUSED*/
status				/* also doubles as ll_precopy */
ll_alloc(t, tblnum, newinfo)
dfd_table *t;
trepnum tblnum;
valcell newinfo;
{
    ll(t, tblnum) = nil;
    return(SUCCESS);
}


predef_exception
ll_insert(t, tblnum, val)
dfd_table *t;
trepnum tblnum;
valcell val;
{
    linklist_trep *newelem;

    if ((newelem = new(linklist_trep)) is nil)
      return(Depletion);

    newelem->value = val;
    newelem->next = ll(t, tblnum);
    ll(t, tblnum) = newelem;

    return(Normal);
}


/*ARGSUSED*/
void
ll_uninsert(t, tblnum, val)
dfd_table *t;
trepnum tblnum;
valcell val;
{
    linklist_trep *deadelem;


    deadelem = ll(t, tblnum);
    ll(t, tblnum) = cdr(deadelem);
    { dispose(deadelem, linklist_trep); }
}


int
ll_foreach(va_alist)
va_dcl
{
    int rc;
    linklist_trep *list;

    va_tableargs(argv, t, tblnum, func, elemcounter, expectedval)


    list = ll(t, tblnum); 
    *elemcounter = 0;

    foreach_list(list) {
	rc = (*func)(t, tblnum, list->value, *elemcounter, argv);
	if (rc isnt expectedval)
	  return(rc);
	(*elemcounter)++;
    }

    va_end(argv);
    return(expectedval);
}


/*ARGSUSED*/
status
ll_initget(t, tblnum, pos, intpos)
dfd_table *t;
trepnum tblnum;
position *pos;
int intpos;			/* ignored since we are unordered */
{
    if ((pos->linklist = new(linklist_position)) is nil)
      return(FAILURE);

    pos->linklist->nextelem = ll(t, tblnum);
				/* point at first element in list */
    pos->linklist->curelem = nil;
    pos->linklist->prevelem = nil;
    return(SUCCESS);
}


/*ARGSUSED*/
predef_exception
ll_get(t, tblnum, pos, val)
dfd_table *t;
trepnum tblnum;
position *pos;
valcell *val;
{
    if (pos->linklist->nextelem is nil)
      return(NotFound);

    pos->linklist->prevelem = pos->linklist->curelem;
    pos->linklist->curelem = pos->linklist->nextelem;
    pos->linklist->nextelem = cdr(pos->linklist->nextelem);

    *val = pos->linklist->curelem->value;
    return(Normal);
}


/*ARGSUSED*/
void
ll_remove(t, tblnum, val, keynum, seltblnum, pos)
dfd_table *t;
trepnum tblnum;
valcell val;
trepnum keynum;			/* not used */
trepnum seltblnum;		/* ditto */
position *pos;			/* ditto ditto */
{
    linklist_trep *deadelem, *prev;


    if (tblnum isnt seltblnum) {
	deadelem = ll(t, tblnum);
	prev = nil;
	foreach_list(deadelem) {
	    if (deadelem->value.nominal is val.nominal)
	      break;
	    prev = deadelem;
	}
	
    }
    else {
	deadelem = pos->linklist->curelem;
	prev = pos->linklist->prevelem;
	pos->linklist->curelem = prev;
    }

    if (prev)
      cdr(prev) = cdr(deadelem);
    else
      ll(t, tblnum) = cdr(deadelem);

    { dispose(deadelem, linklist_trep); }
}


/*ARGSUSED*/
void
ll_endget(t, tblnum, pos)
dfd_table *t;
trepnum tblnum;
position *pos;
{
    { dispose(pos->linklist, linklist_position); }
}

/******************************************************************************
 *                         Generic Functions                                  *
 *****************************************************************************/

void
ll_finalize(t, tblnum, depth, f_op, sched)
dfd_table *t;
trepnum tblnum;
flag depth;
finalize_op f_op;
schedblock *sched;
{
    linklist_trep *l, *deadelem;

    l = ll(t, tblnum);

    while(l) {
	if (depth is DEEP)
	  (*t->tsdr->finalize)(l->value, f_op, sched);
	deadelem = l;
	l = cdr(l);

	{ dispose(deadelem, linklist_trep); }
    }

    ll(t, tblnum) = nil;
}


status 
ll_equal()
{
    nilerror("ll_equal", "Not yet implemented");
    return(FAILURE);
}


comparison
ll_comparekeys()
{
    nilerror("ll_comparekeys", "Not yet implemented");
    return(FAILURE);
}
