/*
#ident	"@(#)smail/src:RELEASE-3_2_0_121:list.c,v 1.13 2005/07/11 19:22:09 woods Exp"
 */

/*
 *    Copyright (C) 1987, 1988 Ronald S. Karr and Landon Curt Noll
 *    Copyright (C) 1992  Ronald S. Karr
 * 
 * See the file COPYING, distributed with smail, for restriction
 * and warranty information.
 */

/*
 * list.c:
 *
 *	external functions: add_intlist, remove_intlist_matching, remove_intlist_at
 */

#include "defs.h"

#include <sys/types.h>
#include <stdio.h>

#ifdef STDC_HEADERS
# include <stdlib.h>
# include <stddef.h>
#else
# ifdef HAVE_STDLIB_H
#  include <stdlib.h>
# endif
#endif

#ifdef HAVE_STRING_H
# if !defined(STDC_HEADERS) && defined(HAVE_MEMORY_H)
#  include <memory.h>
# endif
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif

#ifdef __STDC__
# include <stdarg.h>
#else
# include <varargs.h>
#endif

#if defined(HAVE_UNISTD_H)
# include <unistd.h>
#endif

#include "smail.h"
#include "smailstring.h"
#include "addr.h"			/* for "log.h" */
#include "exitcodes.h"
#include "log.h"
#include "main.h"
#include "alloc.h"
#include "list.h"
#include "debug.h"
#include "smailport.h"

/*
 * add_intlist - add a (long int) value to a list of (long int) values
 *
 * Look through the list headed by lp for unused entries and record the given
 * value in the data field of the list note.  If no unused entry is found then
 * add a new entry to the head of the list and use it.
 *
 * Returns the (possibly new) head of the list.
 */
intlist_t *
add_intlist(lp, val)
    intlist_t *lp;
    long int val;
{
    register intlist_t *nc;

    for (nc = lp; nc; nc = nc->succ) {
	if (!nc->i_used) {
	    nc->i_val = val;		/* store it here */
	    nc->i_used = TRUE;		/* mark this one re-used */

	    return lp;			/* return old header */
	}
    }
    /*
     * no unused entries -- add a new one to the head of the list
     */
    nc = (intlist_t *) xmalloc(sizeof(intlist_t)); /* create it */
    nc->i_val = val;			/* store it */
    nc->i_used = TRUE;			/* mark it used */
    nc->succ = lp;			/* link it in at the head */

    return nc;				/* return new list header */
}


/*
 * remove_intlist_matching - remove an item from a list of (long int) values
 *
 * We don't bother actually try to free allocated list nodes -- instead we just
 * mark entries as "unused".  First match wins, but we assume the values stored
 * to be unique.
 *
 * Returns TRUE if the item was found in the list, FALSE otherwise.
 */
int
remove_intlist_matching(lp, val)
    register intlist_t *lp;
    register long int val;
{
    register intlist_t *nc;

    for (nc = lp; nc; nc = nc->succ) {
	if (nc->i_used && nc->i_val == val) {
	    nc->i_used = FALSE;		/* mark this entry unused */

	    return TRUE;
	}
    }
    /* note this function is called for every child, not just runq's... */

    return FALSE;
}

/*
 * free_intlist - free up a whole list
 */
void
free_intlist(donelst)
    intlist_t *donelst;
{
    register intlist_t *cur;
    register intlist_t *next;

    for (cur = donelst; cur; cur = next) {
	next = cur->succ;
	xfree((char *) cur);
    }
}

/*
 * add_charplist - add a char * value to a list of char * values
 *
 * Returns the (possibly new) head of the list.
 */
charplist_t *
add_charplist(lp, val)
    charplist_t *lp;
    char *val;
{
    register charplist_t *nc;

    nc = (charplist_t *) xmalloc(sizeof(charplist_t)); /* create it */
    nc->text = val;			/* store it */
    nc->succ = lp;			/* link it in at the head */

    return nc;				/* return new list header */
}

/*
 * free_charplist - free up a whole list, and its values
 */
void
free_charplist(donelst)
    charplist_t *donelst;
{
    register charplist_t *cur;
    register charplist_t *next;

    for (cur = donelst; cur; cur = next) {
	next = cur->succ;
	xfree(cur->text);
	xfree((char *) cur);
    }
}


