/******************************************************************
 *  (C) Copyright 1994; dit/upm
 *  Distributed under the conditions stated in the
 *  TOPO General Public License (see file LICENSE)
 ******************************************************************
 *  $Log$
 ******************************************************************/

#ifndef lint
static char rcsid[]= "$Id$";
#endif

/******************************************************************
 *
 *  David Larrabeiti Lopez
 *
 *  19 Mar 1990 ( San Josep )
 *
 *  Management of gates relabelling
 *
 *  RFs composing a RFL are supposed to have different Formal Gates.
 *  The opposite would be meaningless.
 *  ( Besides, this enables the Formal Gate to be the
 *    search key to locate RFs in a list ).
 *
 *  COMPILATION FLAGS:
 *
 *  LOG:
 *     14/07/94. dlarra.
 *     When a relabel operation was printed some list nodes
 *     were lost.
 *
 *     04/02/94. dlarra.
 *     The initialization of new gate prefixes is now automatic.
 *
 ******************************************************************/

/* LINTLIBRARY */

/* KJT 12/02/12: Added */
#include <stdlib.h>
#include "listdh.h"
#include "limisc.h"
#include "listrbk.h"
#include "baattr.h"
#include "batables.h"


/*
 *  count of relab func struct used.
 */
static int new_rf_count      = 0;
static int released_rf_count = 0;
static int max_rf_count      = 0;

/*----------------------------------------------------------------*/

static boolean there_is_newgate_prefix = FALSE;

/* InitRF
 * Init the RF module
 */
void InitRF()
{
  there_is_newgate_prefix = FALSE;
#ifdef SDEBUG
  new_rf_count      = 0;
  released_rf_count = 0;
  max_rf_count      = 0;
#endif
}

/*----------------------------------------------------------------*/

/* StatRF
 * new      : number of cell queries the system has granted this module with.
 * released : number of cell releases.
 * max      : max number of cells hold on by this module till now.
 */
void StatRF( new, released, max )
     int *new, *released, *max;
{
  *new      = new_rf_count;
  *released = released_rf_count;
  *max      = max_rf_count;
}

/*----------------------------------------------------------------*/

/* NewRF
 * Get memory for a new RelabFunc struct.
 */
PRelabFuncTyp NewRF()
{
  PRelabFuncTyp p;

  p          = (PRelabFuncTyp) NewCellM(sizeof(RelabFuncTyp));
  p->gateAct = 0;
  p->gateFor = 0;
  p->next    = NULL;
#ifdef SDEBUG
  new_rf_count++;
  max_rf_count=MAX( max_rf_count, new_rf_count-released_rf_count );
#endif
  return p;
}

/*----------------------------------------------------------------*/

/* FreeRF
 * Free memory used by an RF.
 */
void FreeRF( rf )
     PRelabFuncTyp rf;
{
#ifdef SDEBUG
  released_rf_count++;
#endif
  FreeCellM( (void*)rf, sizeof(RelabFuncTyp) );
}

/*----------------------------------------------------------------*/

/* CopyRF
 * Copy the RF rf.
 */
PRelabFuncTyp CopyRF( rf )
     PRelabFuncTyp rf;
{
  return MakeRF( rf->gateAct, rf->gateFor );
}

/*----------------------------------------------------------------*/

static StrBckTyp strBck;

/* SPrintRelabFunc
 * Make a string with the relabel function rf.
 */
static void SPrintRelabFunc( rf )
     PRelabFuncTyp rf;
{
  char    * str;

  str    = SPrintG(rf->gateAct);
  strBck = ConcatStrBck( strBck, str );
  free( str );
  strBck = ConcatStrBck( strBck, "/" );
  str    = SPrintG(rf->gateFor);
  strBck = ConcatStrBck( strBck, str );
  free( str );
}


/* MakeRF
 * Create the relab function [ga/gf]
 */
PRelabFuncTyp MakeRF( ga, gf )
     DescriptorTyp ga, gf;
{
  PRelabFuncTyp nrf;

  nrf          = NewRF();
  nrf->gateAct = ga;
  nrf->gateFor = gf;
  return nrf;
}

/*----------------------------------------------------------------*/

/* FreeRFL
 * Free the memory used by the RelabFuncList rfl.
 */
void FreeRFL( rfl )
     RelabFuncListTyp rfl;
{
  if ( rfl!=NULL ){
    FreeRFL(rfl->next);
    FreeRF(rfl);
  }
}

