/******************************************************************
 *  (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

/******************************************************************
 *  
 *  
 *  Santiago Pavon Gomez
 *  David Larrabeiti Lopez
 *
 *  19 Jan 1990
 *
 *  Management of offers & offer lists
 *  
 *  Brief description
 *
 *  COMPILATION FLAGS:
 *  
 *  LOG:
 *     25/06/92. santiago.
 *     Introduced a function to get a list with the variables
 *     defined in an offer list
 *     14/10/92. dlarra.
 *     Introduced a function to transform "?x:s" into "!x" in an
 *     offer list
 *
 ******************************************************************/

/* LINTLIBRARY */

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


/* 
 *  count of offer structs used and released.
 */
static int new_offer_count      = 0;
static int released_offer_count = 0;
static int max_offer_count      = 0;

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

/* InitOffer
 * Init the module of offers
 */
void InitOffer()
{
#ifdef SDEBUG
  new_offer_count      = 0;
  released_offer_count = 0;
  max_offer_count      = 0;
#endif
}

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

/* NewOffer
 * Get memory for a new offer.
 */
POfferTyp NewOffer()
{
  POfferTyp p;
  
#ifdef SDEBUG
  new_offer_count++;
  max_offer_count=MAX( max_offer_count, new_offer_count-released_offer_count );
#endif
  p = (POfferTyp) NewCellM(sizeof(OfferTyp));
  p->class = (DescriptorTyp)NULL;
  p->value = NULL;
  p->next  = NULL;
  return p;
}

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

/* DispOffer
 * Free the memory used by an offer cell.
 */
void DispOffer( c )
     POfferTyp    c;  
{
#ifdef SDEBUG
  released_offer_count++;
#endif
  FreeCellM((void*)c,sizeof(OfferTyp));
}

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

/* FreeOffer
 * Free an offer.
 */
void FreeOffer(o)
     POfferTyp  o;
{
  LASSERT(OwnersE(o->value)!=0);
  FreeE(UnshareE(o->value));
  DispOffer(o);
}

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

/* StatOffer
 * 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 StatOffer( new, released, max )
     int * new, *released, *max;
{
  *new      = new_offer_count;
  *released = released_offer_count;
  *max      = max_offer_count;
}

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

/* CopyOffer
 * Copy an offer o.
 */
POfferTyp CopyOffer(o)
     POfferTyp o;
{
  POfferTyp no;
  
  LASSERT(OwnersE(o->value)!=0);
  no = NewOffer();
  no->value = ShareE(CopyE(o->value)); /*mse*/
  no->class = o->class;
  return no;
}

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

/* LookExprOffer
 * Look at the variable or the expression of an offer.
 * It must not be modified, it is only to examine.
 * o is either an offer list or an offer.
 */
ExprTyp LookExprOffer( o )
     OfferListTyp  o; 
{
  LASSERT(o!=NULL);
  LASSERT(OwnersE(o->value)!=0);
  return o->value;
}

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

/* GetExprOffer
 * Get the variable or the expression of an offer.
 * It may be modified. After this, it must be restored into the offer
 * using the function PutExprOffer.
 * o is either an offer list or an offer.
 */
ExprTyp GetExprOffer( o )
     OfferListTyp  o; 
{
  ExprTyp ve;
  
  LASSERT(o!=NULL);
  LASSERT(OwnersE(o->value)!=0);
  ve = UnshareE(o->value);
  o->value = NULL;
  return ve;
}

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

/* PutExprOffer
 * Restore either a variable or an expression into an offer.
 * See the function GetExprOffer.
 * o is either an offer list or an offer.
 * ve points to either a variable or an expression.
 */
void PutExprOffer( o,ve )
     OfferListTyp  o; 
     ExprTyp       ve;  
{
  LASSERT(o!=NULL);
  LASSERT(o->value==NULL);
  o->value = ShareE(ve);
}

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

/* LookKindOffer
 * Return QUESTION or EXCLAMATION depending on the offer kind.
 * o is either an offer list or an offer.
 */
int LookKindOffer( o )
     OfferListTyp  o; 
{
  LASSERT(o!=NULL);
  return o->class;
}

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

/* PutKindOffer
 * Puts the kind QUESTION or EXCLAMATION to the offer o.
 * o is either an offer list or an offer.
 * k is QUESTION or EXCLAMATION.
 */
void PutKindOffer( o, k )
     OfferListTyp  o; 
     int           k;  
{
  LASSERT(o!=NULL);
  o->class = k;
}

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

