/***************************************
*                                      *
*   Copyright (c) 1998 Jean-Eric Pin   *
*   All rights reserved.               *
*                                      *
*   TAB = 2 spaces                     *
*                                      *
***************************************/

/*-------------------------------------------------------------------
 * Memoire.c    Jean-Eric Pin 07/12/96
 *-------------------------------------------------------------------
 */     

#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
#include "Main.h"
#include "Globales.h"
#include "Initialisation.h"
#include "InitLaTeX.h"
#include "Inverses.h"
#include "Matrices.h"
#include "MatricesBooleennes.h"
#include "MatricesMaxPlus.h"
#include "Memoire.h"
#include "Transitions.h"
#include "Utilitaires.h"
#ifdef DEBUG
  extern long ElementsAlloues;
#endif   /* DEBUG */

extern unsigned long *TableDeHachage;    /* La table de l'adresse des elements. On y accede par hachage et adressage ouvert. */
extern unsigned long *TableIdempotents;  /* La table des idempotents */
extern unsigned long *B;  /* La table des blocs */
extern unsigned long NbElements, TailleMaxi; 
extern unsigned long TailleTableDeHachage;
extern info *Table;
extern info2 *Table2;
extern ProduitsDG *TableInfo;
/* extern lettre *Mot; */
extern unsigned short NbEtats, NbLettres, MemoireAllouee, MemoireInitiauxAllouee, 
                      MemoireFinauxAllouee;
extern unsigned long CalculsEffectues;
extern element Identite;
extern element *Generateurs;
extern element *TableDesValeurs;  /* Les valeurs des elements du semigroupe dans l'univers. */
extern Alloue_ AlloueMemoireGenerateur;
extern Libere_ LibereMemoireElement, LibereMemoireGenerateur;
extern char **Messages;
extern infoSommet **Graphe;  /* Le graphe syntactique */
extern Liste2Numeros PileGraphe;  /* Pile utilisee pour le parcours en profondeur du graphe. */
extern unsigned long **TableDeS;  /* La table de multiplication du semigroupe */
extern unsigned short *EtatsInitiaux, *EtatsFinaux;
extern long *TableauLongueurMots;
extern struct NumeroEtLettre *PileInverses;
extern ListeNumero *Inverses, *InversesFaibles;
extern adresses Adresses;

/****************************************************
*
* AlloueMemoireAdresses. OK
*
****************************************************/