/*----------------------------------------------------------------*/

/* LengthRFL
 * Return the length of the relab func list rfl.
 */
int LengthRFL( rfl )
     RelabFuncListTyp  rfl;
{
  int i;

  for ( i=0; rfl!=NULL; i++ )
    rfl = rfl->next;
  return i;
}

/*----------------------------------------------------------------*/

/* CopyRFL
 * Copy the RelabFuncList rfl.
 */
RelabFuncListTyp CopyRFL( rfl )
     RelabFuncListTyp rfl;
{
  RelabFuncListTyp nrfl;

  nrfl = CreateRFL();
  for (  ; rfl!=NULL ; rfl=rfl->next )
    nrfl = AddRF( CopyRF(rfl) , nrfl );
  return nrfl;
}

/*----------------------------------------------------------------*/

/* JoinRFL
 * Join the relab func list rfl1 and rfl2. Returns rfl1,rfl2.
 */
RelabFuncListTyp JoinRFL( rfl1, rfl2 )
     RelabFuncListTyp rfl1,rfl2;
{
  RelabFuncListTyp aux;

  if ( rfl1 != NULL ) {
    for (aux = rfl1 ; aux->next!=NULL ; aux=aux->next )
      ;
    aux->next = rfl2;
    return rfl1;
  }
  else
    return rfl2;
}


/******************************************************************
 *                                                                *
 *              JunctionRFL                                       *
 *                                                                *
 ******************************************************************/

/* Accessible copy of parameters rfl1 and rfl2 of JunctionRFL.
 * It is updated every time JunctionRFL is called.
 */
static RelabFuncListTyp RFL1,RFL2;


/* Step1
 * if (rfPt2->gateAct in fgl1) rfPt2->gateAct:=ActualRFL(g)
 */
static void Step1( rfPt2 )
     PRelabFuncTyp rfPt2;
{
  DescriptorTyp g;

  if ( (g=ActualRFL(RFL1,rfPt2->gateAct)) !=0 )
    rfPt2->gateAct = g;
}


/* Step2
 * g in fgl1 : if (g not in fgl2) Add x/g to rfl2
 */
static void Step2( rfPt1 )
     PRelabFuncTyp rfPt1;
{
  if ( ActualRFL( RFL2, rfPt1->gateFor ) == 0 )
    RFL2 = JoinRFL(RFL2,MakeRF(rfPt1->gateAct,rfPt1->gateFor));
}


/* CleanVoidRFs
 *
 */
static void CleanVoidRFs()
{
  RelabFuncListTyp suspect,victim;

  suspect = RFL2;
  while (suspect!=NULL){
    if (((PRelabFuncTyp)suspect)->gateAct==((PRelabFuncTyp)suspect)->gateFor)
      {
	victim  = suspect;
	suspect = suspect->next;
	RFL2    = DeleteNodeRFL( victim, RFL2 );
      }
    else
      suspect = suspect->next;
  }
}


/* JunctionRFL
 * Return the junction of relabel function lists : rfl1 ( rfl2() ).
 * rfl1 is applied upon rfl2. ( It is non-conmutative ):
 *
 *   rfl1     Example: [ b/a, x/b, x/c ]   ==    [ y/a, x/c ]
 *    |                        |                       |
 *   rfl2                [ a/b, y/a ]                  B
 *    |                        |
 * Behaviour                   B
 *
 * rfl1 and rfl2 are destroyed in order to create the junction.
 * Parameters must be copied,
 */
RelabFuncListTyp JunctionRFL( rfl1, rfl2 )
     RelabFuncListTyp rfl1,rfl2;
{
  RelabFuncListTyp aux;

  RFL1 = rfl1;
  RFL2 = rfl2;

  /*
   *  Let's say:
   *  rfl1 = agl1/fgl1;
   *  rfl2 = agl2/fgl2;
   *
   *  For all g in agl2 : if (g in fgl1) g:=ActualRF(g);
   */
  for (aux=rfl2 ; aux!=NULL ; aux = aux->next )
    Step1(aux);

  /*
   *  For all g in fgl1 : if (g not in fgl2) Add x/g to rfl2;
   */
  for (aux=rfl1 ; aux!=NULL ; aux = aux->next )
    Step2(aux);

  /*
   * Get rid of y/y rf's in rfl2
   */
  CleanVoidRFs();
  FreeRFL( RFL1 );
  aux = RFL2;
  RFL1 = CreateRFL();
  RFL2 = CreateRFL();
  return aux;
}