/*
 * add_voidplist - add a void * value to a list of void * values
 *
 * Returns the (possibly new) head of the list.
 */
voidplist_t *
add_voidplist(lp, storage, freefn)
    voidplist_t *lp;
    char *storage;
    void (*freefn) __P((void *));
{
    register voidplist_t *nc;

    nc = (voidplist_t *) xmalloc(sizeof(voidplist_t)); /* create it */
    nc->storage = storage;		/* store it */
    nc->freefn = freefn;		/* remember how to free storage */
    nc->succ = lp;			/* link it in at the head */

    return nc;				/* return new list header */
}

/*
 * free_voidplist - free up a whole list, and its values
 */
void
free_voidplist(donelst)
    voidplist_t *donelst;
{
    register voidplist_t *cur;
    register voidplist_t *next;

    for (cur = donelst; cur; cur = next) {
	next = cur->succ;
	(*(cur->freefn))(cur->storage);
	xfree((char *) cur);
    }
}

#ifndef NODEBUG

/*
 *	Some debuggging and diagnostic functions
 */

size_t
count_intlist(lp)
    register intlist_t *lp;
{
    register intlist_t *nc;
    register size_t i = 0;
    register size_t j = 0;

    for (nc = lp; nc; nc = nc->succ) {
	i++;
	if (nc->i_used != 0) {
	    j++;
	}
    }
    DEBUG2(DBG_MAIN_LO, "count_int_list(): found %lu entries, %lu valid numbers\n",
	   (unsigned long int) i,
	   (unsigned long int) j);

    return i;
}

void
print_intlist(lp)
    register intlist_t *lp;
{
    register intlist_t *nc;
    register size_t i = 0;
    int odebug = debug;

    debug = DBG_MAIN_LO;			/* force the issue */
    for (nc = lp; nc; nc = nc->succ) {
	i++;
	if (nc->i_used != 0) {
	    DEBUG2(DBG_MAIN_LO, "print_int_list(): lp entry # %lu =  %ld\n", (unsigned long int) i, nc->i_val);
	}
    }
    debug = odebug;

    return;
}

size_t
count_charplist(lp)
    register charplist_t *lp;
{
    register charplist_t *nc;
    register size_t i = 0;
    register size_t j = 0;

    for (nc = lp; nc; nc = nc->succ) {
	i++;
	if (nc->text) {
	    j++;
	}
    }
    DEBUG2(DBG_MAIN_LO, "count_charp_list(): found %lu entries, %lu valid strings\n",
	   (unsigned long int) i,
	   (unsigned long int) j);

    return i;
}

void
print_charplist(lp)
    register charplist_t *lp;
{
    register charplist_t *nc;
    register size_t i = 0;
    int odebug = debug;

    debug = DBG_MAIN_LO;			/* force the issue */
    for (nc = lp; nc; nc = nc->succ) {
	i++;
	if (nc->text) {
	    DEBUG2(DBG_MAIN_LO, "print_charp_list(): lp entry # %lu =  '%v'\n", (unsigned long int) i, nc->text);
	}
    }
    debug = odebug;

    return;
}

size_t
count_voidplist(lp)
    register voidplist_t *lp;
{
    register voidplist_t *nc;
    register size_t i = 0;
    register size_t j = 0;

    for (nc = lp; nc; nc = nc->succ) {
	i++;
	if (nc->storage) {
	    j++;
	}
    }
    DEBUG2(DBG_MAIN_LO, "count_voidp_list(): found %lu entries, %lu valid strings\n",
	   (unsigned long int) i,
	   (unsigned long int) j);

    return i;
}

void
print_voidplist(lp)
    register voidplist_t *lp;
{
    register voidplist_t *nc;
    register size_t i = 0;
    int odebug = debug;

    debug = DBG_MAIN_LO;			/* force the issue */
    for (nc = lp; nc; nc = nc->succ) {
	i++;
	if (nc->storage) {
	    DEBUG2(DBG_MAIN_LO, "print_voidp_list(): lp entry # %lu =  '%v'\n", (unsigned long int) i, nc->storage);
	}
    }
    debug = odebug;

    return;
}

#endif /* NODEBUG */

/* 
 * Local Variables:
 * c-file-style: "smail"
 * End:
 */


syntax highlighted by Code2HTML, v. 0.9.1