void AlloueMemoireAdresses(void)
{
  Adresses.commutatif_1 = (lettre *)malloc(sizeof(lettre));
  if (Adresses.commutatif_1 == NULL)
  {
    printf("%s \n", Messages[M_Pb_memory]);
    exit(1);
  }
  Adresses.commutatif_2 = (lettre *)malloc(sizeof(lettre));
  if (Adresses.commutatif_2 == NULL)
  {
    printf("%s \n", Messages[M_Pb_memory]);
    exit(1);
  }
  Adresses.idempotent = (unsigned long *)malloc(sizeof(unsigned long));
  if (Adresses.idempotent == NULL)
  {
    printf("%s \n", Messages[M_Pb_memory]);
    exit(1);
  }
  Adresses.aperiodique = (unsigned long *)malloc(sizeof(unsigned long));
  if (Adresses.aperiodique == NULL)
  {
    printf("%s \n", Messages[M_Pb_memory]);
    exit(1);
  }
  Adresses.DA_x = (unsigned long *)malloc(sizeof(unsigned long));
  if (Adresses.DA_x == NULL)
  {
    printf("%s \n", Messages[M_Pb_memory]);
    exit(1);
  }
  Adresses.DA_y = (unsigned long *)malloc(sizeof(unsigned long));
  if (Adresses.DA_y == NULL)
  {
    printf("%s \n", Messages[M_Pb_memory]);
    exit(1);
  }
  Adresses.DS_x = (unsigned long *)malloc(sizeof(unsigned long));
  if (Adresses.DS_x == NULL)
  {
    printf("%s \n", Messages[M_Pb_memory]);
    exit(1);
  }
  Adresses.DS_y = (unsigned long *)malloc(sizeof(unsigned long));
  if (Adresses.DS_y == NULL)
  {
    printf("%s \n", Messages[M_Pb_memory]);
    exit(1);
  }
  Adresses.RvL_x = (unsigned long *)malloc(sizeof(unsigned long));
  if (Adresses.RvL_x == NULL)
  {
    printf("%s \n", Messages[M_Pb_memory]);
    exit(1);
  }
  Adresses.RvL_y = (unsigned long *)malloc(sizeof(unsigned long));
  if (Adresses.RvL_y == NULL)
  {
    printf("%s \n", Messages[M_Pb_memory]);
    exit(1);
  }
  Adresses.RvL_z = (unsigned long *)malloc(sizeof(unsigned long));
  if (Adresses.RvL_z == NULL)
  {
    printf("%s \n", Messages[M_Pb_memory]);
    exit(1);
  }
  Adresses.L1_s = (unsigned long *)malloc(sizeof(unsigned long));
  if (Adresses.L1_s == NULL)
  {
    printf("%s \n", Messages[M_Pb_memory]);
    exit(1);
  }
  Adresses.L1_e = (unsigned long *)malloc(sizeof(unsigned long));
  if (Adresses.L1_e == NULL)
  {
    printf("%s \n", Messages[M_Pb_memory]);
    exit(1);
  }
  Adresses.LG_e = (unsigned long *)malloc(sizeof(unsigned long));
  if (Adresses.L1_e == NULL)
  {
    printf("%s \n", Messages[M_Pb_memory]);
    exit(1);
  }
  Adresses.LG_s = (unsigned long *)malloc(sizeof(unsigned long));
  if (Adresses.L1_s == NULL)
  {
    printf("%s \n", Messages[M_Pb_memory]);
    exit(1);
  }
  Adresses.B1_p = (unsigned long *)malloc(sizeof(unsigned long));
  if (Adresses.B1_p == NULL)
  {
    printf("%s \n", Messages[M_Pb_memory]);
    exit(1);
  }
  Adresses.B1_q = (unsigned long *)malloc(sizeof(unsigned long));
  if (Adresses.B1_q == NULL)
  {
    printf("%s \n", Messages[M_Pb_memory]);
    exit(1);
  }
  Adresses.B1_r = (unsigned long *)malloc(sizeof(unsigned long));
  if (Adresses.B1_r == NULL)
  {
    printf("%s \n", Messages[M_Pb_memory]);
    exit(1);
  }
  Adresses.B1_s = (unsigned long *)malloc(sizeof(unsigned long));
  if (Adresses.B1_s == NULL)
  {
    printf("%s \n", Messages[M_Pb_memory]);
    exit(1);
  }
  Adresses.B1_e = (unsigned long *)malloc(sizeof(unsigned long));
  if (Adresses.B1_e == NULL)
  {
    printf("%s \n", Messages[M_Pb_memory]);
    exit(1);
  }
  Adresses.B1_f = (unsigned long *)malloc(sizeof(unsigned long));
  if (Adresses.B1_f == NULL)
  {
    printf("%s \n", Messages[M_Pb_memory]);
    exit(1);
  }
  Adresses.B1Plus_e = (unsigned long *)malloc(sizeof(unsigned long));
  if (Adresses.B1Plus_e == NULL)
  {
    printf("%s \n", Messages[M_Pb_memory]);
    exit(1);
  }
  Adresses.B1Plus_s = (unsigned long *)malloc(sizeof(unsigned long));
  if (Adresses.B1Plus_s == NULL)
  {
    printf("%s \n", Messages[M_Pb_memory]);
    exit(1);
  }
  Adresses.ECom_e = (unsigned long *)malloc(sizeof(unsigned long));
  if (Adresses.ECom_e == NULL)
  {
    printf("%s \n", Messages[M_Pb_memory]);
    exit(1);
  }
  Adresses.ECom_f = (unsigned long *)malloc(sizeof(unsigned long));
  if (Adresses.ECom_f == NULL)
  {
    printf("%s \n", Messages[M_Pb_memory]);
    exit(1);
  }
  Adresses.BG_e = (unsigned long *)malloc(sizeof(unsigned long));
  if (Adresses.BG_e == NULL)
  {
    printf("%s \n", Messages[M_Pb_memory]);
    exit(1);
  }
  Adresses.BG_f = (unsigned long *)malloc(sizeof(unsigned long));
  if (Adresses.BG_f == NULL)
  {
    printf("%s \n", Messages[M_Pb_memory]);
    exit(1);
  }
}