/*-----------------------------------------------------------------*/

/* SPrintRFL
 * Make a string with the Relab Function list rfl.
 * in the format ga1/gf1, ga2/gf2,...,gan/gfm where gai,gfj are gate names.
 */
char * SPrintRFL( rfl )
     RelabFuncListTyp rfl;
{
  char * str;

  strBck = CreateStrBck();
  strBck = ConcatStrBck( strBck, " " );
  while ( rfl!=NULL ) {
    SPrintRelabFunc(rfl);
    rfl=rfl->next;
    if (rfl!=NULL)
      strBck = ConcatStrBck( strBck, ", " );
  }
  strBck = ConcatStrBck( strBck, " " );
  str    = GetStrStrBck( strBck );
  FreeStrBck( strBck );
  return str;
}

/*-----------------------------------------------------------------*/

/* PrintRFL
 * Print the relab function List rfl,
 * in the format  ga1/gf1, ga2/gf2,...,gan/gfm  where gai gaj are gate names.
 * pstr is the function used to print strings.
 */
void PrintRFL( rfl, pstr )
     RelabFuncListTyp rfl;
     void             (*pstr)();
{
  char * str;

  str = SPrintRFL( rfl );
  pstr(str);
  (void)free(str);
}

/*----------------------------------------------------------------*/

/* AddRF
 * Add the relab func rf to the relab func list rfl.
 */
RelabFuncListTyp AddRF( rf, rfl )
     PRelabFuncTyp    rf;
     RelabFuncListTyp rfl;
{
  return JoinRFL( rfl, rf );
}

/*----------------------------------------------------------------*/

/* AddRFL
 * Add [ga/gf] to the RelabFuncList rfl.
 * If it already exists : no append.
 * Conditions: gf can not belong to Range(rfl) or else execution will be halted
 */
RelabFuncListTyp AddRFL( rfl, ga, gf )
     RelabFuncListTyp rfl;
     DescriptorTyp    ga,gf;
{
  DescriptorTyp    g;
  RelabFuncListTyp aux;

  if (ga==gf)
    return rfl;
  if (rfl==NULL)
    return MakeRF(ga,gf);
  g = ActualRFL(rfl,gf);
  if ( g==ga )               /* ga/gf already exists */
    return rfl;
  else {
    if (g!=(DescriptorTyp)NULL)            /* There is x/gf */
      Error("AddRFL:Attempt to add a RelabFunction ga/gf when [x/gf] exists");
    for ( aux = rfl; aux->next!=NULL; aux = aux->next )
      ;
    aux->next = MakeRF(ga,gf);
    return rfl;
  }
}

/*----------------------------------------------------------------*/

/* ActualRFL
 * Return the actual gate associated to the formal gate gf
 * If it doesn't exist : return 0
 */
DescriptorTyp ActualRFL( rfl, gf )
     RelabFuncListTyp rfl;
     DescriptorTyp    gf;
{
  for ( ; rfl!=NULL ; rfl=rfl->next )
    if (gf==rfl->gateFor)
      return rfl->gateAct;
  return 0;
}

/*----------------------------------------------------------------*/

/* FormalRFL
 * Return the n-th Formal gate associated to the actual gate ga
 * If it doesn't exist : return 0
 */
DescriptorTyp FormalRFL( rfl, ga, n )
     RelabFuncListTyp rfl;
     DescriptorTyp    ga;
     int              n;
{
  LASSERT(rfl!=NULL);

  for ( ; (rfl!=NULL) ; rfl=rfl->next )
    if (ga==rfl->gateAct)
      if (n>1)
	n--;
      else
	return rfl->gateFor;
  return 0;
}

/*----------------------------------------------------------------*/

/* LookForGateRF
 * Return the formal gate in the current rfl node.
 */
DescriptorTyp LookForGateRF( rfl )
     RelabFuncListTyp rfl;
{
  return rfl->gateFor;
}

/*----------------------------------------------------------------*/

/* LookActGateRF
 * Return the Actual gate in the current rfl node.
 */
DescriptorTyp LookActGateRF( rfl )
     RelabFuncListTyp rfl;
{
  return rfl->gateAct;
}

/*----------------------------------------------------------------*/

/* RangeRFL
 * Return Range(rfl) = Formal gate set
 */
GateSetTyp RangeRFL( rfl )
     RelabFuncListTyp rfl;
{
  GateSetTyp gs;

  gs = NewGS();
  for ( ; rfl!=NULL ; rfl=rfl->next )
    gs = AddGS( gs, rfl->gateFor );
  return gs;
}