/* MakeOffer
 * Makes an offer with k and ve.
 * k is QUESTION or EXCLAMATION.
 * ve is a variable or an expression.
 */
POfferTyp MakeOffer( k,ve )
     int       k; 
     ExprTyp   ve;  
{
  POfferTyp o;
  
  o = NewOffer();
  o->class = k;
  o->value = ShareE(ve);
  return o;
}

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

/* FreeOL
 * Free the memory used by the offer list ol.
 */
void FreeOL( ol )
     OfferListTyp  ol; 
{
  if ( ol!=NULL ){
    FreeOL(ol->next);
    FreeOffer(ol);
  }
}

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

/* LengthOL
 * Return the length of an offer list ol.
 */
int LengthOL( ol )
     OfferListTyp  ol;
{
  int i;
  
  for (i=0;ol!=NULL;i++)
    ol=ol->next;
  return i;
}

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

/* CopyOL
 * Copy an offer list ol.
 */
OfferListTyp CopyOL( ol )
     OfferListTyp ol; 
{
  OfferListTyp nol;
  
  nol = CreateOL();
  for (  ; ol!=NULL ; ol=ol->next ) 
    nol = AddOL( CopyOffer(ol) , nol );
  return nol;
}

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

/* UnshareOL
 * Unshare an offer list ol.
 */
OfferListTyp UnshareOL( ol )
     OfferListTyp ol; 
{
  OfferListTyp l; 
  
  for (l=ol  ; l!=NULL ; l=l->next ) 
    l->value = ShareE(GetE(UnshareE(l->value)));
  return ol;
}

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

/* JoinOL
 * Join the offer list ol1 and ol2. Return ol1,ol2.
 */
OfferListTyp JoinOL( ol1, ol2 )
     OfferListTyp ol1,ol2;
{
  OfferListTyp aux;
  
  if ( ol1 != NULL ) {
    for (aux = ol1 ; aux->next!=NULL ; aux=aux->next ) ;
    aux->next = ol2;
    return ol1;
  }
  else 
    return ol2;
}

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

static StrBckTyp strBck;

/* SPrintOffer
 * Make a string with Offer o.
 */
static void SPrintOffer( o )
     POfferTyp  o;
{
  char    * str;
  
  if ( o->class==QUESTION ){
    strBck = ConcatStrBck( strBck, " ? " );
    str    = SPrintV(LookNameE(o->value),TRUE);
  }
  else
    if ( o->class==EXCLAMATION ){
      strBck  = ConcatStrBck( strBck, " ! " );
      str     = ExprToStringE( o->value );
    }
    else 
      Error("Unexpected offer type.");
  strBck  = ConcatStrBck( strBck, str );
  free(str);
}


/* PrintOL
 * Print an offer list ol.
 * pstr is the function used to print strings.
 */
void PrintOL( ol, pstr )
     OfferListTyp   ol;
     void (*pstr)(); 
{
  char * str;
  
  str = SPrintOL( ol );
  pstr(str);
  (void)free(str);
  
}

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

/* SPrintOL
 * Make a string with the offer list ol.
 */
char * SPrintOL( ol )
     OfferListTyp   ol;
{
  char    * str;
  
  strBck = CreateStrBck();
  for (  ; ol!=NULL ; ol=ol->next )
    SPrintOffer(ol);
  str = GetStrStrBck( strBck) ;
  FreeStrBck( strBck );
  
  return str;
}

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

/* PrintExitOL
 * Print the offer list ol using exit format.
 * pstr is the function used to print strings.
 */
void PrintExitOL( ol, pstr )
     OfferListTyp   ol;
     void (*pstr)(); 
{
  char * str;
  
  str = SPrintExitOL( ol );
  pstr(str);
  (void)free(str);
  
}

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

/* SPrintExitOL
 * Make a string with an offer list using exit format.
 */
char * SPrintExitOL( ol )
     OfferListTyp ol;
{
  
  char    * str;
  
  strBck = CreateStrBck();
  while ( ol!=NULL ) {
    if ( LookKindOffer(ol)==QUESTION ) {
      strBck  = ConcatStrBck( strBck, "any " );
      str = SPrintS( GetV_sort(LookNameE(LookExprOffer(ol))));
    }
    else
      if ( LookKindOffer(ol)==EXCLAMATION ){
	str = ExprToStringE( LookExprOffer(ol) );
      }
      else
	Error("Unexpected offer type.");
    strBck  = ConcatStrBck( strBck, str );
    free( str );
    ol = MvNextOffer(ol);
    if ( ol!=NULL ) 
      strBck = ConcatStrBck( strBck, ", " );
  }
  str = GetStrStrBck( strBck) ;
  FreeStrBck( strBck );
  
  return str;
}

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