/****************************************************
*
* LibereMemoireAdresses. OK
*
****************************************************/

void LibereMemoireAdresses(void)
{
  free(Adresses.commutatif_1);
  free(Adresses.commutatif_2);
  free(Adresses.idempotent);
  free(Adresses.aperiodique);
  free(Adresses.DA_x);
  free(Adresses.DA_y);
  free(Adresses.DS_x);
  free(Adresses.DS_y);
  free(Adresses.RvL_x);
  free(Adresses.RvL_y);
  free(Adresses.RvL_z);
  free(Adresses.L1_e);
  free(Adresses.L1_s);
  free(Adresses.LG_e);
  free(Adresses.LG_s);
  free(Adresses.B1_p);
  free(Adresses.B1_q);
  free(Adresses.B1_r);
  free(Adresses.B1_s);
  free(Adresses.B1_e);
  free(Adresses.B1_f);
  free(Adresses.B1Plus_e);
  free(Adresses.B1Plus_s);
  free(Adresses.ECom_e);
  free(Adresses.ECom_f);
  free(Adresses.BG_e);
  free(Adresses.BG_f);
}

/****************************************************
*
* AlloueMemoireProduits. OK
* Necessite de connaitre le nombre de lettres
*
****************************************************/

ProduitsDG *AlloueMemoireProduits(void)
{
  register ProduitsDG *Produits;
  
  Produits = ALLOC(ProduitsDG, NbLettres);
  if (Produits == NULL)
  {
    printf("%s %s\n", Messages[M_Pb_memory], Messages[M_Pb_products]);  /* Probleme lors de l'allocation memoire des produits */
    exit(1);
  }
  return Produits;
}

/****************************************************
*
* AlloueMemoireGenerateurs. OK
*
****************************************************/

void AlloueMemoireGenerateurs(void)
{
  lettre a;
  
  if (!(MemoireAllouee & MEMOIRE_GENERATEURS))
  {
    Generateurs = ALLOC(element, NbLettres);
    if (Generateurs == NULL)
    {
      printf("%s %s\n", Messages[M_Pb_memory], Messages[M_Pb_generators]);  /* Probleme lors de l'allocation memoire des generateurs */
      exit(1);
    }
    for (a = 0; a < NbLettres; a++)
      Generateurs[a] = AlloueMemoireGenerateur();
    MemoireAllouee |= MEMOIRE_GENERATEURS;    /* On prend note : on a alloue de la memoire aux generateurs. */
  }
#ifdef DEBUG
  else
    printf("La memoire des generateurs est deja allouee !\n");
#endif   /* DEBUG */
}

/****************************************************
*
* LibereMemoireGenerateurs. OK
*
****************************************************/

void LibereMemoireGenerateurs(void)
{
  lettre a;
  
  if (MemoireAllouee & MEMOIRE_GENERATEURS)
  {
    for (a = 0; a < NbLettres; a++)
      LibereMemoireGenerateur(Generateurs[a]);
    free(Generateurs);
    MemoireAllouee &= ~MEMOIRE_GENERATEURS;    /* On prend note : on a libere la memoire des generateurs. */
  }
}

/***********************************************************************************
*
* AlloueMemoireTableDesValeurs. OK
* TableDesValeurs[1] donne l'identite.
* S'il y a 2 generateurs, leurs valeurs seront stockees
* en TableDesValeurs[2] et TableDesValeurs[3].
*
* Cette procedure est necessairement appelee AVANT InitIdentite et InitGenerateurs()
*
************************************************************************************/

