Diff for /rpl/src/gestion_variables.c between versions 1.19 and 1.108

version 1.19, 2011/01/03 12:08:03 version 1.108, 2020/01/10 11:15:43
Line 1 Line 1
 /*  /*
 ================================================================================  ================================================================================
   RPL/2 (R) version 4.0.20    RPL/2 (R) version 4.1.32
   Copyright (C) 1989-2011 Dr. BERTRAND Joël    Copyright (C) 1989-2020 Dr. BERTRAND Joël
   
   This file is part of RPL/2.    This file is part of RPL/2.
   
Line 25 Line 25
   
 /*  /*
 ================================================================================  ================================================================================
     Fonction de debug
   ================================================================================
     Entrée :
   --------------------------------------------------------------------------------
     Sortie :
   --------------------------------------------------------------------------------
     Effets de bords : néant
   ================================================================================
   */
   
   static void
   liste_variables_par_niveaux(struct_processus *s_etat_processus)
   {
       int                     c;
   
       logical1                fin;
   
       struct_liste_variables  *l;
   
       struct_liste_chainee    *e;
   
       printf("=========================================================="
               "======================\n");
       printf("  Liste des variables par niveaux\n");
       printf("=========================================================="
               "======================\n");
   
       if ((*s_etat_processus).l_liste_variables_par_niveau == NULL)
       {
           printf("=========================================================="
                   "======================\n");
           return;
       }
   
       printf("Backward\n");
       l = (*s_etat_processus).l_liste_variables_par_niveau;
       c = 0;
       fin = d_faux;
   
       do
       {
           l = l->precedent;
           e = l->liste;
   
           while(e != NULL)
           {
               printf("%s (%p->%p, %d) ", ((struct_variable *) e->donnee)->nom,
                       e, e->donnee, ((struct_variable *) e->donnee)->niveau);
               e = e->suivant;
               c++;
               if (c > 100)
               {
                   fin = d_vrai;
                   break;
               }
           }
   
           printf("\n");
   
       } while(l != (*s_etat_processus).l_liste_variables_par_niveau);
   
       printf("Forward\n");
       l = (*s_etat_processus).l_liste_variables_par_niveau;
       c = 0;
   
       do
       {
           e = l->liste;
   
           while(e != NULL)
           {
               printf("%s (%p->%p, %d) ", ((struct_variable *) e->donnee)->nom,
                       e, e->donnee, ((struct_variable *) e->donnee)->niveau);
               e = e->suivant;
               c++;
               if (c > 100) exit(0);
           }
   
           printf("\n");
   
           l = l->suivant;
       } while(l != (*s_etat_processus).l_liste_variables_par_niveau);
   
       printf("=========================================================="
               "======================\n");
   
       if (fin == d_vrai) exit(0);
   
       return;
   }
   
   static void
   liste_variables_tas(struct_processus *s_etat_processus,
           struct_arbre_variables *arbre)
   {
       int                     c;
       int                     i;
   
       logical1                fin;
   
       struct_liste_variables  *l;
   
       fin = d_faux;
   
       if (arbre == NULL)
       {
           return;
       }
   
       printf(">>> Position :                  %d\n",
               (*arbre).indice_tableau_pere);
       printf(">>> Nombre de noeuds utilisés : %u\n",
               (*arbre).noeuds_utilises);
       printf(">>> Noeuds fils : ");
   
       for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
       {
           if ((*arbre).noeuds[i] != NULL)
           {
               printf("%d ", i);
           }
       }
   
       printf("\b\n");
   
       if ((*arbre).feuille != NULL)
       {
           printf("Feuille %p [%d]\n", (*arbre).feuille, (*arbre).noeuds_utilises);
   
           printf("  Backward\n");
   
           l = (*arbre).feuille;
           c = 0;
           fin = d_faux;
   
           do
           {
               l = l->precedent;
               c++;
               if (c > 100)
               {
                   fin = d_vrai;
                   break;
               }
               printf("    %s (%p, %d)\n", l->variable->nom, l->variable,
                       l->variable->niveau);
           } while((*arbre).feuille != l);
   
           printf("  Forward\n");
   
           l = (*arbre).feuille;
           c = 0;
   
           do
           {
               c++;
               if (c > 100) exit(0);
               printf("    %s (%p, %d)\n", l->variable->nom, l->variable,
                       l->variable->niveau);
               l = l->suivant;
           } while((*arbre).feuille != l);
       }
   
       printf("----------------------------------------------------------"
               "----------------------\n");
   
       for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
       {
           if ((*arbre).noeuds[i] != NULL)
           {
   
               liste_variables_tas(s_etat_processus, (*arbre).noeuds[i]);
           }
       }
   
       if (fin == d_vrai) exit(0);
   
       return;
   }
   
   
   static void
   liste_variables_par_feuilles(struct_processus *s_etat_processus)
   {
       printf("=========================================================="
               "======================\n");
       printf("  Liste des variables sur le tas\n");
       printf("=========================================================="
               "======================\n");
   
       liste_variables_tas(s_etat_processus,
               (*s_etat_processus).s_arbre_variables);
   
       printf("=========================================================="
               "======================\n");
   
       return;
   }
   
   
   /*
   ================================================================================
     Routine de gestion du cache mémoire sur l'arbre des variables
   ================================================================================
     Entrée :
   --------------------------------------------------------------------------------
     Sortie :
   --------------------------------------------------------------------------------
     Effets de bords : néant
   ================================================================================
   */
   
   struct_arbre_variables *
   allocation_noeud(struct_processus *s_etat_processus)
   {
       struct_arbre_variables          *objet;
   
       if ((*s_etat_processus).pointeur_variables_noeud > 0)
       {
           objet = (*s_etat_processus).variables_noeud
                   [--(*s_etat_processus).pointeur_variables_noeud];
       }
       else
       {
           objet = malloc(sizeof(struct_arbre_variables));
       }
   
       return(objet);
   }
   
   static inline void
   liberation_noeud(struct_processus *s_etat_processus,
           struct_arbre_variables *objet)
   {
       if ((*s_etat_processus).pointeur_variables_noeud < TAILLE_CACHE)
       {
           (*s_etat_processus).variables_noeud
                   [(*s_etat_processus).pointeur_variables_noeud++] = objet;
       }
       else
       {
           free(objet);
       }
   
       return;
   }
   
   struct_arbre_variables **
   allocation_tableau_noeuds(struct_processus *s_etat_processus)
   {
       struct_arbre_variables          **objet;
   
       if ((*s_etat_processus).pointeur_variables_tableau_noeuds > 0)
       {
           objet = (*s_etat_processus).variables_tableau_noeuds
                   [--(*s_etat_processus).pointeur_variables_tableau_noeuds];
       }
       else
       {
           objet = malloc(((size_t) (*s_etat_processus)
                   .nombre_caracteres_variables)
                   * sizeof(struct_arbre_variables *));
       }
   
       return(objet);
   }
   
   static inline void
   liberation_tableau_noeuds(struct_processus *s_etat_processus,
           struct_arbre_variables **objet)
   {
       if ((*s_etat_processus).pointeur_variables_tableau_noeuds < TAILLE_CACHE)
       {
           (*s_etat_processus).variables_tableau_noeuds
                   [(*s_etat_processus).pointeur_variables_tableau_noeuds++] =
                   objet;
       }
       else
       {
           free(objet);
       }
   
       return;
   }
   
   static inline struct_liste_variables *
   allocation_feuille(struct_processus *s_etat_processus)
   {
       struct_liste_variables          *objet;
   
       if ((*s_etat_processus).pointeur_variables_feuille > 0)
       {
           objet = (*s_etat_processus).variables_feuille
                   [--(*s_etat_processus).pointeur_variables_feuille];
       }
       else
       {
           objet = malloc(sizeof(struct_liste_variables));
       }
   
       return(objet);
   }
   
   static inline void
   liberation_feuille(struct_processus *s_etat_processus,
           struct_liste_variables *objet)
   {
       if ((*s_etat_processus).pointeur_variables_feuille < TAILLE_CACHE)
       {
           (*s_etat_processus).variables_feuille
                   [(*s_etat_processus).pointeur_variables_feuille++] = objet;
       }
       else
       {
           free(objet);
       }
   
       return;
   }
   
   static inline struct_variable *
   allocation_variable(struct_processus *s_etat_processus)
   {
       struct_variable             *objet;
   
       if ((*s_etat_processus).pointeur_variables_variable > 0)
       {
           objet = (*s_etat_processus).variables_variable
                   [--(*s_etat_processus).pointeur_variables_variable];
       }
       else
       {
           objet = malloc(sizeof(struct_variable));
       }
   
       return(objet);
   }
   
   static inline void
   liberation_variable(struct_processus *s_etat_processus,
           struct_variable *objet)
   {
       if ((*s_etat_processus).pointeur_variables_variable < TAILLE_CACHE)
       {
           (*s_etat_processus).variables_variable
                   [(*s_etat_processus).pointeur_variables_variable++] = objet;
       }
       else
       {
           free(objet);
       }
   
       return;
   }
   
   
   /*
   ================================================================================
   Routine de création d'une nouvelle variable    Routine de création d'une nouvelle variable
   Entrée : autorisation_creation_variable_statique vaut 'V' ou 'S'.  ================================================================================
   Dans le cas 'V', la variable est volatile.    Entrée : autorisation_creation_variable_statique vaut 'v' ou 's'.
   Dans le cas 'S', elle est statique.    dans le cas 'v', la variable est volatile.
   Entrée : autorisation_creation_variable_partagee vaut 'P' ou 'S'.    dans le cas 's', elle est statique.
   Dans le cas 'P', la variable est privée.    Entrée : autorisation_creation_variable_partagee vaut 'p' ou 's'.
   Dans le cas 'S', elle est partagée.    dans le cas 'p', la variable est privée.
     dans le cas 's', elle est partagée.
 --------------------------------------------------------------------------------  --------------------------------------------------------------------------------
   Sortie :    Sortie :
 --------------------------------------------------------------------------------  --------------------------------------------------------------------------------
Line 39 Line 398
 ================================================================================  ================================================================================
 */  */
   
 logical1  static logical1
 creation_variable(struct_processus *s_etat_processus,  ajout_variable(struct_processus *s_etat_processus, struct_variable *s_variable)
         struct_variable *s_variable,  
         unsigned char autorisation_creation_variable_statique,  
         unsigned char autorisation_creation_variable_partagee)  
 {  {
     logical1                presence;      int                         i;
   
       logical1                    niveau_acceptable;
   
       struct_liste_variables      *l_nouvelle_variable;
       struct_liste_variables      *l_variable_candidate;
   
       struct_arbre_variables      *l_variable_courante;
       struct_arbre_variables      *l_variable_precedente;
   
       struct_liste_chainee        *l_nouvel_element;
   
       unsigned char               *ptr;
   
       void                        *pointeur_variable_cree;
   
       if ((*s_etat_processus).s_arbre_variables == NULL)
       {
           if (((*s_etat_processus).s_arbre_variables =
                       allocation_noeud(s_etat_processus)) == NULL)
           {
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return(d_erreur);
           }
   
           (*(*s_etat_processus).s_arbre_variables).feuille = NULL;
           (*(*s_etat_processus).s_arbre_variables).feuille_statique = NULL;
           (*(*s_etat_processus).s_arbre_variables).noeuds_utilises = 0;
           (*(*s_etat_processus).s_arbre_variables).indice_tableau_pere = -1;
           (*(*s_etat_processus).s_arbre_variables).noeud_pere = NULL;
   
           if (((*(*s_etat_processus).s_arbre_variables).noeuds =
                   allocation_tableau_noeuds(s_etat_processus)) == NULL)
           {
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return(d_erreur);
           }
   
           for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
           {
               (*(*s_etat_processus).s_arbre_variables).noeuds[i] = NULL;
           }
       }
   
       l_variable_precedente = NULL;
       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));
   
           if ((*l_variable_courante).noeuds[(*s_etat_processus)
                   .pointeurs_caracteres_variables[*ptr]] == NULL)
           {
               // Le noeud n'existe pas encore, on le crée et on le marque
               // comme utilisé dans la structure parente.
   
               if (((*l_variable_courante).noeuds[(*s_etat_processus)
                       .pointeurs_caracteres_variables[*ptr]] =
                       allocation_noeud(s_etat_processus)) == NULL)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return(d_erreur);
               }
   
               (*l_variable_courante).noeuds_utilises++;
   
               // La feuille est par défaut vide et aucun élément du tableau noeuds
               // (les branches qui peuvent être issues de ce nouveau noeud)
               // n'est encore utilisée.
   
               (*(*l_variable_courante).noeuds[(*s_etat_processus)
                       .pointeurs_caracteres_variables[*ptr]]).feuille = NULL;
               (*(*l_variable_courante).noeuds[(*s_etat_processus)
                       .pointeurs_caracteres_variables[*ptr]]).feuille_statique
                       = NULL;
               (*(*l_variable_courante).noeuds[(*s_etat_processus)
                       .pointeurs_caracteres_variables[*ptr]]).noeuds_utilises = 0;
   
               // Le champ noeud_pere de la structure créée pointe sur
               // la structure parente et l'indice tableau_pere correspond à la
               // position réelle dans le tableau noeuds[] de la structure parente
               // du noeud courant. Cette valeur sera utilisée lors de la
               // destruction du noeud pour annuler le pointeur contenu dans
               // le tableau noeuds[] de la structure parente.
   
               (*(*l_variable_courante).noeuds[(*s_etat_processus)
                       .pointeurs_caracteres_variables[*ptr]]).noeud_pere =
                       l_variable_courante;
               (*(*l_variable_courante).noeuds[(*s_etat_processus)
                       .pointeurs_caracteres_variables[*ptr]])
                       .indice_tableau_pere = (*s_etat_processus)
                       .pointeurs_caracteres_variables[*ptr];
   
               // Allocation du tableau noeuds[] et initialisation à zéro de
               // tous les pointeurs.
   
               if (((*(*l_variable_courante).noeuds[(*s_etat_processus)
                       .pointeurs_caracteres_variables[*ptr]]).noeuds =
                       allocation_tableau_noeuds(s_etat_processus)) == NULL)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return(d_erreur);
               }
   
               for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
               {
                   (*(*l_variable_courante).noeuds[(*s_etat_processus)
                           .pointeurs_caracteres_variables[*ptr]]).noeuds[i]
                           = NULL;
               }
           }
   
           l_variable_precedente = l_variable_courante;
           l_variable_courante = (*l_variable_courante).noeuds
                   [(*s_etat_processus).pointeurs_caracteres_variables[*ptr]];
           ptr++;
       }
   
     long                    i;      if ((*l_variable_courante).feuille == NULL)
       {
           // Aucune variable de même nom préexiste. On alloue le premier
           // élément de la liste doublement chaînée contenant toutes les
           // variables de même nom. Cette liste boucle en premier lieu sur
           // elle-même.
   
     struct_variable         *s_nouvelle_base;          if (((*l_variable_courante).feuille = allocation_feuille(
                   s_etat_processus)) == NULL)
           {
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return(d_erreur);
           }
   
     (*s_etat_processus).nombre_variables++;          (*l_variable_courante).noeuds_utilises++;
   
     if ((*s_etat_processus).nombre_variables > (*s_etat_processus)          (*(*l_variable_courante).feuille).suivant =
             .nombre_variables_allouees)                  (*l_variable_courante).feuille;
           (*(*l_variable_courante).feuille).precedent =
                   (*l_variable_courante).feuille;
           (*(*l_variable_courante).feuille).noeud_pere = l_variable_precedente;
           (*(*l_variable_courante).feuille).noeud = l_variable_courante;
   
           // Allocation de la variable sur l'élément de la liste.
   
           if (((*(*l_variable_courante).feuille).variable =
                   allocation_variable(s_etat_processus)) == NULL)
           { 
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return(d_erreur);
           }
   
           (*((struct_variable *) (*(*l_variable_courante).feuille).variable)) =
                   (*s_variable);
           pointeur_variable_cree = (*(*l_variable_courante).feuille).variable;
       }
       else
     {      {
         // La nouvelle variable ne tient pas dans la table courante. Il          if ((l_nouvelle_variable = allocation_feuille(s_etat_processus))
         // faut donc en augmenter la taille.                  == NULL)
           {
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return(d_erreur);
           }
   
         if ((*s_etat_processus).nombre_variables_allouees == 0)          if ((*s_variable).niveau > 1)
         {          {
             (*s_etat_processus).nombre_variables_allouees =              // Cas d'une variable locale
                     (*s_etat_processus).nombre_variables;  
               // Si le niveau de la dernière variable de même nom est
               // supérieur au niveau de la variable locale que l'on veut
               // enregistrer dans la liste, cette liste est incohérente.
   
               BUG((*(*(*l_variable_courante).feuille).variable).niveau >=
                       (*s_variable).niveau,
                       uprintf("Variable=\"%s\"\n", (*s_variable).nom));
   
               // On ajoute la variable à la liste existante.
   
               (*l_nouvelle_variable).suivant = (*l_variable_courante).feuille;
               (*l_nouvelle_variable).precedent = (*(*l_variable_courante).feuille)
                       .precedent;
               (*l_nouvelle_variable).noeud_pere = l_variable_precedente;
               (*l_nouvelle_variable).noeud = l_variable_courante;
               (*(*(*l_variable_courante).feuille).precedent).suivant =
                       l_nouvelle_variable;
               (*(*l_variable_courante).feuille).precedent =
                       l_nouvelle_variable;
               (*l_variable_courante).feuille = l_nouvelle_variable;
   
               if (((*(*l_variable_courante).feuille).variable =
                       allocation_variable(s_etat_processus)) == NULL)
               { 
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return(d_erreur);
               }
   
               (*((struct_variable *) (*(*l_variable_courante).feuille).variable))
                       = (*s_variable);
               pointeur_variable_cree = (*(*l_variable_courante).feuille).variable;
         }          }
         else          else
         {          {
             while((*s_etat_processus).nombre_variables >              // Cas d'une variable globale (niveau 0 [définitions] ou 1
                     (*s_etat_processus).nombre_variables_allouees)              // [variables globales])
   
               l_variable_candidate = (*l_variable_courante).feuille;
   
               do
               {
                   // S'il y a déjà une variable de même niveau, la pile
                   // est incohérente.
   
                   BUG((*(*l_variable_candidate).variable).niveau ==
                           (*s_variable).niveau,
                           uprintf("Variable=\"%s\"\n", (*s_variable).nom));
   
                   l_variable_candidate = (*l_variable_candidate).precedent;
               } while((l_variable_candidate != (*l_variable_courante).feuille) &&
                       ((*(*l_variable_candidate).variable).niveau <= 1));
   
               BUG((*s_variable).niveau == 0,
                       uprintf("Attempt to create a level-0 variable!\n"));
   
               if ((*(*(*(*l_variable_courante).feuille).precedent).variable)
                       .niveau > 1)
               {
                   // La variable précédente est de niveau strictement supérieur
                   // à 1. Il ne peut donc y avoir aucune variable de niveau
                   // inférieur ou égal à 1 puisque la boucle est triée.
                   // On insère donc directement la variable en queue.
               }
               else
               {
                   // Le niveau de la variable précédente dans la boucle est
                   // inférieur ou égal à 1.
                   l_variable_candidate = (*(*l_variable_courante).feuille)
                           .precedent;
               }
   
               (*l_nouvelle_variable).suivant = l_variable_candidate;
               (*l_nouvelle_variable).precedent = (*l_variable_candidate)
                       .precedent;
               (*l_nouvelle_variable).noeud_pere = l_variable_precedente;
               (*l_nouvelle_variable).noeud = l_variable_courante;
               (*(*l_variable_candidate).precedent).suivant = l_nouvelle_variable;
               (*l_variable_candidate).precedent = l_nouvelle_variable;
   
               // Si la variable suivant la variable que l'on vient d'insérer
               // dans la boucle est de niveau 0, la variable insérée est par
               // construction de niveau 1 et il convient de modifier le
               // pointeur de feuille pointant sur l'élément de plus haut niveau
               // de la boucle.
   
               if ((*(*(*l_nouvelle_variable).precedent).variable).niveau == 0)
               {
                   (*(*l_nouvelle_variable).noeud).feuille = l_nouvelle_variable;
               }
   
               if (((*l_nouvelle_variable).variable =
                       allocation_variable(s_etat_processus)) == NULL)
               { 
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return(d_erreur);
               }
   
               (*(*l_nouvelle_variable).variable) = (*s_variable);
               pointeur_variable_cree = (*l_nouvelle_variable).variable;
           }
       }
   
       // Ajout de la variable nouvellement créée à la liste par niveaux.
       // Le pointeur contenu dans la structure de description du processus indique
       // toujours le plus haut niveau utilisé.
   
       if ((*s_etat_processus).l_liste_variables_par_niveau == NULL)
       {
           // Le niveau courant n'existe pas. Il est créé.
   
           if ((l_nouvelle_variable = allocation_feuille(s_etat_processus))
                   == NULL)
           {
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return(d_erreur);
           }
   
           (*l_nouvelle_variable).suivant = l_nouvelle_variable;
           (*l_nouvelle_variable).precedent = l_nouvelle_variable;
           (*l_nouvelle_variable).noeud_pere = NULL;
           (*l_nouvelle_variable).liste = NULL;
   
           (*s_etat_processus).l_liste_variables_par_niveau = l_nouvelle_variable;
   
           // Ajout de la variable en tête de la liste
   
           if ((l_nouvel_element = allocation_maillon(s_etat_processus)) == NULL)
           {
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return(d_erreur);
           }
   
           (*l_nouvel_element).suivant = (*(*s_etat_processus)
                   .l_liste_variables_par_niveau).liste;
           (*l_nouvel_element).donnee = pointeur_variable_cree;
           (*(*s_etat_processus).l_liste_variables_par_niveau).liste =
                   l_nouvel_element;
       }
       else if ((*s_variable).niveau > (*((struct_variable *)
               (*(*(*s_etat_processus).l_liste_variables_par_niveau).liste)
               .donnee)).niveau)
       {
           // Le niveau courant n'existe pas. Il est créé.
   
           if ((l_nouvelle_variable = allocation_feuille(s_etat_processus))
                   == NULL)
           {
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return(d_erreur);
           }
   
           (*l_nouvelle_variable).suivant = (*s_etat_processus)
                   .l_liste_variables_par_niveau;
           (*l_nouvelle_variable).precedent = (*(*s_etat_processus)
                   .l_liste_variables_par_niveau).precedent;
           (*l_nouvelle_variable).noeud_pere = NULL;
           (*l_nouvelle_variable).liste = NULL;
           (*(*(*s_etat_processus).l_liste_variables_par_niveau).precedent)
                   .suivant = l_nouvelle_variable;
           (*(*s_etat_processus).l_liste_variables_par_niveau)
                   .precedent = l_nouvelle_variable;
   
           (*s_etat_processus).l_liste_variables_par_niveau = l_nouvelle_variable;
   
           // Ajout de la variable en tête de la liste
   
           if ((l_nouvel_element = allocation_maillon(s_etat_processus)) == NULL)
           {
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return(d_erreur);
           }
   
           (*l_nouvel_element).suivant = (*(*s_etat_processus)
                   .l_liste_variables_par_niveau).liste;
           (*l_nouvel_element).donnee = pointeur_variable_cree;
           (*(*s_etat_processus).l_liste_variables_par_niveau).liste =
                   l_nouvel_element;
       }
       else if ((*s_variable).niveau <= 1)
       {
           // Création d'une variable de niveau 0 ou 1. Il convient de
           // chercher dans la liste si un niveau 0 ou 1 préexiste. Pour cela, on
           // regarde la position courante et les deux précédentes.
   
           l_variable_candidate = (*s_etat_processus).l_liste_variables_par_niveau;
           niveau_acceptable = d_faux;
   
           for(i = 0; i <= 2; i++)
           {
               if ((*l_variable_candidate).liste == NULL)
             {              {
                 (*s_etat_processus).nombre_variables_allouees *= 2;                  continue;
               }
   
               if ((*((struct_variable *) (*(*l_variable_candidate)
                       .liste).donnee)).niveau == (*s_variable).niveau)
               {
                   niveau_acceptable = d_vrai;
                   break;
             }              }
   
               l_variable_candidate = (*l_variable_candidate).precedent;
         }          }
   
         if ((s_nouvelle_base = realloc((*s_etat_processus).s_liste_variables,          if (niveau_acceptable == d_faux)
                 (*s_etat_processus).nombre_variables_allouees *          {
                 sizeof(struct_variable))) == NULL)              if ((l_nouvelle_variable = allocation_feuille(s_etat_processus))
                       == NULL)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return(d_erreur);
               }
   
               l_variable_candidate =
                       (*(*s_etat_processus).l_liste_variables_par_niveau)
                       .precedent;
   
               // On ne peut créer qu'une variable de niveau supérieur ou égal à
               // 1 lors de l'exécution normale d'un programme. Les variables
               // de niveau 0 sont créées à l'initialisation et relèvent du
               // cas précédent car il n'existe lors de leur création aucun
               // niveau non nul.
   
               BUG((*s_variable).niveau == 0,
                       uprintf("Attempt to create a level-0 variable!\n"));
   
               (*l_nouvelle_variable).suivant = l_variable_candidate;
               (*l_nouvelle_variable).precedent = (*l_variable_candidate)
                       .precedent;
               (*l_nouvelle_variable).noeud_pere = NULL;
               (*l_nouvelle_variable).liste = NULL;
               (*(*l_variable_candidate).precedent).suivant = l_nouvelle_variable;
               (*l_variable_candidate).precedent = l_nouvelle_variable;
   
               l_variable_candidate = l_nouvelle_variable;
           }
   
           // Ajout de la variable en tête de la liste l_variable_candidate.
   
           if ((l_nouvel_element = allocation_maillon(s_etat_processus)) == NULL)
           {
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return(d_erreur);
           }
   
           (*l_nouvel_element).suivant = (*l_variable_candidate).liste;
           (*l_nouvel_element).donnee = pointeur_variable_cree;
           (*l_variable_candidate).liste = l_nouvel_element;
       }
       else
       {
           // Ajout de la variable en tête de la liste
   
           if ((l_nouvel_element = allocation_maillon(s_etat_processus)) == NULL)
         {          {
             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;              (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
             (*s_etat_processus).nombre_variables--;  
             return(d_erreur);              return(d_erreur);
         }          }
   
         (*s_etat_processus).s_liste_variables = s_nouvelle_base;          (*l_nouvel_element).suivant = (*(*s_etat_processus)
                   .l_liste_variables_par_niveau).liste;
           (*l_nouvel_element).donnee = pointeur_variable_cree;
           (*(*s_etat_processus).l_liste_variables_par_niveau).liste =
                   l_nouvel_element;
     }      }
   
       return(d_absence_erreur);
   }
   
   
   logical1
   creation_variable(struct_processus *s_etat_processus,
           struct_variable *s_variable,
           unsigned char autorisation_creation_variable_statique,
           unsigned char autorisation_creation_variable_partagee)
   {
     if ((*s_etat_processus).mode_execution_programme == 'Y')      if ((*s_etat_processus).mode_execution_programme == 'Y')
     {      {
         (*s_variable).origine = 'P';          (*s_variable).origine = 'P';
Line 190  creation_variable(struct_processus *s_et Line 953  creation_variable(struct_processus *s_et
     }      }
   
     /*      /*
      * Positionnement de la variable au bon endroit       * Recherche de la feuille correspondante dans l'arbre des variables.
        * Si cette feuille n'existe pas, elle est créée.
      */       */
   
     // Nous avons (*s_etat_processus).nombre_variables - 1 variables dans la      if (ajout_variable(s_etat_processus, s_variable) == d_erreur)
     // table qui sera balayée de la fin vers le début.      {
           return(d_erreur);
       }
   
       return(d_absence_erreur);
   }
   
   
   /*
   ================================================================================
     Procédure de recherche d'une variable par son nom dans la base
   ================================================================================
     Entrée :
   --------------------------------------------------------------------------------
     Sortie :
   --------------------------------------------------------------------------------
     Effets de bord : néant
   ================================================================================
   */
   
   logical1
   recherche_variable(struct_processus *s_etat_processus,
           unsigned char *nom_variable)
   {
       int                         pointeur;
   
       struct_arbre_variables      *l_variable_courante;
       struct_liste_pile_systeme   *l_element_courant;
   
     if ((*s_etat_processus).nombre_variables == 1)      unsigned char               *ptr;
   
       integer8                    niveau_appel;
   
       if ((*s_etat_processus).s_arbre_variables == NULL)
     {      {
         (*s_etat_processus).s_liste_variables[0] = (*s_variable);          (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
           return(d_faux);
     }      }
     else  
       l_variable_courante = (*s_etat_processus).s_arbre_variables;
       ptr = nom_variable;
   
       while((*ptr) != d_code_fin_chaine)
     {      {
         for(i = (*s_etat_processus).nombre_variables - 2; i >= 0; i--)          pointeur = (*s_etat_processus).pointeurs_caracteres_variables[*ptr];
   
           if (pointeur < 0)
         {          {
             if (strcmp((*s_variable).nom,              // Caractère hors de l'alphabet des variables
                     (*s_etat_processus).s_liste_variables[i].nom) < 0)  
             {              (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
                 (*s_etat_processus).s_liste_variables[i + 1] =              return(d_faux);
                         (*s_etat_processus).s_liste_variables[i];          }
             }  
             else          if ((*l_variable_courante).noeuds[pointeur] == NULL)
           {
               // Le chemin de la variable candidate n'existe pas.
               (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
               return(d_faux);
           }
   
           l_variable_courante = (*l_variable_courante).noeuds[pointeur];
           ptr++;
       }
   
       if ((*l_variable_courante).feuille != NULL)
       {
           // Il existe une pile de variables de même nom. Le sommet de la
           // pile est la variable de niveau le plus haut.
   
           l_element_courant = (*s_etat_processus).l_base_pile_systeme;
   
           if (l_element_courant == NULL)
           {
               // Problème : la pile système est vide !
               (*s_etat_processus).erreur_systeme = d_es_pile_vide;
               return(d_faux);
           }
   
           while((*l_element_courant).retour_definition != 'Y')
           {
               l_element_courant = (*l_element_courant).suivant;
   
               if (l_element_courant == NULL)
             {              {
                 break;                  (*s_etat_processus).erreur_systeme = d_es_pile_vide;
                   return(d_faux);
             }              }
         }          }
   
         if ((*s_variable).niveau > 1)          niveau_appel = (*l_element_courant).niveau_courant;
   
           if (niveau_appel < (*(*(*l_variable_courante).feuille).variable).niveau)
         {          {
             // Cas d'une variable locale              // Une variable locale est accessible puisque créée dans la
             (*s_etat_processus).s_liste_variables[i + 1] = (*s_variable);              // fonction courante.
   
               (*s_etat_processus).pointeur_variable_courante =
                       (*(*l_variable_courante).feuille).variable;
               (*s_etat_processus).pointeur_feuille_courante =
                       (*l_variable_courante).feuille;
               return(d_vrai);
         }          }
         else          else
         {          {
             // Cas d'une variable globale              // Aucune variable locale n'est accessible depuis la fonction.
             presence = d_faux;              // Dans ce cas, on prend la variable de niveau le plus bas
               // si ce niveau est inférieur ou égal à 1 (variable globale
               // ou fonction définie par l'utilisateur). Si le niveau de la
               // plus ancienne variable est strictement supérieur à 1, il
               // s'agit d'une variable locale inaccessible.
   
               if ((*(*(*(*l_variable_courante).feuille).precedent).variable)
                       .niveau <= 1)
               {
                   (*s_etat_processus).pointeur_variable_courante =
                           (*(*(*l_variable_courante).feuille).precedent).variable;
                   (*s_etat_processus).pointeur_feuille_courante =
                           (*(*l_variable_courante).feuille).precedent;
   
                   // S'il existe une variable de niveau 0 et une seconde de
                   // niveau 1, la variable de niveau 0 (fonction) est masquée
                   // par celle de niveau 1.
   
                   if (((*(*(*(*l_variable_courante).feuille).precedent)
                           .variable).niveau == 0) && ((*(*(*(*
                           (*l_variable_courante).feuille).precedent).precedent)
                           .variable).niveau == 1))
                   {
                       (*s_etat_processus).pointeur_variable_courante =
                               (*(*(*(*l_variable_courante).feuille).precedent)
                               .precedent).variable;
                       (*s_etat_processus).pointeur_feuille_courante =
                               (*(*(*l_variable_courante).feuille).precedent)
                               .precedent;
                   }
   
                   return(d_vrai);
               }
           }
       }
   
       (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
       return(d_faux);
   }
   
   
   logical1
   recherche_variable_globale(struct_processus *s_etat_processus,
           unsigned char *nom)
   {
       logical1            presence_variable;
   
       presence_variable = recherche_variable(s_etat_processus, nom);
   
       if (presence_variable == d_vrai)
       {
           switch((*(*s_etat_processus).pointeur_variable_courante).niveau)
           {
               case 0:
               {
                   // La variable est une définition.
                   presence_variable = d_faux;
                   break;
               }
   
             for(; i >= 0; i--)              case 1:
             {              {
                 if ((strcmp((*s_variable).nom,                  break;
                         (*s_etat_processus).s_liste_variables[i].nom) == 0)              }
                         && ((*s_etat_processus).s_liste_variables[i].niveau  
                         != 0))              default:
               {
                   if ((*(*(*(*s_etat_processus).pointeur_feuille_courante)
                           .precedent).variable).niveau == 1)
                 {                  {
                     (*s_etat_processus).s_liste_variables[i + 1] =                      (*s_etat_processus).pointeur_feuille_courante =
                             (*s_etat_processus).s_liste_variables[i];                              (*(*s_etat_processus).pointeur_feuille_courante)
                               .precedent;
                       (*s_etat_processus).pointeur_variable_courante =
                               (*(*s_etat_processus).pointeur_feuille_courante)
                               .variable;
                   }
                   else if ((*(*(*(*(*s_etat_processus).pointeur_feuille_courante)
                           .precedent).precedent).variable).niveau == 1)
                   {
                       (*s_etat_processus).pointeur_feuille_courante =
                               (*(*(*s_etat_processus).pointeur_feuille_courante)
                               .precedent).precedent;
                       (*s_etat_processus).pointeur_variable_courante =
                               (*(*s_etat_processus).pointeur_feuille_courante)
                               .variable;
                 }                  }
                 else                  else
                 {                  {
                     presence = d_vrai;                      presence_variable = d_faux;
                     break;  
                 }                  }
             }  
   
             if (presence == d_faux)                  break;
             {  
                 (*s_etat_processus).s_liste_variables[0] = (*s_variable);  
             }  
             else  
             {  
                 (*s_etat_processus).s_liste_variables[i + 1] = (*s_variable);  
             }              }
         }          }
     }      }
   
     return(d_absence_erreur);      if (presence_variable == d_vrai)
       {
           if ((*(*s_etat_processus).pointeur_variable_courante).objet == NULL)
           {
               // La variable n'est pas globale, elle est partagée.
               presence_variable = d_faux;
               (*s_etat_processus).erreur_execution = d_ex_variable_partagee;
           }
       }
   
       return(presence_variable);
 }  }
   
   
Line 275  logical1 Line 1192  logical1
 retrait_variable(struct_processus *s_etat_processus,  retrait_variable(struct_processus *s_etat_processus,
         unsigned char *nom_variable, unsigned char type)          unsigned char *nom_variable, unsigned char type)
 {  {
     struct_variable     *s_nouvelle_base;      logical1                    erreur;
       logical1                    variable_supprimee;
   
       struct_arbre_variables      *s_arbre_a_supprimer;
       struct_arbre_variables      *s_arbre_courant;
   
       struct_liste_chainee        *l_element_courant;
       struct_liste_chainee        *l_element_precedent;
   
       struct_liste_variables      *variable_a_supprimer;
       struct_liste_variables      *variables_par_niveau;
   
     logical1            erreur;      integer8                    niveau;
   
     unsigned long       position_courante;      (*s_etat_processus).niveau_supprime = d_faux;
     unsigned long       position_supprimee;  
   
     if (recherche_variable(s_etat_processus, nom_variable) == d_vrai)      if (recherche_variable(s_etat_processus, nom_variable) == d_vrai)
     {      {
           // Une variable correspondant au nom recherché est accessible.
   
         if (type == 'G')          if (type == 'G')
         {          {
             if ((*s_etat_processus).position_variable_courante > 0)              if ((*(*s_etat_processus).pointeur_variable_courante).niveau > 1)
             {              {
                 while(strcmp((*s_etat_processus).s_liste_variables                  // La variable obtenue est une variable locale. il faut
                         [(*s_etat_processus).position_variable_courante]                  // s'assurer qu'il existe une variable de niveau 1 de même
                         .nom, nom_variable) == 0)                  // nom sur la feuille.
                 {  
                     (*s_etat_processus).position_variable_courante--;  
   
                     if ((*s_etat_processus).position_variable_courante >=                  if ((*(*(*(*s_etat_processus).pointeur_feuille_courante)
                             (*s_etat_processus).nombre_variables)                          .precedent).variable).niveau <= 1)
                   {
                       (*s_etat_processus).pointeur_feuille_courante =
                               (*(*s_etat_processus).pointeur_feuille_courante)
                               .precedent;
                       (*s_etat_processus).pointeur_variable_courante =
                               (*(*s_etat_processus).pointeur_feuille_courante)
                               .variable;
   
                       // Si la variable retournée est de niveau 0, on regarde
                       // un peu plus loin si une variable de niveau 1 existe.
   
                       if (((*(*(*s_etat_processus).pointeur_feuille_courante)
                               .variable).niveau == 0) &&
                               ((*(*(*(*s_etat_processus)
                               .pointeur_feuille_courante).precedent).variable)
                               .niveau == 1))
                     {                      {
                         erreur = d_erreur;                          (*s_etat_processus).pointeur_feuille_courante =
                         (*s_etat_processus).erreur_execution =                                  (*(*s_etat_processus).pointeur_feuille_courante)
                                 d_ex_variable_non_definie;                                  .precedent;
                         return erreur;                          (*s_etat_processus).pointeur_variable_courante =
                                   (*(*s_etat_processus).pointeur_feuille_courante)
                                   .variable;
                     }                      }
                 }                  }
                   else
                   {
                       // Aucune variable globale (niveau 1) n'existe.
   
                 (*s_etat_processus).position_variable_courante++;                      erreur = d_erreur;
             }                      (*s_etat_processus).erreur_execution =
                               d_ex_variable_non_definie;
             if ((*s_etat_processus).s_liste_variables                      return(erreur);
                     [(*s_etat_processus).position_variable_courante]                  }
                     .niveau != 1)  
             {  
                 erreur = d_erreur;  
                 (*s_etat_processus).erreur_execution =  
                         d_ex_variable_non_definie;  
                 return erreur;  
             }              }
   
             if ((*s_etat_processus).s_liste_variables              if ((*(*s_etat_processus).pointeur_variable_courante)
                     [(*s_etat_processus).position_variable_courante]  
                     .variable_verrouillee == d_vrai)                      .variable_verrouillee == d_vrai)
             {              {
                 erreur = d_erreur;                  erreur = d_erreur;
                 (*s_etat_processus).erreur_execution =                  (*s_etat_processus).erreur_execution =
                         d_ex_variable_verrouillee;                          d_ex_variable_verrouillee;
                 return erreur;                  return(erreur);
             }              }
         }          }
   
         if ((*s_etat_processus).nombre_variables <          // Suppression de la variable de la liste.
                 ((*s_etat_processus).nombre_variables_allouees / 2))          // Deux cas peuvent survenir :
           // 1/ les pointeurs sur la variable et la variable suivante
           // sont identiques et on supprime la variable ainsi que la feuille
           // associée ;
           // 2/ ces deux pointeurs sont différents et se contente de retirer
           // la structure décrivant la variable.
   
           if ((*s_etat_processus).pointeur_feuille_courante ==
                   (*(*s_etat_processus).pointeur_feuille_courante).suivant)
           {
               // Cas 1 :
               // On retire la variable du noeud en décrémentant le nombre
               // de feuilles de ce noeud. Si le nombre de feuilles du noeud
               // est nul, on retire les noeuds récursivement jusqu'à obtenir
               // un nombre non nul de feuilles utilisées (ou la racine des
               // variables).
   
               variable_a_supprimer = (*s_etat_processus)
                       .pointeur_feuille_courante;
               s_arbre_courant = (*variable_a_supprimer).noeud;
               BUG((*s_arbre_courant).noeuds_utilises == 0,
                       uprintf("Freed node !\n"));
               (*s_arbre_courant).noeuds_utilises--;
   
               (*((*(*variable_a_supprimer).noeud_pere).noeuds
                       [(*(*variable_a_supprimer).noeud).indice_tableau_pere]))
                       .feuille = NULL;
   
               while(((*s_arbre_courant).noeuds_utilises == 0) &&
                       ((*s_arbre_courant).feuille_statique == NULL))
               {
                   s_arbre_a_supprimer = s_arbre_courant;
                   s_arbre_courant = (*s_arbre_courant).noeud_pere;
   
                   if (s_arbre_courant == NULL)
                   {
                       liberation_tableau_noeuds(s_etat_processus,
                               (*s_arbre_a_supprimer).noeuds);
                       liberation_noeud(s_etat_processus, s_arbre_a_supprimer);
   
                       (*s_etat_processus).s_arbre_variables = NULL;
                       break;
                   }
   
                   // s_arbre_a_supprimer contient la structure de feuille qui
                   // vient d'être libérée. Il s'agit maintenant
                   // d'annuler le pointeur dans le tableau noeuds de la structure
                   // pointée par noeud_pere, soit s_arbre_courant.
   
                   BUG((*s_arbre_a_supprimer).indice_tableau_pere < 0,
                           uprintf("Invalid pointer !\n"));
                   (*s_arbre_courant).noeuds[(*s_arbre_a_supprimer)
                           .indice_tableau_pere] = NULL;
   
                   liberation_tableau_noeuds(s_etat_processus,
                           (*s_arbre_a_supprimer).noeuds);
                   liberation_noeud(s_etat_processus, s_arbre_a_supprimer);
   
                   BUG((*s_arbre_courant).noeuds_utilises == 0,
                           uprintf("Freed node !\n"));
                   (*s_arbre_courant).noeuds_utilises--;
               }
           }
           else
         {          {
             (*s_etat_processus).nombre_variables_allouees /= 2;              // Cas 2 :
               // On retire la variable de la liste.
   
               variable_a_supprimer = (*s_etat_processus)
                       .pointeur_feuille_courante;
   
             // (*s_etat_processus).nombre_variables est forcément              (*(*(*s_etat_processus).pointeur_feuille_courante).precedent)
             // supérieur à 1 (la décrémentation est postérieure). Ce test                      .suivant = (*(*s_etat_processus).pointeur_feuille_courante)
             // est vrai lorsque le nombre de variables allouées est                      .suivant;
             // strictement supérieur à 2.              (*(*(*s_etat_processus).pointeur_feuille_courante).suivant)
                       .precedent = (*(*s_etat_processus)
                       .pointeur_feuille_courante).precedent;
   
             if ((s_nouvelle_base =              // Mise à jour du pointeur dans l'arbre des variables. Cette
                     realloc((*s_etat_processus).s_liste_variables,              // mise à jour n'est nécessaire que dans le cas où la variable
                     (*s_etat_processus).nombre_variables_allouees *              // supprimée est en tête de la liste.
                     sizeof(struct_variable))) == NULL)  
               if (variable_a_supprimer == (*((*(*variable_a_supprimer).noeud_pere)
                       .noeuds[(*(*variable_a_supprimer).noeud)
                       .indice_tableau_pere])).feuille)
             {              {
                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;                  (*((*(*variable_a_supprimer).noeud_pere).noeuds
                 return(d_erreur);                          [(*(*variable_a_supprimer).noeud).indice_tableau_pere]))
                           .feuille = (*(*((*(*variable_a_supprimer).noeud_pere)
                           .noeuds[(*(*variable_a_supprimer).noeud)
                           .indice_tableau_pere])).feuille).suivant;
             }              }
   
             (*s_etat_processus).s_liste_variables = s_nouvelle_base;              (*s_etat_processus).pointeur_feuille_courante =
                       (*(*s_etat_processus).pointeur_feuille_courante).suivant;
               (*s_etat_processus).pointeur_variable_courante =
                       (*(*s_etat_processus).pointeur_feuille_courante).variable;
         }          }
   
         position_supprimee = (*s_etat_processus).position_variable_courante;          // Dans tous les cas, on retire la variable de la liste des variables
           // par niveau.
         liberation(s_etat_processus, (*s_etat_processus).s_liste_variables  
                 [position_supprimee].objet);  
         free((*s_etat_processus).s_liste_variables[position_supprimee].nom);  
   
         (*s_etat_processus).nombre_variables--;          niveau = (*(*variable_a_supprimer).variable).niveau;
           variables_par_niveau = (*s_etat_processus).l_liste_variables_par_niveau;
           variable_supprimee = d_faux;
   
         for(position_courante = position_supprimee;          if (variables_par_niveau != NULL)
                 position_courante < (*s_etat_processus).nombre_variables;  
                 position_courante++)  
         {          {
             (*s_etat_processus).s_liste_variables[position_courante] =              do
                     (*s_etat_processus).s_liste_variables              {
                     [position_courante + 1];                  l_element_courant = (*variables_par_niveau).liste;
   
                   if (l_element_courant != NULL)
                   {
                       if ((*((struct_variable *) (*l_element_courant).donnee))
                               .niveau == niveau)
                       {
                           // On parcourt le bon niveau.
   
                           l_element_precedent = NULL;
   
                           while(l_element_courant != NULL)
                           {
                               // Tant que l_element_courant est non nul, il reste
                               // des variables à explorer dans le niveau courant.
   
                               if ((*l_element_courant).donnee ==
                                       (void *) (*variable_a_supprimer).variable)
                               {
                                   // On a trouvé la variable à supprimer.
   
                                   if (l_element_precedent == NULL)
                                   {
                                       (*variables_par_niveau).liste =
                                               (*l_element_courant).suivant;
                                   }
                                   else
                                   {
                                       (*l_element_precedent).suivant =
                                               (*l_element_courant).suivant;
                                   }
   
                                   liberation_maillon(s_etat_processus,
                                           l_element_courant);
   
                                   if ((*variables_par_niveau).liste == NULL)
                                   {
                                       (*s_etat_processus).niveau_supprime =
                                               d_vrai;
   
                                       if ((*s_etat_processus)
                                               .l_liste_variables_par_niveau
                                               == variables_par_niveau)
                                       {
                                           // On retire l'élément de la liste
                                           // pointé par
                                           // l_liste_variable_par_niveau
   
                                           (*s_etat_processus)
                                                   .l_liste_variables_par_niveau =
                                                   (*variables_par_niveau).suivant;
                                       }
   
                                       (*(*variables_par_niveau).precedent)
                                               .suivant =
                                               (*variables_par_niveau).suivant;
                                       (*(*variables_par_niveau).suivant)
                                               .precedent =
                                               (*variables_par_niveau)
                                               .precedent;
                                       liberation_feuille(s_etat_processus,
                                               variables_par_niveau);
                                   }
   
                                   variable_supprimee = d_vrai;
                                   break;
                               }
   
                               l_element_precedent = l_element_courant;
                               l_element_courant = (*l_element_courant).suivant;
                           }
                       }
                   }
   
                   if (variable_supprimee == d_vrai)
                   {
                       break;
                   }
   
                   variables_par_niveau = (*variables_par_niveau).suivant;
   
               } while(variables_par_niveau != (*s_etat_processus)
                       .l_liste_variables_par_niveau);
         }          }
   
           // Puis on libère le contenu de la variable.
   
           free((*(*variable_a_supprimer).variable).nom);
           liberation(s_etat_processus, (*(*variable_a_supprimer).variable).objet);
           liberation_variable(s_etat_processus, (*variable_a_supprimer).variable);
           liberation_feuille(s_etat_processus, variable_a_supprimer);
   
         erreur = d_absence_erreur;          erreur = d_absence_erreur;
     }      }
     else      else
     {      {
           // Aucune variable n'est accessible depuis le point courant du
           // programme.
   
         erreur = d_erreur;          erreur = d_erreur;
         (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;          (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
     }      }
   
     return erreur;      return(erreur);
 }  }
   
   
 /*  /*
 ================================================================================  ================================================================================
   Procédure de recherche d'une variable par son nom dans la base    Procédure de retrait des variables de niveau strictement supérieur au
     niveau courant
 ================================================================================  ================================================================================
   Entrée :    Entrée :
 --------------------------------------------------------------------------------  --------------------------------------------------------------------------------
Line 392  retrait_variable(struct_processus *s_eta Line 1500  retrait_variable(struct_processus *s_eta
 */  */
   
 logical1  logical1
 recherche_variable(struct_processus *s_etat_processus,  retrait_variables_par_niveau(struct_processus *s_etat_processus)
         unsigned char *nom_variable)  
 {  {
     logical1                    existence_variable;      struct_liste_variables          *l_element_a_supprimer;
   
     long                        difference;      // Utilisation du champ (*s_etat_processus).liste_variables_par_niveau.
     long                        difference_inferieure;      // La tête de la pile contient toujours les variables de plus haut niveau
     long                        difference_superieure;      // créées.
   
     struct_liste_pile_systeme   *l_element_courant;      while((*s_etat_processus).l_liste_variables_par_niveau != NULL)
   
     unsigned long               borne_inferieure;  
     unsigned long               borne_superieure;  
     unsigned long               moyenne;  
     unsigned long               niveau_appel;  
     unsigned long               nombre_iterations_maximal;  
     unsigned long               ordre_iteration;  
   
     if ((*s_etat_processus).nombre_variables == 0)  
     {      {
         (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;          if ((*(*s_etat_processus).l_liste_variables_par_niveau).liste == NULL)
         return d_faux;          {
     }              // Si le niveau ne contient aucune variable, on le détruit.
               // Le pointeur sur la chaîne est déjà nul et il ne reste rien à
               // faire.
           }
           else
           {
               // Le niveau contient des variables.
   
     ordre_iteration = 0;              if ((*((struct_variable *) (*(*(*s_etat_processus)
     nombre_iterations_maximal = ((unsigned long)                      .l_liste_variables_par_niveau).liste).donnee)).niveau
             (log((*s_etat_processus).nombre_variables) / log(2))) + 2;                      <= (*s_etat_processus).niveau_courant)
               {
                   // On a retiré de l'arbre des variables toutes les
                   // variables de niveau strictement supérieur au niveau
                   // courant.
   
     borne_inferieure = 0;                  break;
     borne_superieure = (*s_etat_processus).nombre_variables - 1;              }
   
     do              if (((*s_etat_processus).at_exit != NULL) &&
     {                      ((*s_etat_processus).niveau_courant == 0))
         moyenne = (borne_inferieure + borne_superieure) / 2;              {
         ordre_iteration++;                  // Il y a une routine ATEXIT enregistrée. On ne détruit pas
                   // les variables globales qui pourraient y être utilisées.
   
         if (((borne_inferieure + borne_superieure) % 2) == 0)                  break;
         {              }
             difference = strcmp(nom_variable,  
                     ((*s_etat_processus).s_liste_variables)[moyenne].nom);  
   
             if (difference != 0)              while((*(*s_etat_processus).l_liste_variables_par_niveau).liste
                       != NULL)
             {              {
                 if (difference > 0)                  // Nécessaire car le pointeur sur la tête de la pile
                   // peut être modifié par retrait_variable().
                   // Sauvegarde des variables statiques.
   
                   if ((*((struct_variable *) (*(*(*s_etat_processus)
                           .l_liste_variables_par_niveau).liste).donnee)).origine
                           == 'P')
                 {                  {
                     borne_inferieure = moyenne;                      if ((*((struct_variable *) (*(*(*s_etat_processus)
                               .l_liste_variables_par_niveau).liste).donnee))
                               .variable_statique.adresse != 0)
                       {
                           if (recherche_variable_statique(s_etat_processus,
                                   (*((struct_variable *) (*(*(*s_etat_processus)
                                   .l_liste_variables_par_niveau).liste).donnee))
                                   .nom, (*((struct_variable *)
                                   (*(*(*s_etat_processus)
                                   .l_liste_variables_par_niveau).liste).donnee))
                                   .variable_statique, ((*s_etat_processus)
                                   .mode_execution_programme
                                    == 'Y') ? 'P' : 'E') != NULL)
                           {
                               (*(*s_etat_processus)
                                       .pointeur_variable_statique_courante)
                                       .objet = (*((struct_variable *)
                                       (*(*(*s_etat_processus)
                                       .l_liste_variables_par_niveau).liste)
                                       .donnee)).objet;
                           }
                           else
                           {
                               (*s_etat_processus).erreur_systeme =
                                       d_es_variable_introuvable;
                           }
   
                           (*((struct_variable *) (*(*(*s_etat_processus)
                                   .l_liste_variables_par_niveau).liste).donnee))
                                   .objet = NULL;
                       }
                 }                  }
                 else                  else
                 {                  {
                     borne_superieure = moyenne;                      if ((*((struct_variable *) (*(*(*s_etat_processus)
                 }                              .l_liste_variables_par_niveau).liste).donnee))
             }                              .variable_statique.pointeur != NULL)
         }                      {
         else                          /*
         {                           * Gestion des variables statiques
             difference_inferieure = strcmp(nom_variable,                           */
                     ((*s_etat_processus).s_liste_variables)[moyenne].nom);  
             difference_superieure = strcmp(nom_variable,                          if (recherche_variable_statique(s_etat_processus,
                     ((*s_etat_processus).s_liste_variables)[moyenne + 1].nom);                                  (*((struct_variable *) (*(*(*s_etat_processus)
                                   .l_liste_variables_par_niveau).liste).donnee))
                                   .nom, (*((struct_variable *)
                                   (*(*(*s_etat_processus)
                                   .l_liste_variables_par_niveau).liste).donnee))
                                   .variable_statique, ((*s_etat_processus)
                                   .mode_execution_programme
                                    == 'Y') ? 'P' : 'E') != NULL)
                           {
                               (*(*s_etat_processus)
                                       .pointeur_variable_statique_courante)
                                       .objet = (*((struct_variable *)
                                       (*(*(*s_etat_processus)
                                       .l_liste_variables_par_niveau).liste)
                                       .donnee)).objet;
                           }
                           else
                           {
                               (*s_etat_processus).erreur_systeme =
                                       d_es_variable_introuvable;
                               return(d_erreur);
                           }
   
             if (difference_inferieure == 0)                          (*((struct_variable *) (*(*(*s_etat_processus)
             {                                  .l_liste_variables_par_niveau).liste).donnee))
                 difference = 0;                                  .objet = NULL;
             }                      }
             else if (difference_superieure == 0)                  }
             {  
                 difference = 0;  
                 moyenne++;  
             }  
             else  
             {  
                 difference = difference_inferieure;  
   
                 if (difference > 0)                  if (retrait_variable(s_etat_processus,
                           (*((struct_variable *) (*(*(*s_etat_processus)
                           .l_liste_variables_par_niveau).liste).donnee)).nom,
                           'L') == d_erreur)
                 {                  {
                     borne_inferieure = moyenne;                      return(d_erreur);
                 }                  }
                 else  
                   if ((*((struct_variable *) (*(*(*s_etat_processus)
                           .l_liste_variables_par_niveau).liste).donnee)).niveau
                           <= (*s_etat_processus).niveau_courant)
                 {                  {
                     borne_superieure = moyenne;                      // On a retiré de l'arbre des variables toutes les
                       // variables de niveau strictement supérieur au niveau
                       // courant.
   
                       return(d_absence_erreur);
                 }                  }
             }              }
         }          }
     } while((difference != 0) &&  
             (ordre_iteration <= nombre_iterations_maximal));  
   
     if (ordre_iteration > nombre_iterations_maximal)          // On retire l'élément de la liste doublement chaînée et circulaire.
   
           (*(*(*s_etat_processus).l_liste_variables_par_niveau).precedent).suivant
                   = (*(*s_etat_processus).l_liste_variables_par_niveau).suivant;
           (*(*(*s_etat_processus).l_liste_variables_par_niveau).suivant).precedent
                   = (*(*s_etat_processus).l_liste_variables_par_niveau).precedent;
   
           l_element_a_supprimer = (*s_etat_processus)
                   .l_liste_variables_par_niveau;
           (*s_etat_processus).l_liste_variables_par_niveau =
                   (*l_element_a_supprimer).suivant;
           liberation_feuille(s_etat_processus, l_element_a_supprimer);
       }
   
       return(d_absence_erreur);
   }
   
   
   /*
   ================================================================================
     Procédure de retrait des toutes les variables locales et globales
   ================================================================================
     Entrée : drapeau indiquant s'il faut retirer les définitions (variables
              de niveau 0)
   --------------------------------------------------------------------------------
     Sortie :
   --------------------------------------------------------------------------------
     Effets de bord : néant
   ================================================================================
   */
   
   void
   liberation_arbre_variables(struct_processus *s_etat_processus,
           struct_arbre_variables *arbre, logical1 retrait_definitions)
   {
       int                                 i;
   
       struct_liste_chainee                *l_element_courant_liste;
       struct_liste_chainee                *l_element_suivant_liste;
   
       struct_liste_variables              *l_element_courant;
       struct_liste_variables              *l_element_suivant;
   
       struct_liste_variables_statiques    *l_element_statique_courant;
       struct_liste_variables_statiques    *l_element_statique_suivant;
   
       // Libération de l'arbre des variables. Le contenu des variables n'est
       // pas détruit par cette opération, il sera détruit lors de la libération
       // de la liste des variables par niveau.
   
       if (arbre == NULL)
     {      {
         existence_variable = d_faux;          return;
         (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;  
     }      }
     else  
       l_element_courant = (*arbre).feuille;
   
       if (l_element_courant != NULL)
       {
           do
           {
               l_element_suivant = (*l_element_courant).suivant;
               liberation_feuille(s_etat_processus, l_element_courant);
               l_element_courant = l_element_suivant;
           } while(l_element_courant != (*arbre).feuille);
   
           (*arbre).feuille = NULL;
       }
   
       l_element_statique_courant = (*arbre).feuille_statique;
   
       while(l_element_statique_courant != NULL)
     {      {
         if ((moyenne + 1) < (*s_etat_processus).nombre_variables)          l_element_statique_suivant = (*l_element_statique_courant).suivant;
   
           free((*(*l_element_statique_courant).variable).nom);
           liberation(s_etat_processus, (*(*l_element_statique_courant)
                   .variable).objet);
           free((*l_element_statique_courant).variable);
           free(l_element_statique_courant);
   
           l_element_statique_courant = l_element_statique_suivant;
       }
   
       for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
       {
           if ((*arbre).noeuds[i] != NULL)
           {
               liberation_arbre_variables(s_etat_processus, (*arbre).noeuds[i],
                       retrait_definitions);
               (*arbre).noeuds[i] = NULL;
           }
       }
   
       // Suppression de la liste des variables par niveau.
   
       if (arbre == (*s_etat_processus).s_arbre_variables)
       {
           l_element_courant = (*s_etat_processus).l_liste_variables_par_niveau;
   
           if (l_element_courant != NULL)
         {          {
             while(strcmp(((*s_etat_processus).s_liste_variables)              do
                     [moyenne + 1].nom, nom_variable) == 0)  
             {              {
                 moyenne++;                  l_element_courant_liste = (*l_element_courant).liste;
   
                 if ((moyenne + 1) >= (*s_etat_processus).nombre_variables)                  while(l_element_courant_liste != NULL)
                 {                  {
                     break;                      if ((retrait_definitions == d_vrai) ||
                               ((*((struct_variable *) (*l_element_courant_liste)
                               .donnee)).niveau >= 1))
                       {
                           liberation(s_etat_processus, (*((struct_variable *)
                                   (*l_element_courant_liste).donnee)).objet);
                           free((*((struct_variable *) (*l_element_courant_liste)
                                   .donnee)).nom);
                       }
   
                       l_element_suivant_liste =
                               (*l_element_courant_liste).suivant;
                       liberation_variable(s_etat_processus, (struct_variable *)
                               (*l_element_courant_liste).donnee);
                       liberation_maillon(s_etat_processus,
                               l_element_courant_liste);
                       l_element_courant_liste = l_element_suivant_liste;
                 }                  }
             }  
                   l_element_suivant = (*l_element_courant).suivant;
                   liberation_feuille(s_etat_processus, l_element_courant);
                   l_element_courant = l_element_suivant;
               } while(l_element_courant != (*s_etat_processus)
                       .l_liste_variables_par_niveau);
         }          }
       }
   
         (*s_etat_processus).position_variable_courante = moyenne;      liberation_tableau_noeuds(s_etat_processus, (*arbre).noeuds);
       liberation_noeud(s_etat_processus, arbre);
       arbre = NULL;
   
         if ((*s_etat_processus).s_liste_variables[(*s_etat_processus)      return;
                 .position_variable_courante].niveau > 1)  }
         {  
             // La variable trouvée est une variable locale.  
             // On vérifie qu'elle est accessible à la définition  
             // courante.  
   
             niveau_appel = (*s_etat_processus).niveau_courant;  
             l_element_courant = (*s_etat_processus).l_base_pile_systeme;  
   
             if (l_element_courant == NULL)  /*
             {  ================================================================================
                 (*s_etat_processus).erreur_systeme = d_es_pile_vide;    Procédure renvoyant les variables dans un tableau
                 existence_variable = d_faux;  ================================================================================
     Entrée :
   --------------------------------------------------------------------------------
     Sortie :
   --------------------------------------------------------------------------------
     Effets de bord : néant
   ================================================================================
   */
   
                 return existence_variable;  static integer8
             }  nombre_variables_locales(struct_processus *s_etat_processus,
           struct_arbre_variables *l_element_courant)
   {
       integer8                            i;
       integer8                            n;
   
             while((*l_element_courant).retour_definition != 'Y')      struct_liste_variables              *l_variable;
             {      struct_liste_variables_statiques    *l_variable_statique;
                 l_element_courant = (*l_element_courant).suivant;  
   
                 if (l_element_courant == NULL)      if (l_element_courant == NULL)
                 {      {
                     (*s_etat_processus).erreur_systeme = d_es_pile_vide;          return(0);
                     existence_variable = d_faux;      }
   
                     return existence_variable;      n = 0;
                 }  
             }      if ((*l_element_courant).feuille != NULL)
       {
           l_variable = (*l_element_courant).feuille;
   
             niveau_appel = (*l_element_courant).niveau_courant;          do
           {
               n++;
               l_variable = (*l_variable).suivant;
           } while(l_variable != (*l_element_courant).feuille);
       }
   
       if ((*l_element_courant).feuille_statique != NULL)
       {
           l_variable_statique = (*l_element_courant).feuille_statique;
   
             if (niveau_appel < (*s_etat_processus).s_liste_variables          do
                     [(*s_etat_processus).position_variable_courante].niveau)          {
               // Si le pointeur est nul, la variable est accessible et a été
               // copiée dans l'arbre des variables.
   
               if ((*(*l_variable_statique).variable).objet != NULL)
             {              {
                 existence_variable = d_vrai;                  n++;
             }              }
             else  
             {  
                 existence_variable = d_faux;  
   
                 // La variable locale n'est pas accessible. On regarde si par              l_variable_statique = (*l_variable_statique).suivant;
                 // hasard il existe une variable globale.          } while(l_variable_statique != NULL);
       }
   
                 while((*s_etat_processus).position_variable_courante != 0)      for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
                 {      {
                     if (strcmp(((*s_etat_processus).s_liste_variables)          if ((*l_element_courant).noeuds[i] != NULL)
                             [(*s_etat_processus).position_variable_courante - 1]                            .nom, nom_variable) == 0)          {
                     {              n += nombre_variables_locales(s_etat_processus,
                         (*s_etat_processus).position_variable_courante--;                      (*l_element_courant).noeuds[i]);
                     }          }
                     else      }
                     {  
                         if ((*s_etat_processus).s_liste_variables  
                                 [(*s_etat_processus).position_variable_courante]  
                                 .niveau <= 1)  
                         {  
                             existence_variable = d_vrai;  
                         }  
   
                         break;      return(n);
                     }  }
                 }  
   
                 if ((strcmp(((*s_etat_processus).s_liste_variables)  
                         [(*s_etat_processus).position_variable_courante].nom,  static integer8
                         nom_variable) == 0) && ((*s_etat_processus)  nombre_variables_partagees(struct_processus *s_etat_processus,
                         .s_liste_variables[(*s_etat_processus)          struct_arbre_variables_partagees *l_element_courant)
                         .position_variable_courante].niveau <= 1))  {
                 {      integer8                            i;
                     existence_variable = d_vrai;      integer8                            n;
                 }  
       struct_liste_variables_partagees    *l_variable;
   
       if (l_element_courant == NULL)
       {
           return(0);
       }
   
       // Mutex deverrouillé par liste_variables_partagees();
       if (pthread_mutex_lock(&((*l_element_courant).mutex_feuille)) != 0)
       {
           (*s_etat_processus).erreur_systeme = d_es_processus;
           return(0);
       }
   
       n = 0;
   
       if ((*l_element_courant).feuille != NULL)
       {
           l_variable = (*l_element_courant).feuille;
   
           do
           {
               n++;
               l_variable = (*l_variable).suivant;
           } while(l_variable != NULL);
       }
   
       for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
       {
           if ((*l_element_courant).noeuds[i] != NULL)
           {
               n += nombre_variables_partagees(s_etat_processus,
                       (*l_element_courant).noeuds[i]);
           }
       }
   
       return(n);
   }
   
   
   integer8
   nombre_variables(struct_processus *s_etat_processus)
   {
       return(nombre_variables_locales(s_etat_processus,
               (*s_etat_processus).s_arbre_variables)
               + nombre_variables_partagees(s_etat_processus,
               (*(*s_etat_processus).s_arbre_variables_partagees)));
   }
   
   
   void
   liberation_mutexes_arbre_variables_partagees(struct_processus *s_etat_processus,
           struct_arbre_variables_partagees *l_element_courant)
   {
       int                                 i;
   
       if (l_element_courant == NULL)
       {
           return;
       }
   
       if (pthread_mutex_trylock(&((*l_element_courant).mutex_feuille)) != 0)
       {
           (*s_etat_processus).erreur_systeme = d_es_processus;
           return;
       }
   
       if (pthread_mutex_unlock(&((*l_element_courant).mutex_feuille)) != 0)
       {
           (*s_etat_processus).erreur_systeme = d_es_processus;
           return;
       }
   
       for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
       {
           if ((*l_element_courant).noeuds[i] != NULL)
           {
               liberation_mutexes_arbre_variables_partagees(s_etat_processus,
                       (*l_element_courant).noeuds[i]);
           }
       }
   
       return;
   }
   
   
   static integer8
   liste_variables_locales(struct_processus *s_etat_processus,
           struct_tableau_variables *tableau, integer8 position,
           struct_arbre_variables *l_element_courant)
   {
       integer8                            i;
   
       struct_liste_variables              *l_variable;
       struct_liste_variables_statiques    *l_variable_statique;
   
       if (l_element_courant == NULL)
       {
           return(position);
       }
   
       if ((*l_element_courant).feuille != NULL)
       {
           l_variable = (*l_element_courant).feuille;
   
           do
           {
               tableau[position].origine = (*(*l_variable).variable).origine;
               tableau[position].nom = (*(*l_variable).variable).nom;
               tableau[position].niveau = (*(*l_variable).variable).niveau;
               tableau[position].objet = (*(*l_variable).variable).objet;
               tableau[position].variable_verrouillee =
                       (*(*l_variable).variable).variable_verrouillee;
               tableau[position].variable_statique =
                       (*(*l_variable).variable).variable_statique;
               tableau[position].variable_partagee =
                       (*(*l_variable).variable).variable_partagee;
               tableau[position].variable_masquee = d_faux;
               tableau[position].mutex = NULL;
   
               position++;
   
               l_variable = (*l_variable).suivant;
           } while(l_variable != (*l_element_courant).feuille);
       }
   
       if ((*l_element_courant).feuille_statique != NULL)
       {
           l_variable_statique = (*l_element_courant).feuille_statique;
   
           do
           {
               if ((*(*l_variable_statique).variable).objet != NULL)
               {
                   tableau[position].origine = 'E';
                   tableau[position].nom = (*(*l_variable_statique).variable).nom;
                   tableau[position].niveau =
                           (*(*l_variable_statique).variable).niveau;
                   tableau[position].objet = (*(*l_variable_statique).variable)
                           .objet;
                   tableau[position].variable_verrouillee = d_faux;
                   tableau[position].variable_statique =
                           (*(*l_variable_statique).variable).variable_statique;
                   tableau[position].variable_partagee.pointeur = NULL;
                   tableau[position].variable_masquee = d_vrai;
                   tableau[position].mutex = NULL;
   
                   position++;
             }              }
   
               l_variable_statique = (*l_variable_statique).suivant;
           } while(l_variable_statique != NULL);
       }
   
       for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
       {
           if ((*l_element_courant).noeuds[i] != NULL)
           {
               position = liste_variables_locales(s_etat_processus,
                       tableau, position, (*l_element_courant).noeuds[i]);
         }          }
         else      }
   
       return(position);
   }
   
   
   static integer8
   liste_variables_partagees(struct_processus *s_etat_processus,
           struct_tableau_variables *tableau, integer8 position,
           struct_arbre_variables_partagees *l_element_courant)
   {
       integer8                            i;
   
       struct_liste_variables_partagees    *l_variable;
   
       if (l_element_courant == NULL)
       {
           return(position);
       }
   
       if ((*l_element_courant).feuille != NULL)
       {
           l_variable = (*l_element_courant).feuille;
   
           do
         {          {
             // La variable trouvée est soit un pointeur sur une définition              tableau[position].origine = 'E';
             // (niveau 0), soit une variable globale (niveau 1).              tableau[position].nom = (*(*l_variable).variable).nom;
               tableau[position].niveau = (*(*l_variable).variable).niveau;
               tableau[position].objet = (*(*l_variable).variable).objet;
               tableau[position].variable_verrouillee = d_faux;
               tableau[position].variable_partagee =
                       (*(*l_variable).variable).variable_partagee;
               tableau[position].variable_statique.pointeur = NULL;
               tableau[position].variable_masquee = d_faux;
               tableau[position].mutex = &((*(*l_variable).variable).mutex);
               pthread_mutex_lock(tableau[position].mutex);
   
               position++;
   
             existence_variable = d_vrai;              l_variable = (*l_variable).suivant;
           } while(l_variable != NULL);
       }
   
       for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
       {
           if ((*l_element_courant).noeuds[i] != NULL)
           {
               position = liste_variables_partagees(s_etat_processus,
                       tableau, position, (*l_element_courant).noeuds[i]);
         }          }
     }      }
   
     return existence_variable;      // Mutex verrouillé par nombre_variables_partagees();
       if (pthread_mutex_unlock(&((*l_element_courant).mutex_feuille)) != 0)
       {
           (*s_etat_processus).erreur_systeme = d_es_processus;
           return(0);
       }
   
       return(position);
   }
   
   
   static int
   fonction_ordre_variables(const void *argument_1, const void *argument_2)
   {
       int                         comparaison;
   
       struct_tableau_variables    *a1;
       struct_tableau_variables    *a2;
   
       a1 = (struct_tableau_variables *) argument_1;
       a2 = (struct_tableau_variables *) argument_2;
   
       comparaison = strcmp((*a1).nom, (*a2).nom);
   
       if (comparaison != 0)
       {
           return(comparaison);
       }
       else
       {
           return(((((*a1).niveau - (*a2).niveau)) > 0) ? 1 : -1);
       }
   }
   
   
   integer8
   liste_variables(struct_processus *s_etat_processus,
           struct_tableau_variables *tableau)
   {
       integer8        nombre_elements;
   
       nombre_elements = liste_variables_locales(s_etat_processus,
               tableau, 0, (*s_etat_processus).s_arbre_variables);
       nombre_elements = liste_variables_partagees(s_etat_processus,
               tableau, nombre_elements, (*(*s_etat_processus)
               .s_arbre_variables_partagees));
   
       qsort(tableau, (size_t) nombre_elements, sizeof(struct_tableau_variables),
               fonction_ordre_variables);
   
       return(nombre_elements);
 }  }
   
   
 /*  /*
 ================================================================================  ================================================================================
   Procédure de retrait des variables de niveau strictement supérieur au    Procédure de copie de l'arbre des variables
   niveau courant  
 ================================================================================  ================================================================================
   Entrée :    Entrée :
 --------------------------------------------------------------------------------  --------------------------------------------------------------------------------
Line 602  recherche_variable(struct_processus *s_e Line 2145  recherche_variable(struct_processus *s_e
 ================================================================================  ================================================================================
 */  */
   
 logical1  void
 retrait_variable_par_niveau(struct_processus *s_etat_processus)  copie_arbre_variables(struct_processus *s_etat_processus, struct_processus
           *s_nouvel_etat_processus)
 {  {
     unsigned long                   i;      // Les définitions sont partagées entre tous les threads et ne sont pas
     unsigned long                   j;      // copiées.
       //
       // NB : on ne copie que les variables de niveaux 0 et 1, les autres
       // variables locales étant masquées par le processus de création de thread
       // ou de processus, elles seront inaccessibles de tous les points
       // du fil d'exécution fils.
   
       // Pour copier ces variables, on récupère les variables depuis la liste par
       // niveaux (niveaux 0 et 1) et on ajoute les variables dans la nouvelle
       // structure. Les variables de niveau 0 étant non modifiables, elles
       // ne sont pas dupliquées.
   
       int                                 i;
   
       logical1                            niveau_0_traite;
       logical1                            niveau_1_traite;
   
       struct_arbre_variables              *l_variable_courante;
   
       struct_liste_chainee                *l_element_courant;
   
       struct_liste_variables              *l_niveau_courant;
       struct_liste_variables_statiques    *l_element_statique_courant;
   
     struct_variable                 *tampon;      struct_variable                     s_variable;
       struct_variable_statique            s_variable_statique;
   
     for(j = 0, i = 0; i < (*s_etat_processus).nombre_variables; i++)      unsigned char                       *ptr;
   
       (*s_nouvel_etat_processus).s_arbre_variables = NULL;
       (*s_nouvel_etat_processus).l_liste_variables_par_niveau = NULL;
   
       l_niveau_courant = (*s_etat_processus).l_liste_variables_par_niveau;
       
       // Si la variable en tête n'est pas une variable de niveau 0, le niveau
       // 0, s'il existe est le niveau précédent la valeur courante dans la
       // boucle.
   
       if ((*((struct_variable *) (*(*l_niveau_courant).liste).donnee)).niveau
               != 0)
     {      {
         if ((*s_etat_processus).s_liste_variables[i].niveau <=          l_niveau_courant = (*l_niveau_courant).precedent;
                 (*s_etat_processus).niveau_courant)      }
         {  
             (*s_etat_processus).s_liste_variables[j++] =      // Les variables de niveaux 0 et 1 sont accessibles en au plus trois
                     (*s_etat_processus).s_liste_variables[i];      // itérations (par construction).
         }  
         else      niveau_0_traite = d_faux;
       niveau_1_traite = d_faux;
   
       for(i = 0; i <= 2; i++)
       {
           if ((*((struct_variable *) (*(*l_niveau_courant).liste)
                   .donnee)).niveau == 0)
         {          {
             if ((*s_etat_processus).s_liste_variables[i].origine == 'P')              if (niveau_0_traite == d_faux)
             {              {
                 if ((*s_etat_processus).s_liste_variables[i]                  l_element_courant = (*l_niveau_courant).liste;
                         .variable_statique.adresse != 0)  
                   while(l_element_courant != NULL)
                 {                  {
                     /*                      if (ajout_variable(s_nouvel_etat_processus,
                      * Gestion des variables statiques                              (struct_variable *) (*l_element_courant).donnee)
                      */                              == d_erreur)
   
                     if (recherche_variable_statique(s_etat_processus,  
                             (*s_etat_processus).s_liste_variables[i]  
                             .nom, (*s_etat_processus).s_liste_variables  
                             [i].variable_statique, ((*s_etat_processus)  
                             .mode_execution_programme  
                              == 'Y') ? 'P' : 'E') == d_vrai)  
                     {  
                         (*s_etat_processus).s_liste_variables_statiques  
                                 [(*s_etat_processus)  
                                 .position_variable_statique_courante]  
                                 .objet = (*s_etat_processus)  
                                 .s_liste_variables[i].objet;  
                     }  
                     else  
                     {                      {
                         (*s_etat_processus).erreur_systeme =                          return;
                                 d_es_variable_introuvable;  
                     }                      }
   
                     (*s_etat_processus).s_liste_variables[i].objet = NULL;                      l_element_courant = (*l_element_courant).suivant;
                 }                  }
   
                   niveau_0_traite = d_vrai;
             }              }
             else          }
           else if ((*((struct_variable *) (*(*l_niveau_courant).liste)
                   .donnee)).niveau == 1)
           {
               if (niveau_1_traite == d_faux)
             {              {
                 if ((*s_etat_processus).s_liste_variables[i]                  l_element_courant = (*l_niveau_courant).liste;
                         .variable_statique.pointeur != NULL)  
                   while(l_element_courant != NULL)
                 {                  {
                     /*                      s_variable = (*((struct_variable *)
                      * Gestion des variables statiques                              (*l_element_courant).donnee));
                      */  
                       if ((s_variable.nom = rpl_malloc(s_nouvel_etat_processus,
                     if (recherche_variable_statique(s_etat_processus,                              (strlen((*((struct_variable *)
                             (*s_etat_processus).s_liste_variables[i]                              (*l_element_courant).donnee)).nom) + 1) *
                             .nom, (*s_etat_processus).s_liste_variables[i]                              sizeof(unsigned char))) == NULL)
                             .variable_statique, ((*s_etat_processus)  
                             .mode_execution_programme  
                              == 'Y') ? 'P' : 'E') == d_vrai)  
                     {                      {
                         (*s_etat_processus).s_liste_variables_statiques                          (*s_nouvel_etat_processus).erreur_systeme =
                                 [(*s_etat_processus)                                  d_es_allocation_memoire;
                                 .position_variable_statique_courante]                          return;
                                 .objet = (*s_etat_processus)  
                                 .s_liste_variables[i].objet;  
                     }                      }
                     else  
                       strcpy(s_variable.nom, (*((struct_variable *)
                               (*l_element_courant).donnee)).nom);
   
                       if ((s_variable.objet = copie_objet(s_nouvel_etat_processus,
                               (*((struct_variable *) (*l_element_courant).donnee))
                               .objet, 'P')) == NULL)
                       {
                           (*s_nouvel_etat_processus).erreur_systeme =
                                   d_es_allocation_memoire;
                           return;
                       }
   
                       if (ajout_variable(s_nouvel_etat_processus, &s_variable)
                               == d_erreur)
                     {                      {
                         (*s_etat_processus).erreur_systeme =                          return;
                                 d_es_variable_introuvable;  
                     }                      }
   
                     (*s_etat_processus).s_liste_variables[i].objet = NULL;                      l_element_courant = (*l_element_courant).suivant;
                 }                  }
   
                   niveau_1_traite = d_vrai;
             }              }
   
             free((*s_etat_processus).s_liste_variables[i].nom);              // Les variables de niveau 0 ayant déjà été copiées, on
             liberation(s_etat_processus,              // peut sortir de la boucle car toutes les variables sont
                     (*s_etat_processus).s_liste_variables[i].objet);              // maintenant disponibles dans le fil d'exécution fils.
   
               break;
         }          }
   
           l_niveau_courant = (*l_niveau_courant).precedent;
     }      }
   
     (*s_etat_processus).nombre_variables = j;      // Copie des variables statiques
   
       l_element_statique_courant = (*s_etat_processus)
               .l_liste_variables_statiques;
   
     if ((*s_etat_processus).nombre_variables <      while(l_element_statique_courant != NULL)
             ((*s_etat_processus).nombre_variables_allouees / 2))  
     {      {
         (*s_etat_processus).nombre_variables_allouees /= 2;          // Création des branches de l'arbre si nécessaire.
   
         if ((tampon = realloc((*s_etat_processus).s_liste_variables,          if ((*s_nouvel_etat_processus).s_arbre_variables == NULL)
                 (*s_etat_processus).nombre_variables_allouees *          {
                 sizeof(struct_variable))) == NULL)              if (((*s_nouvel_etat_processus).s_arbre_variables =
                           allocation_noeud(s_nouvel_etat_processus)) == NULL)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
               (*(*s_nouvel_etat_processus).s_arbre_variables).feuille = NULL;
               (*(*s_nouvel_etat_processus).s_arbre_variables).feuille_statique
                       = NULL;
               (*(*s_nouvel_etat_processus).s_arbre_variables).noeuds_utilises = 0;
               (*(*s_nouvel_etat_processus).s_arbre_variables).indice_tableau_pere
                       = -1;
               (*(*s_nouvel_etat_processus).s_arbre_variables).noeud_pere = NULL;
   
               if (((*(*s_nouvel_etat_processus).s_arbre_variables).noeuds =
                       allocation_tableau_noeuds(s_nouvel_etat_processus)) == NULL)
               {
                   (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                   return;
               }
   
               for(i = 0; i < (*s_nouvel_etat_processus)
                       .nombre_caracteres_variables; i++)
               {
                   (*(*s_nouvel_etat_processus).s_arbre_variables).noeuds[i]
                           = NULL;
               }
           }
   
           l_variable_courante = (*s_nouvel_etat_processus).s_arbre_variables;
           ptr = (*(*l_element_statique_courant).variable).nom;
   
           while((*ptr) != d_code_fin_chaine)
           {
               BUG((*s_nouvel_etat_processus).pointeurs_caracteres_variables
                       [*ptr] < 0, uprintf("Variable=\"%s\", (*ptr)='%c'\n",
                       (*(*l_element_statique_courant).variable).nom, *ptr));
   
               if ((*l_variable_courante).noeuds[(*s_nouvel_etat_processus)
                       .pointeurs_caracteres_variables[*ptr]] == NULL)
               {
                   // Le noeud n'existe pas encore, on le crée et on le marque
                   // comme utilisé dans la structure parente.
   
                   if (((*l_variable_courante).noeuds[(*s_nouvel_etat_processus)
                           .pointeurs_caracteres_variables[*ptr]] =
                           allocation_noeud(s_nouvel_etat_processus)) == NULL)
                   {
                       (*s_etat_processus).erreur_systeme =
                               d_es_allocation_memoire;
                       return;
                   }
   
                   (*l_variable_courante).noeuds_utilises++;
   
                   // La feuille est par défaut vide et aucun élément du tableau
                   // noeuds (les branches qui peuvent être issues de ce nouveau
                   // noeud) n'est encore utilisée.
   
                   (*(*l_variable_courante).noeuds[(*s_nouvel_etat_processus)
                           .pointeurs_caracteres_variables[*ptr]]).feuille = NULL;
                   (*(*l_variable_courante).noeuds[(*s_nouvel_etat_processus)
                           .pointeurs_caracteres_variables[*ptr]]).feuille_statique
                           = NULL;
                   (*(*l_variable_courante).noeuds[(*s_nouvel_etat_processus)
                           .pointeurs_caracteres_variables[*ptr]]).noeuds_utilises
                           = 0;
   
                   // Le champ noeud_pere de la structure créée pointe sur
                   // la structure parente et l'indice tableau_pere correspond à la
                   // position réelle dans le tableau noeuds[] de la structure
                   // parente du noeud courant. Cette valeur sera utilisée lors de
                   // la destruction du noeud pour annuler le pointeur contenu dans
                   // le tableau noeuds[] de la structure parente.
   
                   (*(*l_variable_courante).noeuds[(*s_nouvel_etat_processus)
                           .pointeurs_caracteres_variables[*ptr]]).noeud_pere =
                           l_variable_courante;
                   (*(*l_variable_courante).noeuds[(*s_nouvel_etat_processus)
                           .pointeurs_caracteres_variables[*ptr]])
                           .indice_tableau_pere = (*s_nouvel_etat_processus)
                           .pointeurs_caracteres_variables[*ptr];
   
                   // Allocation du tableau noeuds[] et initialisation à zéro de
                   // tous les pointeurs.
   
                   if (((*(*l_variable_courante).noeuds[(*s_nouvel_etat_processus)
                           .pointeurs_caracteres_variables[*ptr]]).noeuds =
                           allocation_tableau_noeuds(s_nouvel_etat_processus))
                           == NULL)
                   {
                       (*s_etat_processus).erreur_systeme
                               = d_es_allocation_memoire;
                       return;
                   }
   
                   for(i = 0; i < (*s_nouvel_etat_processus)
                           .nombre_caracteres_variables; i++)
                   {
                       (*(*l_variable_courante).noeuds[(*s_nouvel_etat_processus)
                               .pointeurs_caracteres_variables[*ptr]]).noeuds[i]
                               = NULL;
                   }
               }
   
               l_variable_courante = (*l_variable_courante).noeuds
                       [(*s_nouvel_etat_processus).pointeurs_caracteres_variables
                       [*ptr]];
   
               ptr++;
           }
   
           // Il faut copier la variable pour la dissocier de la variable
           // restant dans le thread parent.
   
           s_variable_statique = (*(*l_element_statique_courant).variable);
   
           if (copie_objet(s_etat_processus, s_variable_statique.objet, 'P')
                   == NULL)
         {          {
             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;              (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
             return(d_erreur);              return;
         }          }
   
         (*s_etat_processus).s_liste_variables = tampon;          if ((s_variable_statique.nom = rpl_malloc(s_nouvel_etat_processus,
                   (strlen((*(*l_element_statique_courant).variable).nom) + 1) *
                   sizeof(unsigned char))) == NULL)
           {
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
           }
   
           strcpy(s_variable_statique.nom, (*(*l_element_statique_courant)
                   .variable).nom);
   
           if (creation_variable_statique(s_nouvel_etat_processus,
                   &s_variable_statique) == d_erreur)
           {
               (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
               return;
           }
   
           l_element_statique_courant = (*l_element_statique_courant).suivant;
     }      }
   
     return(d_absence_erreur);      return;
   }
   
   
   /*
   ================================================================================
     Procédure d'initialisation de la table de correspondance des variables
   ================================================================================
     Entrée :
   --------------------------------------------------------------------------------
     Sortie :
   --------------------------------------------------------------------------------
     Effets de bord : néant
   ================================================================================
   */
   
   /*
    * Caractères autorisés dans les variables
    *
    * A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
    * a b c d e f g h i j k l m n o p q r s t u v w x y z
    * _
    * 1 2 3 4 5 6 7 8 9 0
    */
   
   void
   initialisation_variables(struct_processus *s_etat_processus)
   {
       int             decalage;
       int             i;
       int             longueur_tableau;
   
       unsigned char   caractere;
   
       // Récupération de la longueur d'un unsigned char
   
       longueur_tableau = 1;
       decalage = 0;
       caractere = 1;
   
       while((1L << decalage) == (long) ((unsigned char) (caractere << decalage)))
       {
           decalage++;
           longueur_tableau *= 2;
       }
   
       if (((*s_etat_processus).pointeurs_caracteres_variables =
               malloc(((size_t) longueur_tableau) * sizeof(int))) == NULL)
       {
           (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
           return;
       }
   
       for(i = 0; i < longueur_tableau; i++)
       {
           (*s_etat_processus).pointeurs_caracteres_variables[i] = -1;
       }
   
       (*s_etat_processus).nombre_caracteres_variables = 0;
   
   #define DECLARATION_CARACTERE(c) \
           do { (*s_etat_processus).pointeurs_caracteres_variables[c] = \
           (*s_etat_processus).nombre_caracteres_variables++; } while(0)
   
       DECLARATION_CARACTERE('A');
       DECLARATION_CARACTERE('B');
       DECLARATION_CARACTERE('C');
       DECLARATION_CARACTERE('D');
       DECLARATION_CARACTERE('E');
       DECLARATION_CARACTERE('F');
       DECLARATION_CARACTERE('G');
       DECLARATION_CARACTERE('H');
       DECLARATION_CARACTERE('I');
       DECLARATION_CARACTERE('J');
       DECLARATION_CARACTERE('K');
       DECLARATION_CARACTERE('L');
       DECLARATION_CARACTERE('M');
       DECLARATION_CARACTERE('N');
       DECLARATION_CARACTERE('O');
       DECLARATION_CARACTERE('P');
       DECLARATION_CARACTERE('Q');
       DECLARATION_CARACTERE('R');
       DECLARATION_CARACTERE('S');
       DECLARATION_CARACTERE('T');
       DECLARATION_CARACTERE('U');
       DECLARATION_CARACTERE('V');
       DECLARATION_CARACTERE('W');
       DECLARATION_CARACTERE('X');
       DECLARATION_CARACTERE('Y');
       DECLARATION_CARACTERE('Z');
   
       DECLARATION_CARACTERE('a');
       DECLARATION_CARACTERE('b');
       DECLARATION_CARACTERE('c');
       DECLARATION_CARACTERE('d');
       DECLARATION_CARACTERE('e');
       DECLARATION_CARACTERE('f');
       DECLARATION_CARACTERE('g');
       DECLARATION_CARACTERE('h');
       DECLARATION_CARACTERE('i');
       DECLARATION_CARACTERE('j');
       DECLARATION_CARACTERE('k');
       DECLARATION_CARACTERE('l');
       DECLARATION_CARACTERE('m');
       DECLARATION_CARACTERE('n');
       DECLARATION_CARACTERE('o');
       DECLARATION_CARACTERE('p');
       DECLARATION_CARACTERE('q');
       DECLARATION_CARACTERE('r');
       DECLARATION_CARACTERE('s');
       DECLARATION_CARACTERE('t');
       DECLARATION_CARACTERE('u');
       DECLARATION_CARACTERE('v');
       DECLARATION_CARACTERE('w');
       DECLARATION_CARACTERE('x');
       DECLARATION_CARACTERE('y');
       DECLARATION_CARACTERE('z');
   
       DECLARATION_CARACTERE('_');
   
       DECLARATION_CARACTERE('1');
       DECLARATION_CARACTERE('2');
       DECLARATION_CARACTERE('3');
       DECLARATION_CARACTERE('4');
       DECLARATION_CARACTERE('5');
       DECLARATION_CARACTERE('6');
       DECLARATION_CARACTERE('7');
       DECLARATION_CARACTERE('8');
       DECLARATION_CARACTERE('9');
       DECLARATION_CARACTERE('0');
   #undef DECLARATION_CARACTERE
   
       return;
 }  }
   
 // vim: ts=4  // vim: ts=4

Removed from v.1.19  
changed lines
  Added in v.1.108


CVSweb interface <joel.bertrand@systella.fr>