/*----------------------------------------------------------------*/

/* ImageRFL
 * Return Image(rfl) = Actual gates set
 */
GateSetTyp ImageRFL( rfl )
     RelabFuncListTyp rfl;
{
  GateSetTyp gs;

  gs = NewGS();
  for ( ; rfl!=NULL ; rfl=rfl->next )
    gs = AddGS( gs, rfl->gateAct );
  return gs;
}

/*----------------------------------------------------------------*/

/* InvRFL
 * Return the inverse gate relabel function list of rfl.
 * rfl is modified by exchanging ga and gf.
 * Therefore the new relabel function may not be an application.
 */
RelabFuncListTyp InvRFL( rfl )
     RelabFuncListTyp rfl;
{
  RelabFuncListTyp aux;
  DescriptorTyp i;

  for (aux=rfl ; aux!=NULL ; aux=aux->next ) {
    i = aux->gateFor;
    aux->gateFor= aux->gateAct;
    aux->gateAct= i;
  }
  return rfl;
}


/******************************************************************
 *                                                                *
 *                   ApplyRFL and InvApplyRFL                     *
 *                                                                *
 ******************************************************************/

static GateSetTyp sGS;
static RelabFuncListTyp sRFL;


/* If there is x/e : add gate x to GS
 * else: add gate e to the Gate set GS
 */
static void RelabGateTowardsGS( e )
     DescriptorTyp e;
{
  DescriptorTyp g;

  if ( (g=ActualRFL( sRFL, e)) ==0 )
    sGS = AddGS( sGS, e );
  else
    sGS = AddGS( sGS, g );
}


/* ApplyRFL
 * Return the gate set output from applying the relabel function
 * defined by rfl to the input gate set gs.
 */
GateSetTyp ApplyRFL( rfl, gs )
     RelabFuncListTyp rfl;
     GateSetTyp        gs;
{
  GateListTyp  gl;

  gl   = GateSet_to_GateList(gs);
  sGS  = NewGS();
  sRFL = rfl;
  Apply_Proc_list ( gl, RelabGateTowardsGS );
  FreeGL(gl);
  return sGS;
}


static DescriptorTyp Actual( g )
     DescriptorTyp g;
{
  DescriptorTyp rfg;

  rfg = ActualRFL( sRFL, g );
  return rfg==(DescriptorTyp)NULL? g : rfg;
}

/* ApplyGL_RFL
 * Return the gate list output from applying the relabel function
 * defined by rfl to the input gate list gl.
 */
GateListTyp ApplyGL_RFL( rfl, gl )
     RelabFuncListTyp rfl;
     GateListTyp       gl;
{
  sRFL = rfl;
  Apply_Func_list ( gl, (DataListTyp(*)())Actual );
  return gl;
}


/* If there is a element "e/x" in sRFL then this function adds the
 * gate "x" to sGS ,else it adds the gate "e" to sGS.
 * If there is no a formal gate that generate "e", then "e" is included
 * in sGS.
 */
static void InvRelabGateTowardsGS( e )
     DescriptorTyp e;
{
  DescriptorTyp g;
  int n;

  for ( n=1 ; (g=FormalRFL( sRFL, e, n)) != 0 ; n++ ) {
    sGS = AddGS( sGS, g );
  }
  if (ActualRFL(sRFL,e)==0)
    sGS = AddGS( sGS, e );

  /*
     if ( (g=FormalRFL( sRFL, e, 1)) ==0 )
     sGS = AddGS( sGS, e );
     else {
     for ( n=2; g!=0; n++ ){
     sGS = AddGS( sGS, g );
     g = FormalRFL( sRFL, e, n );
     }
     if (ActualRFL(sRFL,e)==0)
     sGS = AddGS( sGS, e );
     }
     */
}


/* InvApplyRFL
 * Return the gate set output from applying reversely the relabel function
 * defined by rfl to the input gate set gs.
 */
GateSetTyp InvApplyRFL( rfl, gs )
     RelabFuncListTyp rfl;
     GateSetTyp        gs;
{
  GateListTyp  gl;

  gl   = GateSet_to_GateList(gs);
  sGS  = NewGS();
  sRFL = rfl;
  Apply_Proc_list ( gl, InvRelabGateTowardsGS );
  FreeGL( gl );
  return sGS;
}

/*----------------------------------------------------------------*/

