Diff for /rpl/src/gestion_variables_statiques.c between versions 1.36 and 1.37

version 1.36, 2012/10/01 11:05:02 version 1.37, 2012/10/04 15:21:26
Line 25 Line 25
   
 /*  /*
 ================================================================================  ================================================================================
   Routine de création d'une nouvelle variable statique    Routine d'ajout d'un bouchon dans la liste des variables statiques
 ================================================================================  ================================================================================
   Entrée :    Entrée :
 --------------------------------------------------------------------------------  --------------------------------------------------------------------------------
Line 35 Line 35
 ================================================================================  ================================================================================
 */  */
   
   // Routine ajoutant à la liste des variables statiques créées un 'bouchon'
   // qui est un enregistrement dont la variable est NULL. Cela permet
   // d'effacer les variables statiques créées dans une expression évaluées car,
   // l'adresse de ces variables changeant à chaque évaluation, elles ne sont
   // pas utilisables et constituent une fuite de mémoire
   
 logical1  logical1
 creation_variable_statique(struct_processus *s_etat_processus,  ajout_bouchon_variable_statique(struct_processus *s_etat_processus)
         struct_variable_statique *s_variable)  
 {  {
     struct_variable_statique            *s_nouvelle_base;      struct_liste_variables_statiques    *l_tete_liste;
   
     long                                i;      l_tete_liste = (*s_etat_processus).l_liste_variables_statiques;
       
       if (((*s_etat_processus).l_liste_variables_statiques =
               malloc(sizeof(struct_liste_variables_statiques))) == NULL)
       {
           (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return(d_erreur);
       }
   
     (*s_etat_processus).nombre_variables_statiques++;      (*(*s_etat_processus).l_liste_variables_statiques).variable = NULL;
       (*(*s_etat_processus).l_liste_variables_statiques).suivant = l_tete_liste;
       (*(*s_etat_processus).l_liste_variables_statiques).precedent = NULL;
       (*l_tete_liste).precedent = (*s_etat_processus).l_liste_variables_statiques;
   
     if ((*s_etat_processus).nombre_variables_statiques > (*s_etat_processus)      return(d_absence_erreur);
             .nombre_variables_statiques_allouees)  }
     {  
         // La nouvelle variable statique ne tient pas dans la table courante.  
         // Il convient donc d'en augmenter la taille.  
   
         if ((*s_etat_processus).nombre_variables_statiques_allouees == 0)  
         {  
             (*s_etat_processus).nombre_variables_statiques_allouees =  
                     (*s_etat_processus).nombre_variables_statiques;  
         }  
         else  
         {  
             while((*s_etat_processus).nombre_variables_statiques >  
                     (*s_etat_processus).nombre_variables_statiques_allouees)  
             {  
                 (*s_etat_processus).nombre_variables_statiques_allouees *= 2;  
             }  
         }  
   
         if ((s_nouvelle_base = realloc((*s_etat_processus)  /*
                 .s_liste_variables_statiques, (*s_etat_processus)  ================================================================================
                 .nombre_variables_statiques_allouees *    Routine de retrait des variables statiques
                 sizeof(struct_variable_statique))) == NULL)  ================================================================================
     Entrée :
   --------------------------------------------------------------------------------
     Sortie :
   --------------------------------------------------------------------------------
     Effets de bords : néant
   ================================================================================
   */
   
   // Cette routine libère toutes les variables statiques jusqu'au prochain
   // bouchon ou jusqu'à la fin de la liste si aucun bouchon n'est rencontré.
   
   logical1
   retrait_variables_statiques(struct_processus *s_etat_processus)
   {
       unsigned char                       registre_mode_execution;
   
       registre_mode_execution = (*s_etat_processus).mode_execution_programme;
   
       while((*s_etat_processus).l_liste_variables_statiques != NULL)
       {
           (*s_etat_processus).mode_execution_programme =
                   ((*(*(*s_etat_processus).l_liste_variables_statiques)
                   .variable).origine == 'P') ? 'Y' : 'N';
   
           if ((*(*s_etat_processus).l_liste_variables_statiques).variable == NULL)
           {
               // On vient de tomber sur un bouchon...
               (*s_etat_processus).l_liste_variables_statiques =
                       (*(*s_etat_processus).l_liste_variables_statiques).suivant;
               free((*(*s_etat_processus).l_liste_variables_statiques).precedent);
               (*(*s_etat_processus).l_liste_variables_statiques).precedent = NULL;
               break;
           }
   
           if (retrait_variable_statique(s_etat_processus, (*(*(*s_etat_processus)
                   .l_liste_variables_statiques).variable).nom,
                   (*(*(*s_etat_processus).l_liste_variables_statiques).variable)
                   .variable_statique) == d_erreur)
         {          {
             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;              (*s_etat_processus).mode_execution_programme =
             (*s_etat_processus).nombre_variables_statiques--;                      registre_mode_execution;
             return(d_erreur);              return(d_erreur);
         }          }
   
         (*s_etat_processus).s_liste_variables_statiques = s_nouvelle_base;  
     }      }
   
     /*      (*s_etat_processus).mode_execution_programme = registre_mode_execution;
      * Positionnement de la variable statique au bon endroit      return(d_absence_erreur);
      */  }
   
   
   /*
   ================================================================================
     Routine de création d'une nouvelle variable statique
   ================================================================================
     Entrée :
   --------------------------------------------------------------------------------
     Sortie :
   --------------------------------------------------------------------------------
     Effets de bords : néant
   ================================================================================
   */
   
   logical1
   creation_variable_statique(struct_processus *s_etat_processus,
           struct_variable_statique *s_variable)
   {
       struct_arbre_variables                  *l_variable_courante;
   
       struct_liste_variables_statiques        *l_nouvel_element;
   
       unsigned char                           *ptr;
   
     // Nous avons (*s_etat_processus).nombre_variables_statiques - 1 variables      // Ajout de la variable en tête de la liste des variables statiques
     // dans la table qui sera balayée de la fin vers le début.  
   
     if ((*s_etat_processus).nombre_variables_statiques == 1)      if ((l_nouvel_element = malloc(sizeof(struct_liste_variables_statiques)))
               == NULL)
     {      {
         (*s_etat_processus).s_liste_variables_statiques[0] = (*s_variable);          (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return(d_erreur);
     }      }
     else  
       if (((*l_nouvel_element).variable = malloc(sizeof(
               struct_variable_statique))) == NULL)
     {      {
         for(i = (*s_etat_processus).nombre_variables_statiques - 2; i >= 0; i--)          (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
         {          return(d_erreur);
             if (strcmp((*s_variable).nom,      }
                     (*s_etat_processus).s_liste_variables_statiques[i].nom) < 0)  
             {  
                 (*s_etat_processus).s_liste_variables_statiques[i + 1] =  
                         (*s_etat_processus).s_liste_variables_statiques[i];  
             }  
             else  
             {  
                 break;  
             }  
         }  
   
         (*s_etat_processus).s_liste_variables_statiques[i + 1] = (*s_variable);      (*(*l_nouvel_element).variable) = (*s_variable);
       (*l_nouvel_element).suivant = (*s_etat_processus)
               .l_liste_variables_statiques;
       (*(*s_etat_processus).l_liste_variables_statiques).precedent
               = l_nouvel_element;
       (*l_nouvel_element).precedent = NULL;
       (*s_etat_processus).l_liste_variables_statiques = l_nouvel_element;
   
       // Ajout de la variable à la feuille statique de l'arbre des variables
   
       BUG((*s_etat_processus).s_arbre_variables == NULL,
               uprintf("(*s_etat_processus).s_arbre_variables=NULL\n"));
   
       l_variable_courante = (*s_etat_processus).s_arbre_variables;
       ptr = (*s_variable).nom;
   
       while((*ptr) != d_code_fin_chaine)
       {
           BUG((*s_etat_processus).pointeurs_caracteres_variables[*ptr] < 0,
                   uprintf("Variable=\"%s\", (*ptr)='%c'\n", (*s_variable).nom,
                   *ptr));
   
           // La feuille doit préexister car la variable statique est toujours
           // créée depuis une variable locale.
   
           BUG((*l_variable_courante).noeuds[(*s_etat_processus)
                   .pointeurs_caracteres_variables[*ptr]] == NULL,
                   uprintf("Variable=\"%s\", (*ptr)='%c', nullified folder\n"));
   
           l_variable_courante = (*l_variable_courante).noeuds
                   [(*s_etat_processus).pointeurs_caracteres_variables[*ptr]];
           ptr++;
     }      }
   
     return d_absence_erreur;      if ((l_nouvel_element = malloc(sizeof(struct_liste_variables_statiques)))
               == NULL)
       {
           (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return(d_erreur);
       }
   
       // Dans la feuille statique de l'arbre des variables, on ne balaie
       // les variables que dans l'ordre. Le champ 'reference' est alors utilisé
       // pour sauvegarder une référence vers la liste des variables statiques
       // pour pouvoir purger l'élément en cas de besoin.
   
       (*l_nouvel_element).suivant = (*l_variable_courante).feuille_statique;
       (*l_nouvel_element).precedent = NULL;
       (*(*l_nouvel_element).suivant).precedent = l_nouvel_element;
   
       (*l_nouvel_element).reference =
               (*s_etat_processus).l_liste_variables_statiques;
       (*l_nouvel_element).variable = (*(*s_etat_processus)
               .l_liste_variables_statiques).variable;
       (*l_variable_courante).feuille_statique = l_nouvel_element;
       return(d_absence_erreur);
 }  }
   
   
Line 128  logical1 Line 231  logical1
 retrait_variable_statique(struct_processus *s_etat_processus,  retrait_variable_statique(struct_processus *s_etat_processus,
         unsigned char *nom_variable, union_position_variable position)          unsigned char *nom_variable, union_position_variable position)
 {  {
     struct_variable_statique        *s_nouvelle_base;      struct_liste_variables_statiques        *l_element_a_supprimer;
       struct_liste_variables_statiques        *l_element_liste_a_supprimer;
     logical1                        erreur;  
   
     unsigned long                   position_courante;      logical1                                erreur;
     unsigned long                   position_supprimee;  
   
     if (recherche_variable_statique(s_etat_processus, nom_variable,      if ((l_element_a_supprimer = recherche_variable_statique(s_etat_processus,
             position, ((*s_etat_processus).mode_execution_programme == 'Y')              nom_variable, position, ((*s_etat_processus)
             ? 'P' : 'E') == d_vrai)              .mode_execution_programme == 'Y') ? 'P' : 'E')) != NULL)
     {      {
         if ((*s_etat_processus).nombre_variables_statiques <          // (*s_etat_processus).pointeur_variable_statique_courante
                 ((*s_etat_processus).nombre_variables_statiques_allouees / 2))          // pointe sur la variable à éliminer. Cette variable est celle qui
         {          // est présente dans l'une des feuilles statiques de l'arbre des
             (*s_etat_processus).nombre_variables_statiques_allouees /= 2;          // variables.
   
             if ((s_nouvelle_base =          l_element_liste_a_supprimer = (*l_element_a_supprimer).reference;
                     realloc((*s_etat_processus).s_liste_variables_statiques,  
                     (*s_etat_processus).nombre_variables_statiques_allouees *          // Suppression de la liste des variables statiques
                     sizeof(struct_variable_statique))) == NULL)  
             {          if ((*l_element_liste_a_supprimer).precedent != NULL)
                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;          {
                 return(d_erreur);              (*(*l_element_liste_a_supprimer).precedent).suivant =
             }                      (*l_element_liste_a_supprimer).suivant;
           }
           else
           {
               (*(*l_element_liste_a_supprimer).suivant).precedent = NULL;
           }
   
             (*s_etat_processus).s_liste_variables_statiques = s_nouvelle_base;          if ((*l_element_liste_a_supprimer).suivant != NULL)
           {
               (*(*l_element_liste_a_supprimer).suivant).precedent =
                       (*l_element_liste_a_supprimer).precedent;
           }
           else
           {
               (*(*l_element_liste_a_supprimer).precedent).suivant = NULL;
         }          }
   
         position_supprimee = (*s_etat_processus)          free(l_element_liste_a_supprimer);
                 .position_variable_statique_courante;  
   
         liberation(s_etat_processus, (*s_etat_processus)          // Suppression depuis la feuille statique. Le champ 'precedent' ne sert
                 .s_liste_variables_statiques[position_supprimee].objet);          // pas car la liste est simplement chaînée.
         free((*s_etat_processus).s_liste_variables_statiques  
                 [position_supprimee].nom);  
   
         (*s_etat_processus).nombre_variables_statiques--;          if ((*l_element_a_supprimer).precedent != NULL)
           {
               (*(*l_element_a_supprimer).precedent).suivant =
                       (*l_element_a_supprimer).suivant;
           }
           else
           {
               (*(*l_element_a_supprimer).suivant).precedent = NULL;
           }
   
         for(position_courante = position_supprimee; position_courante <          if ((*l_element_a_supprimer).suivant != NULL)
                 (*s_etat_processus).nombre_variables_statiques;          {
                 position_courante++)              (*(*l_element_a_supprimer).suivant).precedent =
                       (*l_element_a_supprimer).precedent;
           }
           else
         {          {
             (*s_etat_processus).s_liste_variables_statiques[position_courante]              (*(*l_element_a_supprimer).precedent).suivant = NULL;
                     = (*s_etat_processus).s_liste_variables_statiques  
                     [position_courante + 1];  
         }          }
   
           liberation(s_etat_processus, (*(*l_element_a_supprimer).variable)
                   .objet);
           free((*(*l_element_a_supprimer).variable).nom);
           free((*l_element_a_supprimer).variable);
           free(l_element_a_supprimer);
   
         erreur = d_absence_erreur;          erreur = d_absence_erreur;
     }      }
     else      else
Line 199  retrait_variable_statique(struct_process Line 324  retrait_variable_statique(struct_process
 ================================================================================  ================================================================================
 */  */
   
 logical1  struct_liste_variables_statiques *
 recherche_variable_statique(struct_processus *s_etat_processus,  recherche_variable_statique(struct_processus *s_etat_processus,
         unsigned char *nom_variable, union_position_variable position,          unsigned char *nom_variable, union_position_variable position,
         unsigned char origine)          unsigned char origine)
 {  {
     logical1                    existence_variable;      int                                 pointeur;
   
     long                        difference;      struct_arbre_variables              *l_variable_courante;
     long                        difference_inferieure;      struct_liste_variables_statiques    *l_element_courant;
     long                        difference_superieure;  
   
     unsigned long               borne_inferieure;  
     unsigned long               borne_superieure;  
     unsigned long               moyenne;  
     unsigned long               nombre_iterations_maximal;  
     unsigned long               ordre_iteration;  
   
     if ((*s_etat_processus).nombre_variables_statiques == 0)      unsigned char                       *ptr;
     {  
         (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;  
         return d_faux;  
     }  
   
     ordre_iteration = 0;  
     nombre_iterations_maximal = ((unsigned long)  
             (log((*s_etat_processus).nombre_variables_statiques) / log(2))) + 2;  
   
     borne_inferieure = 0;      l_variable_courante = (*s_etat_processus).s_arbre_variables;
     borne_superieure = (*s_etat_processus).nombre_variables_statiques - 1;      ptr = nom_variable;
   
     do      while((*ptr) != d_code_fin_chaine)
     {      {
         moyenne = (borne_inferieure + borne_superieure) / 2;          pointeur = (*s_etat_processus).pointeurs_caracteres_variables[*ptr];
         ordre_iteration++;  
   
         if ((2 * ((unsigned long) ((borne_inferieure + borne_superieure) / 2)))          if (pointeur < 0)
                 == (borne_inferieure + borne_superieure))  
         {          {
             difference = strcmp(nom_variable,              // Caractère hors de l'alphabet des variables
                     ((*s_etat_processus).s_liste_variables_statiques)  
                     [moyenne].nom);  
   
             if (difference != 0)              (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
             {              return(NULL);
                 if (difference > 0)  
                 {  
                     borne_inferieure = moyenne;  
                 }  
                 else  
                 {  
                     borne_superieure = moyenne;  
                 }  
             }  
         }          }
         else  
         {  
             difference_inferieure = strcmp(nom_variable,  
                     ((*s_etat_processus).s_liste_variables_statiques)  
                     [moyenne].nom);  
             difference_superieure = strcmp(nom_variable,  
                     ((*s_etat_processus).s_liste_variables_statiques)  
                     [moyenne + 1].nom);  
   
             if (difference_inferieure == 0)          if ((*l_variable_courante).noeuds[pointeur] == NULL)
             {          {
                 difference = 0;              // Le chemin de la variable candidate n'existe pas.
             }              (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
             else if (difference_superieure == 0)              return(NULL);
             {  
                 difference = 0;  
                 moyenne++;  
             }  
             else  
             {  
                 difference = difference_inferieure;  
   
                 if (difference > 0)  
                 {  
                     borne_inferieure = moyenne;  
                 }  
                 else  
                 {  
                     borne_superieure = moyenne;  
                 }  
             }  
         }          }
     } while((difference != 0) &&  
             (ordre_iteration <= nombre_iterations_maximal));  
   
     if (ordre_iteration > nombre_iterations_maximal)          l_variable_courante = (*l_variable_courante).noeuds[pointeur];
     {          ptr++;
         existence_variable = d_faux;  
         (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;  
     }      }
     else  
       if ((*l_variable_courante).feuille_statique != NULL)
     {      {
         // Reste à rechercher la variable déclarée à la position 'position'...          // Il existe au moins une variable statique du nom requis.
   
         if (((*s_etat_processus).s_liste_variables_statiques)[moyenne]          l_element_courant = (*l_variable_courante).feuille_statique;
                 .origine == 'P')  
         {  
             if ((((*s_etat_processus).s_liste_variables_statiques)[moyenne]  
                     .variable_statique.adresse == position.adresse) &&  
                     (((*s_etat_processus).s_liste_variables_statiques)[moyenne]  
                     .origine == origine))  
             {  
                 existence_variable = d_vrai;  
             }  
             else  
             {  
                 existence_variable = d_faux;  
             }  
         }  
         else  
         {  
             if ((((*s_etat_processus).s_liste_variables_statiques)[moyenne]  
                     .variable_statique.pointeur == position.pointeur) &&  
                     (((*s_etat_processus).s_liste_variables_statiques)[moyenne]  
                     .origine == origine))  
             {  
                 existence_variable = d_vrai;  
             }  
             else  
             {  
                 existence_variable = d_faux;  
             }  
         }  
   
         if (existence_variable == d_faux)          while(l_element_courant != NULL)
         {          {
             // On rembobine.              if ((*(*l_element_courant).variable).origine == 'P')
   
             if (moyenne > 0)  
             {              {
                 while(strcmp(nom_variable, ((*s_etat_processus)                  if (((*(*l_element_courant).variable).variable_statique.adresse
                         .s_liste_variables_statiques)[moyenne - 1].nom) == 0)                          == position.adresse) &&
                           ((*(*l_element_courant).variable).origine == origine))
                 {                  {
                     moyenne--;                      (*s_etat_processus).pointeur_variable_statique_courante
                               =   (*l_element_courant).variable;
                     if (moyenne == 0)                      return(l_element_courant);
                     {  
                         break;  
                     }  
                 }                  }
             }              }
               else
             // Un petit test pour voir si le premier élément du tableau  
             // peut correspondre au critère de recherche.  
   
             existence_variable = d_faux;  
   
             if (strcmp(((*s_etat_processus).s_liste_variables_statiques)  
                     [moyenne].nom, nom_variable) == 0)  
             {  
                 if (((*s_etat_processus).s_liste_variables_statiques)  
                         [moyenne].origine == 'P')  
                 {  
                     if ((((*s_etat_processus).s_liste_variables_statiques)  
                             [moyenne].variable_statique.adresse  
                             == position.adresse) &&  
                             (((*s_etat_processus).s_liste_variables_statiques)  
                             [moyenne].origine == origine))  
                     {  
                         existence_variable = d_vrai;  
                     }  
                 }  
                 else  
                 {  
                     if ((((*s_etat_processus).s_liste_variables_statiques)  
                             [moyenne].variable_statique.pointeur  
                             == position.pointeur) &&  
                             (((*s_etat_processus).s_liste_variables_statiques)  
                             [moyenne].origine == origine))  
                     {  
                         existence_variable = d_vrai;  
                     }  
                 }  
             }  
   
             // Puis on balaye dans le sens croissant.  
   
             if (((moyenne + 1) < (*s_etat_processus)  
                     .nombre_variables_statiques) &&  
                     (existence_variable == d_faux))  
             {              {
                 while(strcmp(((*s_etat_processus)                  if (((*(*l_element_courant).variable).variable_statique.pointeur
                         .s_liste_variables_statiques)[moyenne + 1].nom,                          == position.pointeur) &&
                         nom_variable) == 0)                          ((*(*l_element_courant).variable).origine == origine))
                 {                  {
                     moyenne++;                      (*s_etat_processus).pointeur_variable_statique_courante
                               =   (*l_element_courant).variable;
                     if (((*s_etat_processus).s_liste_variables_statiques)                      return(l_element_courant);
                             [moyenne].origine == 'P')  
                     {  
                         if ((((*s_etat_processus).s_liste_variables_statiques)  
                                 [moyenne].variable_statique.adresse ==  
                                 position.adresse) && (((*s_etat_processus)  
                                 .s_liste_variables_statiques)  
                                 [moyenne].origine == origine))  
                         {  
                             existence_variable = d_vrai;  
                             break;  
                         }  
                     }  
                     else  
                     {  
                         if ((((*s_etat_processus).s_liste_variables_statiques)  
                                 [moyenne].variable_statique.pointeur ==  
                                 position.pointeur) && (((*s_etat_processus)  
                                 .s_liste_variables_statiques)  
                                 [moyenne].origine == origine))  
                         {  
                             existence_variable = d_vrai;  
                             break;  
                         }  
                     }  
   
                     if ((moyenne + 1) >= (*s_etat_processus)  
                             .nombre_variables_statiques)  
                     {  
                         break;  
                     }  
                 }                  }
             }              }
         }          }
   
         (*s_etat_processus).position_variable_statique_courante = moyenne;  
     }      }
   
     return existence_variable;      (*s_etat_processus).pointeur_variable_statique_courante = NULL;
       return(NULL);
 }  }
   
 // vim: ts=4  // vim: ts=4

Removed from v.1.36  
changed lines
  Added in v.1.37


CVSweb interface <joel.bertrand@systella.fr>