void AlloueMemoireTableDesValeurs(void)
{  
  if (!(MemoireAllouee & MEMOIRE_TABLE_VALEURS))
  {
    TableDesValeurs = ALLOC(element, 2 + TailleMaxi);
    if (TableDesValeurs == NULL)
    {
      printf("%s %s\n", Messages[M_Pb_memory], Messages[M_Pb_table_elements]);  /* Probleme lors de l'allocation memoire de la table des elements */
      exit(1);
    }
    MemoireAllouee |= MEMOIRE_TABLE_VALEURS;    /* On prend note : on a alloue de la memoire aux generateurs. */
  }
#ifdef DEBUG
  else
    printf("La memoire de la table des valeurs est deja allouee !\n");
#endif   /* DEBUG */
}

/****************************************************
*
* LibereMemoireTableDesValeurs. OK
*
****************************************************/

void LibereMemoireTableDesValeurs(void)
{
  unsigned long i;
  
  if (MemoireAllouee & MEMOIRE_TABLE_VALEURS)
  {
    for (i = 1; i <= NbElements; i++)
      LibereMemoireElement(TableDesValeurs[i]);
    free(TableDesValeurs);
    MemoireAllouee &= ~MEMOIRE_TABLE_VALEURS;    /* On prend note : on a libere la memoire de la table. */
  }
}

/****************************************************
*
* AlloueMemoirePile. OK
*
****************************************************/

elementpile *AlloueMemoirePile(void)
{
  elementpile *Pile;
    
  if (!(MemoireAllouee & MEMOIRE_PILE))
  {
    Pile = ALLOC(elementpile, NbElements);
    if (Pile == NULL)
    {
      printf("%s %s\n", Messages[M_Pb_memory], Messages[M_Pb_table]);  /* Probleme lors de l'allocation memoire d'un tableau */
      return 0;
    }
    MemoireAllouee |= MEMOIRE_PILE;    /* On prend note : on a alloue de la memoire aux generateurs. */
    return Pile;
  }
#ifdef DEBUG
  else
  {
    printf("La memoire de la pile est deja allouee !\n");
    return 0;
  }
#endif   /* DEBUG */
}

/****************************************************
*
* AlloueMemoirePileComposanteConnexe. OK
*
****************************************************/

unsigned long *AlloueMemoirePileComposanteConnexe(void)
{
  unsigned long *PileComposanteConnexe;
    
  PileComposanteConnexe = ALLOC(unsigned long, NbElements + 1);  /* +1, car on met une sentinelle en fond de pile */
  if (PileComposanteConnexe == NULL)
  {
    printf("%s %s\n", Messages[M_Pb_memory], Messages[M_Pb_table]);  /* Probleme lors de l'allocation memoire d'un tableau */
    return 0;
  }
  return PileComposanteConnexe;
}

/****************************************************
*
* AlloueMemoireTableau. OK
*
****************************************************/

unsigned long *AlloueMemoireTableau(unsigned long Taille)
{
  unsigned long *MyTableau;
    
  MyTableau = ALLOC(unsigned long, Taille);
  if (MyTableau == NULL)
  {
    printf("%s %s\n", Messages[M_Pb_memory], Messages[M_Pb_table]);  /* Probleme lors de l'allocation memoire d'un tableau */
    return 0;
  }
  return MyTableau;
}

/****************************************************
*
* AlloueMemoireTable. OK
*
****************************************************/

info *AlloueMemoireTable(void)
{
  info *MyTable;
  
  MyTable = ALLOC(info, 1 + TailleMaxi);
  if (MyTable == NULL)
  {
    printf("%s %s\n", Messages[M_Pb_memory], Messages[M_Pb_table_elements]);  /* Probleme lors de l'allocation memoire de la table des elements */
    exit(1);
  }
  return(MyTable);
}