/* MvNextOffer
 * Move to the next offer.
 * o points to an offer list, and the next node is returned.
 */
OfferListTyp MvNextOffer( o )
     OfferListTyp  o;
{
  LASSERT(o != NULL);
  return o->next;
}

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

/* AddOL
 * Add an offer o to the offer list ol.
 */
OfferListTyp AddOL( o,ol )
     POfferTyp  o;  
     OfferListTyp  ol;  
{
  LASSERT(o->next == NULL);
  return  JoinOL(ol,o);
}

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

/* InsertOL
 * Insert the offer o into the offer list ol.
 */
OfferListTyp InsertOL( o,ol )
     POfferTyp  o;  
     OfferListTyp  ol;  
{
  LASSERT(o->next == NULL);
  return JoinOL(o,ol);
}

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

/* IsThereQuestionOL
 * Return TRUE if there is an offer QUESTION in the offer list ol.
 * otherwise FALSE.
 */
boolean IsThereQuestionOL( ol )
     OfferListTyp  ol; 
{
  while (ol!=NULL) {
    if (ol->class == QUESTION)
      return TRUE;
    else
      ol = ol->next;
  }
  return FALSE;
}

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

/* IsThereExclamationOL
 * Return TRUE if there is an offer EXCLAMATION in the offer list ol.
 * otherwise FALSE.
 */
boolean IsThereExclamationOL( ol )
     OfferListTyp  ol;  
{
  while (ol!=NULL) {
    if (ol->class == EXCLAMATION)
      return TRUE;
    else
      ol = ol->next;
  }
  return FALSE;
}

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

/* StatisticOL
 * Statistic of an offer list ol.
 * Returns the number of Offer-nodes (no) used in the offer list ol, and
 * the number of variable and operator cells and list nodes used.
 * nv,vv and ov are virtual values of number of list nodes, variable and
 * operation cell, i.e. without paying attention to the sharing feature.
 * nr,vr and or are the real values, i.e. nodes and cells already counted
 * in other expressions are not counted again here.
 */
void StatisticOL( ol,nv,vv,ov,nr,vr,or,no )
     OfferListTyp ol;
     int          *nv,*vv,*ov,*nr,*vr,*or,*no; 
{
  int op,var,list,op2,var2,list2;
  
  *nv = *vv = *ov = *nr = *vr = *or = *no = 0; 
  while (ol != NULL) {
    (*no)++;
    StatisticE(ol->value,&list,&var,&op,&list2,&var2,&op2);
    *vr += var2;
    *or += op2;
    *nr += list2;
    *vv += var;
    *ov += op;
    *nv += list;
    ol = MvNextOffer(ol);
  }
}

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

static ExprListTyp lol;

static void VarInOfferListAux( ol )
     OfferListTyp ol;
{
  ExprTyp v;
  
  while(ol!=NULL) {
    if (LookKindOffer(ol)==QUESTION) {
      v = LookExprOffer(ol);
      if ( !InEL(v,lol) )                  /* puede estar dos veces ???!!! */
	lol = InsertEL(CopyE(v),lol); /*mse*/
    }
    ol = MvNextOffer(ol);
  }
}

/* VarsDefinedInOL
 * Return a list with the variables defined in the offer list ol.
 */
ExprListTyp VarsDefinedInOL( ol )
     OfferListTyp ol;
{
  lol = CreateEL();
  VarInOfferListAux( ol );
  return lol;
}

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

/* LookForVarOL
 * Look for the offer where variable v is being defined
 */
OfferListTyp LookForVarOL( vd, ol )
     DescriptorTyp vd;
     OfferListTyp  ol;
{
  for ( ; ol!=NULL; ol = MvNextOffer(ol) )
    if ( LookKindOffer(ol)==QUESTION &&
	LookNameE(LookExprOffer(ol))==vd )
      return ol;
  Error("LookForVarOL:variable not found");
  return NULL;
}

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

/* Convert_to_AdmirationOL
 * Transform all the QUESTION offers into ADMIRATION offers
 */
void Convert_to_AdmirationOL(ol)
     OfferListTyp ol;
{
  for ( ;ol!=NULL; ol = MvNextOffer(ol) )
    if ( LookKindOffer(ol)==QUESTION )
      PutKindOffer(ol,EXCLAMATION);
}

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









