/*
    mmorph, MULTEXT morphology tool
    Version 2.3, October 1995
    Copyright (c) 1994,1995 ISSCO/SUISSETRA, Geneva, Switzerland
    Dominique Petitpierre, <petitp@divsun.unige.ch>
*/
/*
    bitmap.c

    handle circular list (chains)
    used to preserve order of insertion.

    Dominique Petitpierre, ISSCO Summer 1994

*/

#include "config.h"
#include "chain.h"
#include "mymalloc.h"

s_chain    *
insert_chain_link(chain, item)
s_chain    *chain;
char       *item;

{
    s_chain    *new_chain_link;

    MY_MALLOC(new_chain_link, s_chain);
    new_chain_link->item = item;
    if (chain) {
	new_chain_link->next = chain->next;	/* keep track of first link */
	chain->next = new_chain_link;	/* append link */
    }
    else {
	new_chain_link->next = new_chain_link;	/* first link is last link */
    }
    return (new_chain_link);	/* last link */
}

s_chain    *
reverse_chain(chain)
s_chain    *chain;

{
    s_chain    *previous_chain_link;
    s_chain    *next_current;
    s_chain    *current_chain_link;
    s_chain    *start_chain;

    if (chain) {
	previous_chain_link = chain;
	start_chain = chain->next;
	current_chain_link = start_chain;
	do {
	    next_current = current_chain_link->next;
	    current_chain_link->next = previous_chain_link;
	    previous_chain_link = current_chain_link;
	    current_chain_link = next_current;
	} while (current_chain_link != start_chain);
	return (current_chain_link);	/* new last link */
    }
    else
	return (chain);
}

void
map_chain(chain, action)
s_chain    *chain;
void        (*action) ();

{
    s_chain    *start_chain;
    s_chain    *current_chain_link;

    if (chain) {
	start_chain = chain->next;
	current_chain_link = start_chain;
	do {
	    action(current_chain_link->item);
	    current_chain_link = current_chain_link->next;
	} while (current_chain_link != start_chain);
    }
}

void
free_chain(chain)
s_chain    *chain;

{
    s_chain    *current_chain_link;
    s_chain    *next;

    if (chain) {
	current_chain_link = chain;
	do {
	    next = current_chain_link->next;
	    MY_FREE(current_chain_link);
	    current_chain_link = next;
	} while (current_chain_link != chain);
    }
}
