//Copyright, 2002-2003, Astra Network Inc.  All Rights Reserved

//This source code has been published by Astra Network Inc. However, any
//use, reproduction, modification, distribution or transfer of this
//software, or any software which includes or is based upon any of this
//code, is only permitted if expressly authorized by a written license
//agreement from Astra. Contact your Astra representative directly for
//more information.

/*!
 * \file HC_Sequence.c
 * Collection of functions relating to sequences.
 */

#include <stdio.h>
#include <string.h>
#include <malloc.h>

#include "checkpoint_int.h"

/*!
 * Execution of a sequence starts here. The sequence starts by running
 * the Normal function for the start_node given.
 *
 * \param sequence The sequence object, created by HC_NewSequence().
 * \param userdata User defined data. It is passed to all user functions.
 * \param start_node The first executed node.
 * \return An error code (or HC_OK)
 */
int
HC_CallSequence (HC_Sequence_t *sequence, void *userdata, long start_node)
{
  int rc;

  if (sequence)
    {
      sequence->curr_node = start_node;
      sequence->userdata = userdata;
      sequence->curr_event = HC_INVALID_EVENT;

      rc = HC_Normal (sequence, sequence->curr_node, userdata);
      if (rc != HC_OK )
	{
	  (void) HC_Log (sequence, "Initial Normal returned failure, %s",
			 HC_Strerror (rc));
	  return (HC_FAIL);
	}

      while (sequence->curr_node > 0)
	{
	  rc = HCI_CallPolicy (sequence, sequence->curr_node,
			       userdata, sequence->curr_event,
			       sequence->curr_policy_data);
	  if (rc != HC_OK)
	    {
	      (void) HC_Log (sequence, "Policy returned failure, %s",
			     HC_Strerror (rc));
	    }
	}
      return (sequence->curr_node);
    }
  return (HC_INVALIDSEQUENCE);
}

/*!
 * Creates a sequence object from nodelist.
 *
 * \param nodelist A table of nodes and functions to be executed by 
 *    the sequence.
 * \return A sequence object containing the nodelist data given.
 */
HC_Sequence_t *HC_NewSequence (HC_NodelistNode_t *nodelist)
{
  HC_Sequence_t *new_seq;
  long myindex;

  if (nodelist == NULL)
    return NULL;

  new_seq = malloc (sizeof (HC_Sequence_t));
  if (!new_seq)
    return (NULL);

  memset (new_seq, 0, sizeof (HC_Sequence_t));	// Zero everything

  new_seq->node_list = nodelist;

  myindex = 0;
  while (nodelist[myindex].type_tag != HC_LISTEND)
    myindex++;

  new_seq->num_nodes = myindex;

  return (new_seq);
}

/*!
 * Deletes a sequence, cleanups up any memory, etc.
 * The sequence pointer is invalid after this call.
 *
 * \param sequence A sequence object
 */
void HC_DeleteSequence (HC_Sequence_t *sequence)
{
  if (sequence != NULL )
    {
      free (sequence);
    }
}
