

#include "head.h"

#define MUXUP 1
#define MUXDN 2
#define CMPUP 3
#define CMPDN 4

extern chain_list * INF_MUXU;
extern chain_list * INF_MUXD;
extern chain_list * INF_CMPU;
extern chain_list * INF_CMPD;


/****************************************************************************
 *                         fonction mux2fcf();                              *
 ****************************************************************************/
chain_list * mux2fcf()
{
chain_list  * doubletListeMu = NULL ;
chain_list  * doubletListeMd = NULL ;
chain_list  * doubletListeCu = NULL ;
chain_list  * doubletListeCd = NULL ;
chain_list  * varListeMu     = NULL ;
chain_list  * varListeMd     = NULL ;
chain_list  * varListeCu     = NULL ;
chain_list  * varListeCd     = NULL ;
chain_list  * varListe       = NULL ;
chain_list  * res = NULL;

   /* SI PAS DE CONTRAINTES */
   if((INF_MUXU == NULL) &&
      (INF_MUXD == NULL) &&
      (INF_CMPU == NULL) &&
      (INF_CMPD == NULL) )
   return(NULL) ;


varListeMu=muxMakeVarList(INF_MUXU);
varListeMd=muxMakeVarList(INF_MUXD);
varListeCu=muxMakeVarList(INF_CMPU);
varListeCd=muxMakeVarList(INF_CMPD);

varListe=muxMergeList(varListe,varListeMd);
varListe=muxMergeList(varListe,varListeMu);
varListe=muxMergeList(varListe,varListeCu);
varListe=muxMergeList(varListe,varListeCd);

doubletListeMu=muxMakeDoubletList(INF_MUXU);
doubletListeMd=muxMakeDoubletList(INF_MUXD);
doubletListeCu=muxMakeDoubletList(INF_CMPU);
doubletListeCd=muxMakeDoubletList(INF_CMPD);

res=muxFcfDrive(varListe,doubletListeMu,doubletListeMd,INF_CMPU,doubletListeCu,INF_CMPD,doubletListeCd);

return(res);
}


/****************************************************************************
 *                         fonction muxFcfDrive();                           *
 ****************************************************************************/
/*---------------------------------------------------------------------------+
| Fabrique la base de donnee pour FcF concernant les contrainte externes     |
|                                                                            |
| Entree: Les liste de doublets pour les AND et les liste de variables pour  |
|         les OR les AND (contrainte 'completes').                           |
|                                                                            |
| sortie: Une chain_liste: Le premier DATA contient la liste (chain_liste)   |
|         de tous les connecteurs concernes par des contraintes.             |
|         Le  nieme (n>1) DATA contient  la nieme liste                      |
|         list_list)  de variables constituant UNE contrainte.               |
|         Le USER du premier (list_list) de chaque liste contient l'ABL      |
|         exprimant la contrainte                                            |
|                                                                            |
| Exemple  2 contraintes : A AND B =0 , A AND C =0;                          |
|                                                                            |
|         DATA(1) pointe sur (chain_list)A->B->C->NULL;                      |
|         DATA(2) pointe sur (list_list) A->B->NULL;                         |
|                                        |                                   |
|                                 user : +-> ABL (A AND B)                   |
|                                                                            |
|         DATA(3) pointe sur (list_list) A->C->NULL;                         |
|                                        |                                   |
|                                 user:  +-> ABL (A AND C)                   |
|                                                                            |
+---------------------------------------------------------------------------*/