/****************************************************
*
* AlloueMemoireTable2. OK
*
****************************************************/

info2 *AlloueMemoireTable2(void)
{
  info2 *MyTable2;
  
  MyTable2 = ALLOC(info2, 1 + NbElements);
  if (MyTable2 == NULL)
  {
    printf("%s %s\n", Messages[M_Pb_memory], Messages[M_Pb_table_elements]);  /* Probleme lors de l'allocation memoire de la table des elements */
    exit(1);
  }
  return(MyTable2);
}

/*********************************************************
*
* AlloueMemoireMot. Ajoute la place pour terminer par '\0' 
*
*********************************************************/

lettre *AlloueMemoireMot(short Longueur)
{
  lettre *Mot;
  
  Mot = ALLOC(lettre, 1 + Longueur);    /* Un de plus, pour terminer par '\0' */
  if (Mot == NULL)
  {
    printf("%s %s\n", Messages[M_Pb_memory], Messages[M_Pb_word]);  /* Probleme lors de l'allocation memoire d'un mot */
    exit(1);
  }
  return(Mot);
}

/****************************************************
*
* AlloueMemoireLettre. OK
*
****************************************************/

lettre *AlloueMemoireLettre(void)
{
  lettre *Mot;
  
  Mot = ALLOC(lettre, 2);    /* Un de plus, pour terminer par '\0' */
  if (Mot == NULL)
  {
    printf("%s %s\n", Messages[M_Pb_memory], Messages[M_Pb_word]);  /* Probleme lors de l'allocation memoire d'un mot */
    exit(1);
  }
  return(Mot);
}


/**********************************************************************
*
* AlloueMemoireChaine. 
*
**********************************************************************/

char *AlloueMemoireChaine(short Longueur)
{
  char *Chaine;
  
  Chaine = ALLOC(char, Longueur);
  if (Chaine == NULL)
  {
    printf("%s %s\n", Messages[M_Pb_memory], Messages[M_Pb_word]);
            /* Probleme lors de l'allocation memoire d'un mot. */
    exit(1);
  }    
  return(Chaine);
}

/**********************************************************************
*
* AlloueMemoireGraphe. Comme les indices partent de 1, 
* on prend un graphe de taille (1 + NbElements) * (1 + NbElements).
* Les entrees Graphe[0][v] et Graphe[u][0] ne servent pas.
*
**********************************************************************/

void AlloueMemoireGraphe(void)
{
  unsigned long j;

  Graphe = ALLOC(infoSommet *, (1 + NbElements));
  if (Graphe == NULL)
  {
    printf("%s %s\n", Messages[M_Pb_memory], Messages[M_Pb_graph]);  /* Probleme lors de l'allocation memoire du graphe. */
    exit(1);
  }
  for (j = 0; j < 1 + NbElements; j++)
  {
    Graphe[j] = ALLOC(infoSommet, 1 + NbElements);
    if (Graphe[j] == NULL)
    {
      printf("%s %s\n", Messages[M_Pb_memory], Messages[M_Pb_graph]);  /* Probleme lors de l'allocation memoire du graphe.  */
      exit(1);
    }
  }
}

/**********************************************************************
*
* LibereMemoireGraphe. 
*
**********************************************************************/

void LibereMemoireGraphe(void)
{
  unsigned long u, v;
  Liste2Numeros Temporaire;

  for (u = 0; u <= NbElements; u++)
    for (v = 0; v <= NbElements; v++)
      while (Graphe[u][v].Aretes != NULL)
      {
        Temporaire = Graphe[u][v].Aretes;
        Graphe[u][v].Aretes = Graphe[u][v].Aretes->suivant;
        free(Temporaire);
      }
  for (u = 0; u <= NbElements; u++)
    free(Graphe[u]);
  free(Graphe);
}

/****************************************************
*
* AlloueMemoirePileGraphe. OK
*
****************************************************/

