#include<stdio.h> 
 
/* 




                 VV                   VV    EEEEEEEEEEEEEE   
                  VV                 VV     EE  
                   VV               VV      EE
                    VV             VV       EE
                     VV           VV        EE
                      VV         VV         EEEEEEEEEEEEEE
                       VV       VV          EE
                        VV     VV           EE
                         VV   VV            EE
                          VV VV             EE
                           VVV              EE
                            V               EEEEEEEEEEEEEE
                                                       
 
 
 
 
                       MODULE  : lnklst.c
 
                       VERSION : v3.2
 
                       REVISED : 02 Jun 2005
 
                       AUTHOR  : Michael A. Campbell
 
 
 
 
 
 


                          FUNCTIONAL DESCRIPTION
                          ----------------------
 
               This module contains the linked list handlers for VE.
 
               Basic handlers are provided to allow the addition and     
 
               deletion of lines, and linked list traversals.
 











*/

/* .page */

/*****************
 * INCLUDE FILES *
 *****************/

#include "../def/common.def"


#include "../str/vestruct.str"

/* .page */

/**********************
 * PUBLIC PROCEDURES  *
 **********************/

void init_list ( list_d )

/****************************************************************************
 * This function initializes the supplied link list descriptor.             *
 ****************************************************************************/

struct file_ctl *list_d;

begin

   list_d->fwd_link = NULL;
   list_d->bwd_link = NULL;

   list_d->head     = NULL;
   list_d->tail     = NULL;

   list_d->nodes    = 0;
   list_d->bytes    = 0;
   list_d->length   = 0;

end /* init_list */

/* .page */

void purge_list ( list_d )

/****************************************************************************
 * This function releases all of the memeory associated with a given list   *
 * and the re-initializes it.                                               *
 ****************************************************************************/

struct file_ctl *list_d;

begin
    struct node *cnode, *nnode;

    cnode = list_d->head;

    while (cnode != EOL) begin

        nnode = cnode->fwd_link;
        free (cnode);

        cnode = nnode;
    end

    init_list ( list_d );

end /* purge_list */

/* .page */

void add (list_d, pnode, cnode, status)

/****************************************************************************
 *                                                                          *
 *   Add the node pointed to by cnode after the node pointed to by pnode.   *
 *                                                                          *
 ****************************************************************************/

struct file_ctl *list_d;        /* Linked List descriptor                   */
struct node     *pnode, *cnode; /* Pointer to the previous and current nodes*/
int             *status;

begin

    struct node   *nnode;        /* Pointer to the next node after pnode    */

    cnode->fwd_link = pnode->fwd_link;
    cnode->bwd_link = pnode;

    pnode->fwd_link = cnode;

    if (cnode->fwd_link != EOL) begin
        nnode = cnode->fwd_link;
        nnode->bwd_link = cnode;
    end

    if (list_d->nodes == 0) begin
        list_d->head = cnode;
        list_d->tail = cnode;
    end

    if (cnode->bwd_link == (struct node *) list_d) then
        list_d->head = cnode;

    if (cnode->fwd_link == EOL) then
        list_d->tail = cnode;

    list_d->nodes += 1;

    *status = E_OK;
    
end /* add */

/* .page */

struct node *delete (list_d, cnode, status)

/****************************************************************************
 *                                                                          *
 *   Delete the node pointed to by cnode.                                   *
 *                                                                          *
 ****************************************************************************/

struct file_ctl  *list_d;
struct node      *cnode;        /* Pointer to the node to be deleted        */
int              *status;       /* Status variable                          */

begin

    struct node *pnode, *nnode; /* Pointers to the previous and next nodes  */

    if (list_d->nodes == 0) begin
        *status = E_LIST_ERROR;
        return (cnode);
    end

    pnode = cnode->bwd_link;
    nnode = cnode->fwd_link;

    pnode->fwd_link = cnode->fwd_link;

    if (nnode != EOL) then
        nnode->bwd_link = pnode;

    if (pnode->fwd_link == EOL) then
        list_d->tail = pnode;

    if (nnode != EOL ) then
        if (nnode->bwd_link == (struct node *) list_d) then
            list_d->head = nnode;

    list_d->nodes -= 1;

    return (cnode);

end /* delete */

/* .page */

struct node *traverse_list (list_d, cnode, dir, actual, count, status)

/*****************************************************************************
 *                                                                           *
 *  Starting at cnode, move either forward or backward along the linked list *
 *  for as many nodes as specified by count, or until the end of the list or *
 *  the head of the list is encountered.  Return the number of nodes moved   *
 *  over in "actual", and the pointer to the node moved to as the return val *
 *                                                                           *
 *****************************************************************************/

struct file_ctl *list_d;      /* Linked list to be worked with               */
struct node     *cnode;       /* Starting node of the move                   */
int             dir;          /* "+" = forward, "-" = backward               */
int             *actual;      /* Returned: nodes moved over                  */
int             count;        /* Number of nodes to move over, if possible   */
int             *status;      /* Status variable                             */

begin

    struct node  *pnode;     /* Pointer to previous node                    */

    for (*actual = 0; *actual < count; (*actual)++) begin
        pnode = cnode;

        if (dir == '+') then
            cnode = cnode->fwd_link;
        else
            cnode = cnode->bwd_link;

        if (cnode == EOL || cnode == (struct node *) list_d) begin
            *status = E_EOL;
            return (pnode);
        end
    end

    return (cnode);

end /* traverse_list */

/* .page */

void send_node (list_d, cnode)

/****************************************************************************
 *                                                                          *
 *   Send the node pointed to by cnode to the tail of the list whose        *
 *   descriptor is list_d.                                                  *
 *                                                                          *
 ****************************************************************************/

struct file_ctl *list_d;
struct node     *cnode;

begin

    int status;

    if (list_d->nodes == 0) then
        add (list_d, (struct node *) list_d, cnode, &status);

    else
        add (list_d, list_d->tail, cnode, &status);


end /* send_node */

/* .page */

struct node *receive_node (list_d, status)

/****************************************************************************
 *                                                                          *
 *   Receive a node from the head of the list whose descriptor is list_d.   *
 *                                                                          *
 ****************************************************************************/

struct file_ctl *list_d;
int             *status;

begin

    return (delete(list_d, list_d->head, status));

end /* receive_node */