chain_list *muxFcfDrive(varTot,doubMu,doubMd,orOneTot,doubCu,andZerTot,doubCd)
chain_list *varTot ;
chain_list *doubMu ; 
chain_list *doubMd ; 
chain_list *andZerTot ;
chain_list *doubCu ; 
chain_list *doubCd ; 
chain_list *orOneTot ;
{
chain_list * chain=NULL;
chain_list * res=NULL;

   /*--------------------------------------------+
   | Constitution des I AND J = 0 muxUp          |
   +--------------------------------------------*/
   for(chain=doubMu;chain!=NULL;chain=chain->NEXT)
   {
   chain_list * doublet;
   list_list * contr=NULL;        /*contrainte a construire*/
   chain_list * abl=NULL ;

   doublet=(chain_list*)chain->DATA;
   contr=muxChainToList(doublet);
   abl=muxDoubleToAbl(MUXUP,doublet);
   contr->USER=(ptype_list*)abl;

   res=addchain(res,(void*)contr);
   }

   /*--------------------------------------------+
   | Constitution des I AND J = 0 cmpUp          |
   +--------------------------------------------*/
   for(chain=doubCu;chain!=NULL;chain=chain->NEXT)
   {
   chain_list * doublet;
   list_list * contr=NULL;
   chain_list * abl=NULL ;

   doublet=(chain_list*)chain->DATA;
   contr=muxChainToList(doublet);
   abl=muxDoubleToAbl(CMPUP,doublet);
   contr->USER=(ptype_list*)abl;

   res=addchain(res,(void*)contr);
   }

   /*--------------------------------------------+
   | Constitution des I OR J = 1 muxDn           |
   +--------------------------------------------*/
   for(chain=doubMd;chain!=NULL;chain=chain->NEXT)
   {
   chain_list * doublet;
   list_list * contr=NULL;
   chain_list * abl=NULL ;

   doublet=(chain_list*)chain->DATA;
   contr=muxChainToList(doublet);
   abl=muxDoubleToAbl(MUXDN,doublet);
   contr->USER=(ptype_list*)abl;

   res=addchain(res,(void*)contr);
   }
                   
   /*--------------------------------------------+
   | Constitution des I OR J = 1 cmpDn           |
   +--------------------------------------------*/
   for(chain=doubCd;chain!=NULL;chain=chain->NEXT)
   {
   chain_list * doublet;
   list_list * contr=NULL;
   chain_list * abl=NULL ;

   doublet=(chain_list*)chain->DATA;
   contr=muxChainToList(doublet);
   abl=muxDoubleToAbl(CMPDN,doublet);
   contr->USER=(ptype_list*)abl;

   res=addchain(res,(void*)contr);
   }

   /*--------------------------------------------+
   | Constitution des I OR J OR K..= 1 cmpUp     |
   +--------------------------------------------*/
   for(chain=orOneTot;chain!=NULL;chain=chain->NEXT)
   {
   chain_list * liste;  /* liste de variable */
   list_list * contr=NULL;
   chain_list * abl ;

   liste=(chain_list*)chain->DATA;
   contr=muxChainToList(liste);
   abl=muxChaineToAbl(CMPUP,liste);
   contr->USER=(ptype_list*)abl;
   res=addchain(res,(void*)contr);
   }
      
   /*--------------------------------------------+
   | Constitution des I AND J AND K..= 0 cmpDn   |
   +--------------------------------------------*/
   for(chain=andZerTot;chain!=NULL;chain=chain->NEXT)
   {
   chain_list * liste;
   list_list * contr=NULL;
   chain_list * abl ;

   liste=(chain_list*)chain->DATA;
   contr=muxChainToList(liste);
   abl=muxChaineToAbl(CMPDN,liste);
   contr->USER=(ptype_list*)abl;
   res=addchain(res,(void*)contr);
   }
   
/*-------------------------------------------+
| On ajoute la liste de TOUTES les variables |
+-------------------------------------------*/
res=addchain(res,(void*)varTot);
return(res);
}

/****************************************************************************
 *                         fonction muxAddDoublet();                        *
 ****************************************************************************/
chain_list * muxAddDoublet(list,doublet)
chain_list * list ;
chain_list * doublet ;
{
   
   if(doublet==NULL)
   {
   printf("mux2vcx addCoupleChain doublet=NULL\n");
   exit(-1);
   }

   if(muxDoubletInList(list,doublet)==-1)
   {
   list=addchain(list,(void*)doublet);
   }

return(list);
}

/****************************************************************************
 *                         fonction doubletInList();                         *
 ****************************************************************************/
short muxDoubletInList(list,doublet)
chain_list * list;
chain_list * doublet;
{
chain_list * chain ;
chain_list * couple ;

   if(doublet==NULL)
   {
   printf("mux2vcx doubletInList : doublet=NULL\n");
   exit(-1);
   }

   for(chain=list; chain!=NULL;chain=chain->NEXT)
   {
   couple=(chain_list *)chain->DATA ;

      if ( ((char*)doublet->DATA==(char*)couple->DATA)&&
           ((char*)doublet->NEXT->DATA==(char*)couple->NEXT->DATA) )
      break;

      if ( ((char*)doublet->DATA==(char*)couple->NEXT->DATA)&&
           ((char*)doublet->NEXT->DATA==(char*)couple->DATA) )
      break;
   }

   if(chain==NULL) return(-1);
   else return(0);
}

