#include "prehtml.h"

char *typeimbrique(imbrique *i){
  switch(i->type){
   case MAIN:return "top-level";
   case IF:return "IF";
   case FOR:return "FOR";
   case WHILE:return "WHILE";
   case INCLUDE:return "(NOT)INCLUDE";
   default:return "inconnue";
  }
}

int attend(char *etiq){ /* trouve le champ "etiq" correspondant sans
			  * exécuter le code intermédiaire, mais en
			  * faisant attention aux imbrications*/
  /* si etiq="else", renvoie 1 si trouvé, et 0 si a rencontré "fi" */
  char *autorisee[]={"else","fi","done",NULL};
  int i;
  for (i=0;autorisee[i];i++) if (!strcmp(autorisee[i],etiq)) break;
  if (!autorisee[i]) {
    erreur("attend() ne peut pas attendre l'étiquette <%s>",etiq);
  }
  while(1){
    i=decode();
    if (i==EOF) erreur("EOF rencontré alors que j'attendais <%s>",etiq);
    if (i!=EST_FONCTION) continue;
    /* fonctions qui terminent des imbrications */
    if (!strcmp(fonction,"else")){
      if (!strcmp(etiq,"else")) return 1; /* mission accomplie */
      erreur("<else> rencontré alors que j'attendais <%s>",etiq);
    }
    if (!strcmp(fonction,"fi")){
      if (!strcmp(etiq,"fi")) return 1; /* mission accomplie */
      if (!strcmp(etiq,"else")) return 0; /* ce <if> n'a donc pas de <else>*/
      erreur("<fi> rencontré alors que j'attendais <%s>",etiq);
    }
    if (!strcmp(fonction,"done")){
      if (!strcmp(etiq,"done")) return 1; /* mission accomplie */
      erreur("<done> rencontré alors que j'attendais <%s>",etiq);
    }
    /* fonctions qui commencent des imbrications */
    if (!strcmp(fonction,"if")) {
      if (attend("else")) attend("fi");
      continue;
    }
    if ( (!strcmp(fonction,"while")) || (!strcmp(fonction,"for")) ) {
      attend("done");
      continue;
    }
  }
}

imbrique *imbriqueactu;

void referme_imbrique(void){ /* referme l'imbrication courant */
  imbrique *old;
  char **suit;
  switch(imbriqueactu->type){
   case MAIN:
    erreur("erreur interne: referme_imbrique() au top-niveau");
   case IF:
    break; /* rien de spécial à libérer */
   case FOR:
    suit=imbriqueactu->info.pourfor.liste;
    while (*suit){
      free(*suit);
      suit+=1;
    }
    free(imbriqueactu->info.pourfor.liste);
    break;
   case WHILE:
    free(imbriqueactu->info.pourwhile.condition);
    break;
   case INCLUDE:
    suit=imbriqueactu->info.pourinclude.liste;
    while (*suit){
      free(*suit);
      suit+=1;
    }
    affiche=imbriqueactu->info.pourinclude.affiche;
    free(imbriqueactu->info.pourinclude.liste);
    break;
   default: erreur("erreur interne: referme_imbrique: type non géré");
  }
  old=imbriqueactu->precedent;
  free(imbriqueactu);
  imbriqueactu=old;
}

void ouvre_imbrique(void){ /* operations génériques pour tous les types */
  imbrique *imbriquenew;
  imbriquenew=monalloc(sizeof(imbrique));
  imbriquenew->precedent=imbriqueactu;
  imbriqueactu=imbriquenew;
}
