/****************************************
 * Sebastien Leriche, Antoine Jacquet   *
 * Programme principal - Interpreteur   *
 * Niveau 4                             *
 ****************************************/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "memoire.h"

#define TAILLELIGNE 512
#define DELIMITEUR " \t\n"

struct memoire *p_memoire;
FILE *fprimitives;

void afficher_log(char *ligne, struct memoire *p_memoire)
/* Ecriture du fichier pour l'interface graphique Perl/Tk */
{
  static FILE *ficlog=NULL;
  struct liste_tas *p_liste_tas;

  if (ficlog==NULL) ficlog=fopen("log.txt","wt");
  fprintf(ficlog,"%s",ligne);
  if (p_memoire!=NULL)
  {
    p_liste_tas=p_memoire->p_liste_tas;
    fprintf(ficlog,"taille_memoire %d\n",p_memoire->taille_memoire);
    while (p_liste_tas!=NULL)
    {
      fprintf(ficlog,"tas %s %d %d %d\n",p_liste_tas->tas.ident,p_liste_tas->tas.adresse,p_liste_tas->tas.taille,p_liste_tas->tas.compteur_references);
      p_liste_tas=p_liste_tas->p_suivant;
    }
  }
  fprintf(ficlog,"\n");
  if (strcmp(ligne,"terminer")==0) fclose(ficlog);
  return;
}

void quitte(int erreur, char *message)
/* Quitte proprement l'interpreteur */
{
  fprintf(fhistorique,message);
  terminer(&p_memoire);
  fclose(fprimitives);
  fclose(fhistorique);
  exit(erreur);
}

void interprete(char *ligne)
/* Interprete la ligne passee en parametre */
{
  char *mot,*mot2,ligne2[TAILLELIGNE];
  int entier,code;

  strcpy(ligne2,ligne);
  mot=strtok(ligne2,DELIMITEUR);
  if (mot==NULL) return;
  if (mot[0]=='#') return;

  fprintf(fhistorique,"Interpretation de : %s",ligne);

  if (strcmp(mot,"initialiser")==0)
  {
    mot=strtok(NULL,DELIMITEUR);
    if (mot==NULL) quitte(1,"Taille memoire invalide !\n");
    entier=atoi(mot);
    if (entier==0) quitte(1,"Taille memoire invalide !\n");
    code=initialiser(entier,&p_memoire);
  }
  else if (p_memoire==NULL)
  {
    fprintf(fhistorique,"La memoire n'a pas ete initialisee !\n");
    fclose(fprimitives);
    fclose(fhistorique);
    exit(1);
  }
  else if (strcmp(mot,"allouer_tas")==0)
  {
    mot=strtok(NULL,DELIMITEUR);
    if ((mot==NULL) || (strlen(mot)>=TAILLE_IDENT)) quitte(1,"Nom de tas invalide !\n");
    mot2=strtok(NULL,DELIMITEUR);
    if (mot2==NULL) quitte(1,"Taille de tas invalide !\n");
    entier=atoi(mot2);
    if (entier==0) quitte(1,"Taille de tas invalide !\n");
    code=allouer_tas(mot,entier,p_memoire);
  }
  else if (strcmp(mot,"liberer_tas")==0)
  {
    mot=strtok(NULL,DELIMITEUR);
    if (mot==NULL) quitte(1,"Nom de tas invalide !\n");
    code=liberer_tas(mot,p_memoire);
  }
  else if (strcmp(mot,"terminer")==0)
  {
    code=terminer(&p_memoire);
  }
  else if (strcmp(mot,"ajouter_programme")==0)
  {
    mot=strtok(NULL,DELIMITEUR);
    if (mot==NULL) quitte(1,"Nom de programme invalide !\n");
    code=ajouter_programme(mot,p_memoire);
  }
  else if (strcmp(mot,"supprimer_programme")==0)
  {
    mot=strtok(NULL,DELIMITEUR);
    if (mot==NULL) quitte(1,"Nom de programme invalide !\n");
    code=supprimer_programme(mot,p_memoire);
  }
  else if (strcmp(mot,"ajouter_lien")==0)
  {
    mot=strtok(NULL,DELIMITEUR);
    mot2=strtok(NULL,DELIMITEUR);
    if ((mot==NULL) || (mot2==NULL)) quitte(1,"Nom de tas invalide !\n");
    code=ajouter_lien(mot,mot2,p_memoire);
  }
  else if (strcmp(mot,"supprimer_lien")==0)
  {
    mot=strtok(NULL,DELIMITEUR);
    mot2=strtok(NULL,DELIMITEUR);
    if ((mot==NULL) || (mot2==NULL)) quitte(1,"Nom de tas invalide !\n");
    code=supprimer_lien(mot,mot2,p_memoire);
  }
  else if (strcmp(mot,"politique")==0)
  {
    mot=strtok(NULL,DELIMITEUR);
    if ((mot==NULL) || ((strcmp(mot,"first_fit")!=0) && (strcmp(mot,"best_fit")!=0) && (strcmp(mot,"worst_fit")!=0)) ) quitte(1,"Nom de politique invalide !\n");
    fprintf(fhistorique,"Nouvelle politique : %s\n",mot);
    politique=mot[0];
    code=0;
  }
  else quitte(1,"Primitive invalide !\n");

  afficher_log(ligne,p_memoire);

  fprintf(fhistorique,"Code de retour : %d\n",code);
  fprintf(fhistorique,"Fin de l'interpretation de : %s\n",ligne);
  return;
}

int main(int argc, char **argv)
/* Programme principal
   parametre optionnel : fichier de primitives */
{
  char ligne[TAILLELIGNE];

  if (argc==1) fprimitives=fopen("primitives.txt","rt");
  else fprimitives=fopen(argv[1],"rt");
  if (fprimitives==NULL)
  {
    fprintf(stderr,"Erreur d'ouverture du fichier de primitives !\n");
    return(1);
  }
  if ((fhistorique=fopen("historique.txt","wt"))==NULL)
  {
    fprintf(stderr,"Erreur d'ouvertude du fichier d'historique !\n");
    fclose(fprimitives);
    return(2);
  }

  while (1)
  {
    if (fgets(ligne,TAILLELIGNE,fprimitives)==NULL) break;
    if (strlen(ligne)==TAILLELIGNE-1)
    {
      fprintf(stderr,"Ligne trop longue dans le fichier de primitives !\n");
      fclose(fprimitives);
      fclose(fhistorique);
      return(3);
    }
    interprete(ligne);
  }

  fprintf(fhistorique,"Fin de l'interpretation des primitives\n");
  fclose(fprimitives);
  fclose(fhistorique);
  return(0);
}