/****************************************************************************
 *                         fonction muxVarInList();                         *
 ****************************************************************************/
/*--------------------------------------------------+
| teste si var (char*)est dans la liste(chain_list) |
| Retourne 0 si OUI                                 |
|         -1 si NON                                 |
+--------------------------------------------------*/
short muxVarInList(list,var)
chain_list * list;
char       * var;
{
chain_list * chain;

   if(var==NULL)
   {
   printf("mux2vcx varInList : var = NULL \n");
   exit(-1);
   }

   for(chain=list;chain!=NULL;chain=chain->NEXT)
   {
      if(var==(char*)chain->DATA) break;
   }

   if(chain==NULL) return(-1);
   else return(0);
} 

/****************************************************************************
 *                         fonction muxAddVar();                            *
 ****************************************************************************/
/*--------------------------------------------------+
| Ajoute une variable 'name' dans la liste 'list'   |
| si elle n'y est pas deja                          |
+--------------------------------------------------*/
chain_list *muxAddVar(list,name)
chain_list * list ;
char *       name ;
{
chain_list * chain ;

   if(name==NULL)
   {
   printf("mux2vcx muxAddVar : name = NULL \n");
   exit(-1); 
   }

   if(name[0]=='~') name++;
   
   if(muxVarInList(list,name)==-1)
   {
   list=addchain(list,(void*)(namealloc(name)));
   }

return(list);
}

/****************************************************************************
 *                         fonction muxMakeVarList();                       *
 ****************************************************************************/
       /*---------------------------------------------------+
       | Entree : Un chain_list de chainlist  de variable   |
       | Sortie : Un chain_list unique de variables dans    |
       |          laquelle il n'y a pas de redondance       |
       +---------------------------------------------------*/
chain_list * muxMakeVarList(liste)
chain_list * liste ;
{
chain_list  *result=NULL;
chain_list  *intList ;
chain_list  *intVar;

   for(intList=liste;intList!=NULL;intList=intList->NEXT)
   {
      for(intVar=(chain_list*)intList->DATA;intVar!=NULL;intVar=intVar->NEXT)
      {
      result=muxAddVar(result,(char*)intVar->DATA);
      }
   }
return(result);
}


/****************************************************************************
 *                         fonction muxMergeList();                         *
 ****************************************************************************/
/*-------------------------------------------------+
| Ajoute a la liste list1, toutes les variables de |
| la liste list2 qui ne sont pas deja dans list1   |
| Entree: deux chain_list de char * non redondant  |
| Sortie: Une liste unique de variables            |
+-------------------------------------------------*/
chain_list * muxMergeList(list1,list2)
chain_list * list1 ;
chain_list * list2 ;
{
chain_list * chain = NULL ;
   
   for(chain=list2;chain!=NULL;chain=chain->NEXT)
   {
   list1=muxAddVar(list1,(char*)chain->DATA);
   }
return(list1);
}

/****************************************************************************
 *                         fonction muxMakeDoubletList();                   *
 ****************************************************************************/
/*------------------------------------------------------------------+
| Constitue une liste de doublets a partie d'une LISTE (chain_list*)|
| de liste (chain_list*). Pour chaque liste, {A,B,C...} sont        |
| constitues les doublet {A,B} {A,C}...puis {B,C}.....              |
| Entree: Une LISTE de liste.                                       |
| Sortie: Une liste de doublets                                     |
+------------------------------------------------------------------*/
chain_list *muxMakeDoubletList(liste)
chain_list *liste;
{
chain_list * result=NULL;
chain_list * listList;
chain_list * varList;

   for(listList=liste;listList!=NULL;listList=listList->NEXT)
   {
      for(varList=(chain_list*)listList->DATA;
          varList!=NULL;
          varList=varList->NEXT) 
      {
      chain_list * chain;
         for(chain=varList->NEXT;chain!=NULL;chain=chain->NEXT)
         {
         chain_list * doublet ;
         doublet=NULL;
         doublet=addchain(doublet,(void*)varList->DATA);
         doublet=addchain(doublet,(void*)chain->DATA);
         
         result=muxAddDoublet(result,doublet);
         }
      }
   }
return(result);
}
         

/****************************************************************************
 *                         fonction muxAddList();                           *
 ****************************************************************************/
list_list * muxAddList(headList,data,type)
list_list  *headList ;
char       *data ;
long        type ;
{
list_list       *ptlist = NULL ;

ptlist          = (list_list *)mbkalloc(sizeof(list_list));
ptlist->NEXT    = headList ;
ptlist->TYPE    = type ;
ptlist->DATA    = data ;
ptlist->USER    = NULL ;
return( ptlist ) ;
}