Liste2Numeros AlloueMemoirePileGraphe(unsigned long Taille)
{
  Liste2Numeros MyPileGraphe;
    
  MyPileGraphe = ALLOC(struct Wagon2Numeros, Taille);
  if (MyPileGraphe == NULL)
  {
    printf("%s %s\n", Messages[M_Pb_memory], Messages[M_Pb_table]);  /* Probleme lors de l'allocation memoire d'un tableau */
    return 0;
  }
  return MyPileGraphe;
}

/****************************************************
*
* AlloueMemoireArete. 
*
****************************************************/

Liste2Numeros AlloueMemoireArete(void)
{
  Liste2Numeros Liste;
  
  Liste = ALLOC(struct Wagon2Numeros, 1);
  if (Liste == NULL)
  {
    printf("%s %s xxx\n", Messages[M_Pb_memory], Messages[M_Pb_graph]);  /* Probleme lors de l'allocation memoire du graphe. */
    exit(1);
  }
  return(Liste);
}

/****************************************************
*
* AlloueMemoireTableDeS. 
*
****************************************************/

unsigned long **AlloueMemoireTableDeS(void)
{
  unsigned long **MyTable;
  unsigned long i;
  
  MyTable = ALLOC(unsigned long *, 1 + NbElements);
  if (MyTable == NULL)
  {
    printf("%s %s\n", Messages[M_Pb_memory], Messages[M_Pb_table]);  /* Probleme lors de l'allocation memoire du graphe. */
    exit(1);
  }
  for (i = 0; i <= NbElements; i++)
  {
    MyTable[i] = ALLOC(unsigned long, 1 + NbElements);
    if (MyTable[i] == NULL)
    {
      printf("%s %s\n", Messages[M_Pb_memory], Messages[M_Pb_table]);  /* Probleme lors de l'allocation memoire du graphe. */
      exit(1);
    }
  }
  return(MyTable);
}

/****************************************************
*
* LibereMemoireTableDeS. 
*
****************************************************/

void LibereMemoireTableDeS(void)
{
  unsigned long i;
  
  for (i = 0; i <= NbElements; i++)
    free(TableDeS[i]);
  free(TableDeS);
}

/****************************************************
*
* AlloueMemoirePileNumeroEtLettre. OK
*
****************************************************/

struct NumeroEtLettre *AlloueMemoirePileNumeroEtLettre(void)
{
  struct NumeroEtLettre *Pile;
    
  Pile = ALLOC(struct NumeroEtLettre, NbElements);
  if (Pile == NULL)
  {
    printf("%s %s\n", Messages[M_Pb_memory], Messages[M_Pb_table]);  /* Probleme lors de l'allocation memoire d'un tableau */
    return 0;
  }
  return Pile;
}

/**********************************************************************
*
* AlloueMemoireTableListeNumero.
*
**********************************************************************/

ListeNumero *AlloueMemoireTableListeNumero(void)
{
  ListeNumero *MyTable;

  MyTable = ALLOC(ListeNumero, 1 + NbElements);    /* Les indices commencent a 1 ... */
  if (MyTable == NULL)
  {
    printf("%s %s\n", Messages[M_Pb_memory], Messages[M_Pb_liste]);  /* Probleme lors de l'allocation memoire d'une liste. */
    exit(1);
  }
  return(MyTable);
}

/****************************************************
*
* AlloueMemoireWagonNumero. 
*
****************************************************/

ListeNumero AlloueMemoireWagonNumero(void)
{
  ListeNumero Liste;
  
  Liste = ALLOC(struct WagonNumero, 1);
  if (Liste == NULL)
  {
    printf("%s %s\n", Messages[M_Pb_memory], Messages[M_Pb_graph]);  /* Probleme lors de l'allocation memoire du graphe. */
    exit(1);
  }
  return(Liste);
}

/****************************************************
*
* LibereMemoireMot. OK
*
****************************************************/

void LibereMemoireMot(element Element)
{
  free(Element);
} 

/**********************************************************************
*
* LibereMemoireListe. 
*
**********************************************************************/

