/***********************************************
 (C) Copyright 1992-1993; dit/upm
   Distributed under the conditions stated in the
   EPS General Public License (see file LICENSE)
 ***********************************************
 $Log: astmmg.c,v $
 * Revision 2.6  1993/09/20  14:16:40  eps
 * new functions: cut_rb cut_lb cutsons cutbrothers
 *
 * Revision 2.5  1993/01/12  16:33:44  eps
 * portability issues
 *
 * Revision 2.4  1992/11/17  11:46:35  eps
 * fix definition of *alloc for PC portability
 *
 * Revision 2.3  1992/01/14  15:42:24  eps
 * distribution issues
 *
 * Revision 2.2  92/01/07  11:30:27  eps
 * minor fix in cp_node: redundant code removed
 * 
 * Revision 2.1  90/10/30  08:30:47  eps
 * hardwired colours added
 * new colours I2, IAT, AT
 * ! is no longer used as colour delimiter
 * still some bugs are known w.r.t. colour deallocation
 * 
 * Revision 1.6  90/06/21  15:25:23  eps
 * calloc (N, s) => malloc (N * s)
 * allocate in incements of 256
 * 
 * Revision 1.5  90/03/16  15:37:15  eps
 * minor beautifying
 * 
 * Revision 1.4  90/02/19  19:06:10  eps
 * buck allocation of memory
 * 
 * Revision 1.3  90/02/12  10:51:33  eps
 * miscellaneous cleanup
 * SHAREABLE removed
 * 
 * Revision 1.2  90/01/29  14:51:04  eps
 * fixing license details
 * 
 * Revision 1.1  90/01/25  17:58:13  eps
 * Initial revision
 * 
 **********************************************/

#ifndef lint
static char rcsid[]= "$Id: astmmg.c,v 2.6 1993/09/20 14:16:40 eps Exp $";
#endif

/***********************************************************************
        Tomas P. de Miguel Moro
	Jose A. Manas
        dpt. Ingenieria Telematica
        E.T.S.I. Telecomunicacion
        Ciudad Universitaria
        E-28040  MADRID

        tmiguel@dit.upm.es
        jmanas@dit.upm.es
 **********************************************************************/

/* LINTLIBRARY */

# define cast_IMP
# include "cast.hh"

# include <stdio.h>

PRIVATE TNODE* freelist= NULL;
# define BUCKSIZE 256

PRIVATE void
kill_node(node)
	TNODE*	node;
{
  if (node != NULL) {	
    kill_node (node->sons);
    kill_node (node->brothers);
    free_node (node);
    }
} /* end of kill_node */

PUBLIC TNODE*
new_node (type)
     int type;
{
  TNODE* slot;
  TNODE* buck;
  int i;

  if (freelist == NULL) {
    buck= (TNODE*) malloc (BUCKSIZE * sizeof (TNODE));
    if (buck == NULL)
      fatal ("new_node: run out of memory");
    for (i= 0; i < BUCKSIZE; i++)
      buck[i].brothers= &buck[i+1];
    freelist= buck;
    buck[BUCKSIZE-1].brothers= NULL;
  }
  slot= freelist;
  freelist= freelist->brothers;
  slot->type = type;
  slot->father = NULL;
  slot->sons = NULL;
  slot->brothers = NULL;
  slot->attrs = NULL;
  slot->value0= NULL;
  slot->value1= NULL;
  return slot;
}

PUBLIC void
free_node (nd)
     TNODE* nd;
{
  freeattrs (nd);
  nd->brothers= freelist;
  freelist= nd;
}

PUBLIC TNODE*
cp_node (nodep, shared)
     TNODE* nodep;
     int shared;
{
  TNODE* newn;

  newn= new_node (nodep->type);
  if (shared)
    copyattrs (newn, nodep);
  return newn;
} /* end of cp_node */

PUBLIC TNODE*
cp_tree (nodep, shared)
     TNODE* nodep;
     int shared;
{
  TNODE *newt, *tson, *nson, *oson;

  if (nodep == NULL)
    return NULL;
  newt= cp_node (nodep, shared);
  oson= cp_tree (nodep->sons, shared); /* copy its sons */
  if (oson != NULL) {
    oson->father= newt;
    newt->sons= oson;
    for (tson= nodep->sons->brothers;
	 tson != NULL;
	 tson= gt_rb(tson)) {
      nson= cp_tree (tson, shared); /* copy its brothers */
      if (nson != NULL) {
	nson->father= newt;
	oson->brothers= nson;
	oson= nson;
      }
      else
	break;
    }
  }
  return newt;
} /* end of cp_tree */

PUBLIC void
cut_tree (nodep)
     TNODE* nodep;
{
  TNODE* auxp;

  if (nodep == NULL)
    return ;
  auxp= gt_lb (nodep);
  if (auxp != NULL)
    auxp->brothers= nodep->brothers;
  else
    if (nodep->father != NULL)
      nodep->father->sons= nodep->brothers;
  nodep->father= NULL ;
  nodep->brothers= NULL;
} /* end of cut_tree */

/* cuts off right brother and returns it */

PUBLIC TNODE*
cut_rb (nodep)
  TNODE* nodep;
{
  TNODE* auxp;

  if (nodep == NULL)
    return NULL;
  auxp= nodep->brothers;
  if (auxp == NULL)
    return NULL;
  nodep->brothers= auxp->brothers;
  auxp->father= NULL;
  auxp->brothers= NULL;
  return auxp;
}

/* cuts off left brother and returns it */

PUBLIC TNODE*
cut_lb (nodep)
  TNODE* nodep;
{
  TNODE* oldp;
  TNODE* auxp;

  if (nodep == NULL)
    return NULL;
  auxp = nodep->father;
  if (auxp == NULL)
    return NULL;
  oldp= NULL;
  for (auxp= auxp->sons;
       auxp->brothers != nodep;
       auxp= auxp->brothers)
    oldp= auxp;
  if (oldp != NULL)
    oldp->brothers= auxp->brothers;
  else
    nodep->sons= auxp->brothers;
  auxp->father= NULL ;
  auxp->brothers= NULL;
  return auxp;
}

/* cuts off sons and returns them */

PUBLIC TNODE*
cutsons (nodep)
  TNODE* nodep;
{
  TNODE* sons;
  TNODE* auxp;

  if (nodep == NULL)
    return NULL;
  sons= nodep->sons;
  if (sons == NULL)
    return NULL;
  nodep->sons= NULL;
  for (auxp= sons;
       auxp != NULL;
       auxp= auxp->brothers)
    auxp->father= NULL;
  return sons;
}

/* cuts off brothers and returns them */

PUBLIC TNODE*
cutbrothers (nodep)
  TNODE* nodep;
{
  TNODE* brothers;
  TNODE* auxp;

  if (nodep == NULL)
    return NULL;
  brothers= nodep->brothers;
  if (brothers == NULL)
    return NULL;
  nodep->brothers= NULL;
  for (auxp= brothers;
       auxp != NULL;
       auxp= auxp->brothers)
    auxp->father= NULL;
  return brothers;
}

/* adds a new brother to the right */


PUBLIC void
kill_tree (tree)
     TNODE* tree;
{
  cut_tree (tree);
  kill_node (tree);
} /* end of kill_tree */