/****************************************************************************
 *                         fonction muxChainToList();                       *
 ****************************************************************************/
list_list * muxChainToList(chainliste)
chain_list * chainliste ;
{
chain_list * chain ;
list_list * res = NULL;

  for(chain=chainliste;chain!=NULL;chain=chain->NEXT)
  {
  char * varName=(char*)chain->DATA;
     if(varName[0]=='~') varName++;
  res=muxAddList(res,varName,(long)0);
  }
return(res);
}
  
/****************************************************************************
 *                         fonction muxDoubleToAbl();                       *
 ****************************************************************************/
chain_list* muxDoubleToAbl(oper,doublet) 
short oper;
chain_list *doublet;
{
chain_list * abl=NULL;
chain_list * chain ;

   switch (oper) 
   {
      /* le produit fait Zero */
      case MUXUP :
      case CMPUP :
      {
      abl=createExpr(AND);

         for(chain=doublet;chain!=NULL;chain=chain->NEXT)
         {
         char * var;
         var=(char*)chain->DATA;
            if(var[0]=='~')
            {
           var++;
            addQExpr(abl,notExpr(createAtom(var)));
            }
            else addQExpr(abl,createAtom(var));
         }

      return(notExpr(abl));
      }
      
      /* La somme fait Un */
      case MUXDN :
      case CMPDN :
      {
      abl=createExpr(OR);
    
         for(chain=doublet;chain!=NULL;chain=chain->NEXT)
         {
         char * var;
         var=(char*)chain->DATA;
            if(var[0]=='~')
            {
            var++;
            addQExpr(abl,notExpr(createAtom(var)));
            }
            else addQExpr(abl,createAtom(var));
         }
         
      return(abl);
      }
   }
}
      
   
/****************************************************************************
 *                         fonction muxChaineToAbl();                       *
 ****************************************************************************/
chain_list * muxChaineToAbl(oper,liste)
short oper ;
chain_list * liste ;
{
chain_list * chaine;
chain_list * abl;

   switch (oper)
   {
      /* la somme fait Un */
      case CMPUP :
      {
      abl=createExpr(OR);
         for(chaine=liste;chaine!=NULL;chaine=chaine->NEXT)
         {
         char * var ;
         var=(char*)chaine->DATA;
            if(var[0]=='~')
            {
            var++;
            addQExpr(abl,notExpr(createAtom(var)));
            }
            else addQExpr(abl,createAtom(var));
         }
      return(abl);
      }

      /* le produit fait Zero */
      case CMPDN :
      {
      abl=createExpr(AND);
         for(chaine=liste;chaine!=NULL;chaine=chaine->NEXT)
         {
         char * var ;
         var=(char*)chaine->DATA;
            if(var[0]=='~')
            {
            var++;
            addQExpr(abl,notExpr(createAtom(var)));
            }
            else addQExpr(abl,createAtom(var));
         }
      return(notExpr(abl));
      }
   }
}

/****************************************************************************
 *                         fonction toto();                                 *
 ****************************************************************************/
void muxAffichList(plist)
list_list *plist ;
{
list_list * list;

   for(list=plist; list;list=list->NEXT)
   {
   printf("var: %s Tag=%d\n",(char*)list->DATA,list->TYPE );
   }
}

/****************************************************************************
 *                         fonction toto();                                 *
 ****************************************************************************/
void muxAffichContr(pchain)
chain_list * pchain ;
{
chain_list * chain = NULL;
int cmpt = 1;

   for(chain=pchain;chain;chain=chain->NEXT)
   {
   printf("Liste %d \n",cmpt++);
   muxAffichList((list_list*)chain->DATA);
   }
}

/****************************************************************************
 *                         fonction toto();                                 *
 ****************************************************************************/
void muxAffichChain(chaine)
chain_list * chaine;
{
chain_list * chn ; 

   for(chn=chaine;chn!=NULL;chn=chn->NEXT)
   {
   printf("var: %s \n",(char*)chn->DATA);
   }
}

void muxAffichVarChain(chaine)
chain_list * chaine ;
{
chain_list * chn;
int cmpt = 1;
   for(chn=chaine;chn!=NULL;chn=chn->NEXT)
   {
   printf("Chaine %d \n",cmpt++);
   muxAffichChain((chain_list*)chn->DATA);
   }
}