/* Mk_GLs_RFL
 * Make a new relabel function list by combining
 * an actual gate list ,gla, and a formal one ,glf.
 * The gate list lengths must be equal.
 * The RFL is NOT a literal transcription of [ga1/gf1,ga2/gf2,...] :
 * The RFs are added through the AddRFL command which filters
 * duplicated RFs off and verifies inequality of formal gates.
 */
RelabFuncListTyp Mk_GLs_RFL( gla, glf)
     GateListTyp gla,glf;
{
  RelabFuncListTyp rfl;

  rfl = CreateRFL();
  while (( gla != NULL) && ( glf != NULL ))
    { rfl = AddRFL( rfl, (DescriptorTyp)(gla->info),
		   (DescriptorTyp)(glf->info) );
      gla = Next_list( gla );
      glf = Next_list( glf );
    }
  LASSERT( gla==NULL && glf==NULL );
  return rfl;
}

/*----------------------------------------------------------------*/

/* EqualRFL
 * Return TRUE if rfl1 and rfl2 are equal (in the same order).
 */
boolean EqualRFL( rfl1, rfl2 )
     RelabFuncListTyp rfl1,rfl2;
{
  while (rfl1!=NULL && rfl2!=NULL) {
    if ( (rfl1->gateAct!=rfl2->gateAct) || (rfl1->gateFor!=rfl2->gateFor) )
      return FALSE;
    rfl1 = Next_list(rfl1);
    rfl2 = Next_list(rfl2);
  }
  return (rfl1==rfl2);
}

/*----------------------------------------------------------------*/

/* DeleteNodeRFL
 * Delete the current node n of rfl.
 * Returns the new rfl.
 * Conditions:
 *   n must belong to rfl.
 *   n !=NULL. l !=NULL.
 */
RelabFuncListTyp DeleteNodeRFL( n, l )
     PRelabFuncTyp    n;
     RelabFuncListTyp l;

{
  RelabFuncListTyp pNode;

  LASSERT ((n!=NULL)&&(l!=NULL));
  /* alternative: if ((n==NULL)||(l==NULL)) return l; */
  if ( l==n )
    l = l->next;
  else {
    for ( pNode=l ;(pNode->next!=n) && (pNode!=NULL); pNode=pNode->next )
      ;
    if (pNode!=NULL)
      pNode->next = n->next;
    else
      Error("DeleteNodeRFL: Node to be deleted doesn't belong to the rlist.");
  }
  FreeRF(n);
  return l;
}

/*----------------------------------------------------------------*/

/* RemoveWhenRFL
 * Delete the rfl nodes which hold the boolean condition "when".
 * Return the new rfl.
 */
RelabFuncListTyp RemoveWhenRFL( rfl, when )
     RelabFuncListTyp rfl;
     boolean          (*when)();
{
  RelabFuncListTyp pNode,next;

  pNode=rfl;
  while ( pNode!=NULL ) {
    next=pNode->next;
    if ( when(pNode) )
      rfl=DeleteNodeRFL(pNode,rfl);
    pNode=next;
  }
  return rfl;
}


/******************************************************************
 *                                                                *
 *       Printing of Relabelling as a generalized gatechoice      *
 *                                                                *
 ******************************************************************/


/* ExistPrefixG
 * Say if there is a gate in the table of gates whose prefix is namePrefix.
 */
static boolean ExistPrefixG( namePrefix )
     char  *namePrefix;
{
  DescriptorTyp i,gTab_last;

  gTab_last=LastTableG();
  for (i=1 ; i<=gTab_last ; i++ )
    if (strncmp(GetG_name(i),namePrefix,strlen(namePrefix))==0)
      break;
  return ( i<=gTab_last );

}

static char newGatePrefix[3];

/* InitNewGatePrefixRF
 * Determine an appropiate prefix for the auxiliary new gates.
 * ng,nh,...,nz,og,......,zz.
 */
static void InitNewGatePrefixRF()
{
  char c2,c1;

  for ( c1='n'; c1<='z'; c1++ ) {
    newGatePrefix[0] = c1;
    for ( c2='g'; c2<='z'; c2++ ) {
      newGatePrefix[1] = c2;
      if ( !ExistPrefixG(newGatePrefix) ) {
	newGatePrefix[2] = '\0';
	there_is_newgate_prefix = TRUE;
	return;
      }
    }
  }
  Error("InitNewGatePrefixRF : gate name overflow");
}