void LibereMemoireListe(ListeNumero *MyList)
{
  unsigned long u;
  ListeNumero Temporaire;

  for (u = 0; u <= NbElements; u++)
    while (MyList[u] != NULL)
    {
      Temporaire = MyList[u];
      MyList[u] = MyList[u]->suivant;
      free(Temporaire);
    }
  free(MyList);
}

/**********************************************************************
*
* AlloueMemoireInitiaux. 
*
**********************************************************************/

void AlloueMemoireInitiaux(void)
{
  EtatsInitiaux = ALLOC(unsigned short, (1 + NbEtats)); /* Initialisation a 0 automatique */
  MemoireInitiauxAllouee = 1;
  if (EtatsInitiaux == NULL)
  {
    printf("%s %s\n", Messages[M_Pb_memory], Messages[M_Pb_initial_states]);
            /* Probleme lors de l'allocation memoire des etats initiaux. */
    exit(1);
  }
}

/**********************************************************************
*
* AlloueMemoireFinaux. 
*
**********************************************************************/

void AlloueMemoireFinaux(void)
{
  EtatsFinaux = ALLOC(unsigned short, (1 + NbEtats)); /* Initialisation a 0 automatique */
  MemoireFinauxAllouee = 1;
  if (EtatsFinaux == NULL)
  {
    printf("%s %s\n", Messages[M_Pb_memory], Messages[M_Pb_final_states]);
            /* Probleme lors de l'allocation memoire des etats finaux. */
    exit(1);
  }
}

/**********************************************************************
*
* AlloueMemoireMessages. 
*
**********************************************************************/

void AlloueMemoireMessages(void)
{
  Messages = ALLOC(char *, M_Last_Line);
  if (Messages == NULL)
  {
    printf("%s %s\n", Messages[M_Pb_memory], Messages[M_Pb_messages]);
            /* Probleme lors de l'allocation memoire des messages. */
    exit(1);
  }
}

/****************************************************
*
* LibereMemoire. OK
* free(TableDeHachage) est fait independamment
*  LibereMemoireGenerateurs() est inutile, car les
* generateurs sont stockes dans la table des valeurs 
*
****************************************************/

void LibereMemoire(void)
{
  unsigned long i;
  
  LibereMemoireGenerateurs();
  for (i = NbElements; i > 0; i--)
    free(Table[i].Produits);
  free(Table[0].Produits);    /* i est de type unsigned long : si i vaut 0, i-- est > 0 ! */
  free(Table);
  free(Table2);
  LibereMemoireTableDesValeurs();
  LibereMemoireAdresses();
  if (CalculsEffectues & CALCUL_LISTE_IDEMPOTENTS)
    free(TableIdempotents);
  if (CalculsEffectues & CALCUL_SYNTACTIQUE)
    LibereMemoireGraphe();
  if (CalculsEffectues & CALCUL_TABLE_DE_S)
    LibereMemoireTableDeS();
  if (CalculsEffectues & CALCUL_BLOCS)
    free(B);
  if (CalculsEffectues & CALCUL_INVERSES)
  {
    free(PileInverses);
    LibereMemoireListe(Inverses);
    LibereMemoireListe(InversesFaibles);
  }
  if (CalculsEffectues & CALCUL_SYNTACTIQUE)
    free(PileGraphe);
  if (MemoireInitiauxAllouee)
  {
    free(EtatsInitiaux);
    MemoireInitiauxAllouee = 0;
  }
  if (MemoireFinauxAllouee)
  {
    free(EtatsFinaux);
    MemoireFinauxAllouee = 0;
  }
  if (MemoireAllouee & MEMOIRE_TABLEAU_LONGUEUR_MOTS)
  {
    free(TableauLongueurMots);
    MemoireAllouee &= ~MEMOIRE_TABLEAU_LONGUEUR_MOTS;    /* On prend note : on a libere la memoire de la table. */
  }
#ifdef DEBUG
  printf("Elements Alloues : %ld \n", ElementsAlloues);
#endif   /* DEBUG */
}