/********************************************************************************************************
 * QRNA - Comparative analysis of biological sequences 
 *         with pair hidden Markov models, pair stochastic context-free
 *        grammars, and probabilistic evolutionary  models.
 *       
 * Version 2.0.0 (JUN 2003)
 *
 * Copyright (C) 2000-2003 Howard Hughes Medical Institute/Washington University School of Medicine
 * All Rights Reserved
 * 
 *     This source code is distributed under the terms of the
 *     GNU General Public License. See the files COPYING and LICENSE
 *     for details.
 ***********************************************************************************************************/


/* (modified)
 * trace.c  -  support for traceback of regular grammar structure 
 */


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

#include "funcs.h"
#include "globals.h"
#include "squid.h"
#include "structs.h"

#ifdef MEMDEBUG
#include "dbmalloc.h"
#endif

/* Function: InitTracer()
 * 
 * Purpose:  Initialize a traceback tree structure.
 *
 * Return:   ptr to the new tree.
 */          
struct tracer_s *
InitTracer(void)
{
  struct tracer_s *new;

  if ((new = (struct tracer_s *) malloc (sizeof(struct tracer_s))) == NULL)
    Die("Memory allocation failure at %s line %d", __FILE__, __LINE__);
  
  new->emit = -1;
  new->type = -1;
  new->nxt  = NULL;
  new->prv  = NULL;
  return new;
}

/* Function : InitTracerstack()
 *            
 * Purpose:   Implementation of the pushdown stack for
 *            traversing traceback trees.
 */            
struct tracerstack_s *
InitTracerstack(void)
{
  struct tracerstack_s *stack;

  if ((stack = (struct tracerstack_s *) malloc (sizeof(struct tracerstack_s))) == NULL)
    Die("Memory allocation failure at %s line %d", __FILE__, __LINE__);
  stack->nxt = NULL;
  return stack;
}

/* Function: AttachTracer()
 * 
 * Purpose:  attach a new node to a tracetree node.
 *           There are no dummy END nodes, in contrast to COVE.
 *           
 *           Because of the mechanics of tracebacks through a Viterbi matrix,
 *           we have to make sure that BIFURC children are attached
 *           right first, left second.
 *           
 * Returns:  ptr to the new node, or NULL on failure.
 */          
struct tracer_s *
AttachTracer(struct tracer_s *parent,
	        int           emit,
                int           type)
{
  struct tracer_s *new;

  if (parent->nxt != NULL)
    Die("That trace node is already full, fool.");

 if ((new = (struct tracer_s *) malloc (sizeof(struct tracer_s))) == NULL)
  Die("Memory allocation failure at %s line %d", __FILE__, __LINE__);

  new->nxt    = NULL;
  new->prv    = parent;
  new->emit   = emit;
  new->type   = type;
  parent->nxt = new;

  return new;
}

void
FreeTracer(struct tracer_s *tr)
{
  struct tracerstack_s *stack;
  struct tracer_s      *currtr;

  stack = InitTracerstack();
  PushTracerstack(stack, tr);

  while ((currtr = PopTracerstack(stack)) != NULL)
    {
      if (currtr->nxt != NULL)
	PushTracerstack(stack, currtr->nxt);
      free(currtr);
    }
  FreeTracerstack(stack);
}

void
DeleteTracernode(struct tracer_s *oldtr)
{
  struct tracer_s *parent;

  parent = oldtr->prv;

  parent->nxt = oldtr->nxt;
  oldtr->nxt->prv = parent;
  free(oldtr);
}

void 
PushTracerstack(struct tracerstack_s *stack, struct tracer_s *tracernode)
{
  struct tracerstack_s *new;

 if ((new = (struct tracerstack_s *) malloc (sizeof(struct tracerstack_s))) == NULL)
    Die("Memory allocation failure at %s line %d", __FILE__, __LINE__);
  new->node = tracernode;
 
  new->nxt = stack->nxt;
  stack->nxt = new;
}

struct tracer_s *
PopTracerstack(struct tracerstack_s *stack)
{
  struct tracer_s *node;
  struct tracerstack_s *old;

  if (stack->nxt == NULL)
    return NULL;

  old = stack->nxt;
  stack->nxt = old->nxt;

  node = old->node;
  free(old);
  return node;
}

void
FreeTracerstack(struct tracerstack_s *stack)
{
  while (PopTracerstack(stack) != NULL);
  free(stack);
}


