static DescriptorTyp NewGate(i)
     int i;
{
  DescriptorTyp gd;
  char * s;

  if ( !there_is_newgate_prefix )
    InitNewGatePrefixRF();
  s = (char*)emalloc(8);
  (void)sprintf(s,"%s%d",newGatePrefix,i);
  LASSERT(strlen(s)<8);
  if ( (gd=FindG(s))==0 )
    return Declare_gate(s);
  else {
    free(s);
    return gd;
  }
}


/* KJT 22/01/23: added "int" type */
static int EqGFor( e1, e2 )
     DataListTyp e1,e2;
{
  return e1==(DataListTyp)LookForGateRF((RelabFuncListTyp)(e2));
}


/* KJT 22/01/23: added "int" type */
static int EqGAct( e1, e2 )
     DataListTyp e1,e2;
{
  return e1==(DataListTyp)LookActGateRF((RelabFuncListTyp)(e2));
}


/* KJT 22/01/23: added "int" type */
static int IndexRFs( rfl, clean, dirt )
     RelabFuncListTyp rfl;
     ListTyp *clean, *dirt;
{
  ListTyp n;

  for ( ; rfl!=NULL; rfl = Next_list(rfl) ) {
    n = LookFor_list( (DataListTyp)LookActGateRF(rfl), *clean, EqGFor );
    if ( n==NULL )
      *clean = Add_list((DataListTyp)rfl,*clean);
    else
      if ( !In_list( (DataListTyp)LookForGateRF(rfl), n, EqGAct ) )
	*clean = InsertBeforeNode_list( (DataListTyp)(rfl), *clean, n );
      else
	*dirt  = Add_list((DataListTyp)rfl,*dirt);

  }
}


/* RFL_to_GDL
 * Compute the equivalent gate declaration list of a rfl.
 */
GateDecListTyp RFL_to_GDL( rfl )
     RelabFuncListTyp rfl;
{

  GateDecListTyp result, tail;
  GateSetTyp     fgs,fngs;
  GateListTyp    agl,angl;
  DescriptorTyp  ng;
  ListTyp        cleanRFs, dirtyRFs, cleanRFsBk,dirtyRFsBk;
  int            i;

  result   = Create_list();
  tail     = Create_list();
  dirtyRFs = Create_list();
  cleanRFs = Create_list();
  IndexRFs( rfl, &cleanRFs, &dirtyRFs );

  cleanRFsBk = cleanRFs;
  dirtyRFsBk = dirtyRFs;
  for ( i=1 ; cleanRFs!=NULL ; cleanRFs = Next_list(cleanRFs) ) {
    agl    = InsertGL( LookActGateRF((RelabFuncListTyp)LookInfo_list(cleanRFs)),
		      Create_list() );
    fgs    = GetG_mask(LookForGateRF((RelabFuncListTyp)LookInfo_list(cleanRFs)));
    result = AddGDL( MakeGD(agl,CopyGS(fgs)), result );
  }
  Disp_list(cleanRFsBk);

  for ( i=1 ; dirtyRFs!=NULL ; dirtyRFs = Next_list(dirtyRFs) ) {
    agl = InsertGL( LookActGateRF((RelabFuncListTyp)LookInfo_list(dirtyRFs)),
		   Create_list() );
    fgs = GetG_mask(LookForGateRF((RelabFuncListTyp)LookInfo_list(dirtyRFs)));
    ng  = NewGate(i);
    i++;
    fngs   = GetG_mask(ng);
    angl   = InsertGL( ng, Create_list() );
    result = InsertGDL( MakeGD(agl,CopyGS(fngs)), result );
    tail   = AddGDL( MakeGD(angl,CopyGS(fgs)), tail );
  }
  Disp_list(dirtyRFsBk);

  return Join_list(result,tail);
}

/*----------------------------------------------------------------*/

/* SimplifyRFL
 * Remove from rfl those RFs whose formal gates belong to gs.
 * ( gs is supposed to be an invisible (to the rfl) gate set )
 */
RelabFuncListTyp SimplifyRFL( rfl, gs )
     RelabFuncListTyp rfl;
     GateSetTyp gs;
{
  RelabFuncListTyp pNode,next;

  pNode = rfl;
  while ( pNode!=NULL ) {
    next = Next_list( pNode );
    if ( GateInGS( LookForGateRF(pNode), gs ) )
      rfl = DeleteNodeRFL(pNode,rfl);
    pNode = next;
  }
  return rfl;

}

/*----------------------------------------------------------------*/






