// automate-suff.c

// << Algorithmique du texte >>
// Maxime Crochemore, Christophe Hancart et Thierry Lecroq
// Vuibert, 2001.

#include <stdio.h>
#include "chl.h"
#include "automate-suff.h"

static int compteur = 0;
int *visite;

Etat nouvelEtat() {
   Etat etat;

   etat = (Etat)malloc(sizeof(struct _etat));
   if (etat == NULL) error("nouvelEtat");
   etat->terminal = FAUX;
   etat->succ = NULL;
   etat->sortie = -1;      // Merci à Johann Pelfrêne
   etat->suppleant = NULL;
   etat->nom = compteur++;
   return(etat);
}


void fixerCible(Etat etat, Etiquette a, Etat cible) {
   Succ succ;

   succ = (Succ)malloc(sizeof(struct _succ));
   if (succ == NULL) error("fixerCible");

   succ->etiquette = a;
   succ->cible = cible;
   succ->suivant = etat->succ;
   etat->succ = succ;
   cible->parent = etat;
}


void oterCible(Etat etat, Etiquette a) {
   Succ del, succ;
   // il existe une transition de etat par a

   succ = etat->succ;
   if (succ->etiquette.position == a.position &&
       succ->etiquette.longueur == a.longueur) {
      etat->succ = succ->suivant;
      free(succ);
   }
   else {
      while (succ->suivant->etiquette.position != a.position ||
             succ->suivant->etiquette.longueur != a.longueur)
         succ = succ->suivant;
      del = succ->suivant;
      succ->suivant = del->suivant;
      free(del);
  }
}


Etat cible(Etat etat, Etiquette a) {
   Succ succ;

   succ = etat->succ;
   while (succ != NULL) {
      if (succ->etiquette.position == a.position && succ->etiquette.longueur == a.longueur)
         return(succ->cible);
          else
         succ = succ->suivant;
   }
   return(NULL);
}


Etat cibleParUneLettre(Etat etat, Lettre a, Mot y) {
   Succ succ;

   succ = etat->succ;
   while (succ != NULL) {
      if (y[succ->etiquette.position] == a)
         return(succ->cible);
          else
         succ = succ->suivant;
   }
   return(NULL);
}


Etiquette etiq(Etat p, Etat q) {
   Succ succ;
   // il existe une transition de p a q

   succ = p->succ;
   while (VRAI) {
      if (succ->cible == q)
         return(succ->etiquette);
          else
         succ = succ->suivant;
   }
}


Automate nouvelAutomate() {
   Automate automate;

   automate = (Automate)malloc(sizeof(struct _automate));
   if (automate == NULL) error("nouvelAutomate");
   automate->initial = nouvelEtat();
   automate->initial->parent = NULL;
   return(automate);
}


void ecrireEtat(Etat etat) {
   Succ succ;

   if (!visite[etat->nom]) {
      visite[etat->nom] = VRAI;
      printf("état %d sortie : %d", etat->nom, etat->sortie);
      if (terminal(etat)) printf(" terminal");
      printf("\n");
          succ = etat->succ;
          while (succ != NULL) {
         printf("   delta(%d, (%d,%d)) = %d\n", etat->nom, succ->etiquette.position,
                                                                        succ->etiquette.longueur, succ->cible->nom);
         ecrireEtat(succ->cible);
                 succ = succ->suivant;
      }
   }
}


void ecrireAutomate(Automate automate) {
   visite = (int *)calloc(compteur, sizeof(int));
   if (visite == NULL) error("ecrireAutomate");
   ecrireEtat(initial(automate));
   free(visite);
}