--- rpl/src/gestion_variables.c 2011/06/01 18:17:35 1.27 +++ rpl/src/gestion_variables.c 2015/02/19 11:01:20 1.92 @@ -1,7 +1,7 @@ /* ================================================================================ - RPL/2 (R) version 4.1.0.prerelease.0 - Copyright (C) 1989-2011 Dr. BERTRAND Joël + RPL/2 (R) version 4.1.21 + Copyright (C) 1989-2015 Dr. BERTRAND Joël This file is part of RPL/2. @@ -25,13 +25,372 @@ /* ================================================================================ + 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 - Entrée : autorisation_creation_variable_statique vaut 'V' ou 'S'. - Dans le cas 'V', la variable est volatile. - Dans le cas 'S', elle est statique. - Entrée : autorisation_creation_variable_partagee vaut 'P' ou 'S'. - Dans le cas 'P', la variable est privée. - Dans le cas 'S', elle est partagée. +================================================================================ + Entrée : autorisation_creation_variable_statique vaut 'v' ou 's'. + dans le cas 'v', la variable est volatile. + dans le cas 's', elle est statique. + Entrée : autorisation_creation_variable_partagee vaut 'p' ou 's'. + dans le cas 'p', la variable est privée. + dans le cas 's', elle est partagée. -------------------------------------------------------------------------------- Sortie : -------------------------------------------------------------------------------- @@ -44,30 +403,37 @@ ajout_variable(struct_processus *s_etat_ { int i; - struct_arbre_variables *l_variable_courante; + 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 = - malloc(sizeof(struct_arbre_variables))) == NULL) + 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).arbre_instructions).noeud = - malloc((*s_etat_processus).nombre_caracteres_variables - * sizeof(struct_arbre_variables))) == 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); @@ -75,41 +441,69 @@ ajout_variable(struct_processus *s_etat_ for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++) { - (*(*s_etat_processus).s_arbre_variables).noeud[i] = NULL; + (*(*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, - printf("Variable=\"%s\", (*ptr)='%c'\n", (*s_variable).nom, + uprintf("Variable=\"%s\", (*ptr)='%c'\n", (*s_variable).nom, *ptr)); - if ((*l_variable_courante).noeud[(*s_etat_processus) + if ((*l_variable_courante).noeuds[(*s_etat_processus) .pointeurs_caracteres_variables[*ptr]] == NULL) { - // Le noeud n'existe pas encore, on le crée. + // Le noeud n'existe pas encore, on le crée et on le marque + // comme utilisé dans la structure parente. - if (((*l_variable_courante).noeud[(*s_etat_processus) + if (((*l_variable_courante).noeuds[(*s_etat_processus) .pointeurs_caracteres_variables[*ptr]] = - malloc(sizeof(struct_arbre_variables))) == NULL) + allocation_noeud(s_etat_processus)) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(d_erreur); } - (*(*l_variable_courante).noeud[(*s_etat_processus) + (*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).noeud[(*s_etat_processus) + (*(*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; - if (((*(*l_variable_courante).noeud[(*s_etat_processus) - .pointeurs_caracteres_variables[*ptr]]).noeud = - malloc((*s_etat_processus).nombre_caracteres_variables - * sizeof(struct_arbre_variables))) == NULL) + // 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); @@ -117,13 +511,14 @@ ajout_variable(struct_processus *s_etat_ for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++) { - (*(*l_variable_courante).noeud[(*s_etat_processus) - .pointeurs_caracteres_variables[*ptr]]).noeud[i] = NULL; + (*(*l_variable_courante).noeuds[(*s_etat_processus) + .pointeurs_caracteres_variables[*ptr]]).noeuds[i] + = NULL; } } - (*l_variable_courante).noeuds_utilises++; - l_variable_courante = (*l_variable_courante).noeud + l_variable_precedente = l_variable_courante; + l_variable_courante = (*l_variable_courante).noeuds [(*s_etat_processus).pointeurs_caracteres_variables[*ptr]]; ptr++; } @@ -135,22 +530,26 @@ ajout_variable(struct_processus *s_etat_ // variables de même nom. Cette liste boucle en premier lieu sur // elle-même. - if (((*l_variable_courante).feuille = malloc( - sizeof(struct_liste_variables))) == NULL) + if (((*l_variable_courante).feuille = allocation_feuille( + s_etat_processus)) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(d_erreur); } + (*l_variable_courante).noeuds_utilises++; + (*(*l_variable_courante).feuille).suivant = (*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 = - malloc(sizeof(struct_variable))) == NULL) + allocation_variable(s_etat_processus)) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(d_erreur); @@ -158,16 +557,17 @@ ajout_variable(struct_processus *s_etat_ (*((struct_variable *) (*(*l_variable_courante).feuille).variable)) = (*s_variable); - - if (((*((struct_variable *) (*(*l_variable_courante).feuille).variable)) - .nom = strdup((*s_variable).nom)) == NULL) + pointeur_variable_cree = (*(*l_variable_courante).feuille).variable; + } + else + { + if ((l_nouvelle_variable = allocation_feuille(s_etat_processus)) + == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(d_erreur); } - } - else - { + if ((*s_variable).niveau > 1) { // Cas d'une variable locale @@ -178,20 +578,15 @@ ajout_variable(struct_processus *s_etat_ BUG((*(*(*l_variable_courante).feuille).variable).niveau >= (*s_variable).niveau, - printf("Variable=\"%s\"\n", (*s_variable).nom)); + uprintf("Variable=\"%s\"\n", (*s_variable).nom)); // On ajoute la variable à la liste existante. - if ((l_nouvelle_variable = malloc(sizeof(struct_liste_variables))) - == NULL) - { - (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; - return(d_erreur); - } - (*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 = @@ -199,7 +594,7 @@ ajout_variable(struct_processus *s_etat_ (*l_variable_courante).feuille = l_nouvelle_variable; if (((*(*l_variable_courante).feuille).variable = - malloc(sizeof(struct_variable))) == NULL) + allocation_variable(s_etat_processus)) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(d_erreur); @@ -207,13 +602,7 @@ ajout_variable(struct_processus *s_etat_ (*((struct_variable *) (*(*l_variable_courante).feuille).variable)) = (*s_variable); - - if (((*((struct_variable *) (*(*l_variable_courante).feuille) - .variable)).nom = strdup((*s_variable).nom)) == NULL) - { - (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; - return(d_erreur); - } + pointeur_variable_cree = (*(*l_variable_courante).feuille).variable; } else { @@ -229,19 +618,27 @@ ajout_variable(struct_processus *s_etat_ BUG((*(*l_variable_candidate).variable).niveau == (*s_variable).niveau, - printf("Variable=\"%s\"\n", (*s_variable).nom)); + 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) { - // Ajout inconditionnel des variables de niveaux 0 et 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; } @@ -249,24 +646,31 @@ ajout_variable(struct_processus *s_etat_ (*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 = - malloc(sizeof(struct_variable))) == NULL) + allocation_variable(s_etat_processus)) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(d_erreur); } (*(*l_nouvelle_variable).variable) = (*s_variable); - - if (((*(*l_nouvelle_variable).variable).nom = - strdup((*s_variable).nom)) == NULL) - { - (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; - return(d_erreur); - } + pointeur_variable_cree = (*l_nouvelle_variable).variable; } } @@ -278,7 +682,7 @@ ajout_variable(struct_processus *s_etat_ { // Le niveau courant n'existe pas. Il est créé. - if ((l_nouvelle_variable = malloc(sizeof(struct_liste_variables))) + if ((l_nouvelle_variable = allocation_feuille(s_etat_processus)) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; @@ -287,8 +691,24 @@ ajout_variable(struct_processus *s_etat_ (*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) @@ -296,7 +716,7 @@ ajout_variable(struct_processus *s_etat_ { // Le niveau courant n'existe pas. Il est créé. - if ((l_nouvelle_variable = malloc(sizeof(struct_liste_variables))) + if ((l_nouvelle_variable = allocation_feuille(s_etat_processus)) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; @@ -307,54 +727,121 @@ ajout_variable(struct_processus *s_etat_ .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) + .precedent = l_nouvelle_variable; (*s_etat_processus).l_liste_variables_par_niveau = l_nouvelle_variable; - } - else - { - // Création d'une variable de niveau 0 ou 1 + + // 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; - if ((*((struct_variable *) (*(*(*(*s_etat_processus) - .l_liste_variables_par_niveau).precedent).liste).donnee)) - .niveau > 1) + for(i = 0; i <= 2; i++) { - // Ajout inconditionnel des variables de niveaux 0 et 1 + if ((*l_variable_candidate).liste == NULL) + { + 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; } - else + + if (niveau_acceptable == d_faux) { - l_variable_candidate = (*(*s_etat_processus) - .l_liste_variables_par_niveau).precedent; + 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; } - (*l_nouvelle_variable).suivant = l_variable_candidate; - (*l_nouvelle_variable).precedent = (*l_variable_candidate) - .precedent; - (*(*l_variable_candidate).precedent).suivant = l_nouvelle_variable; - (*l_variable_candidate).precedent = l_nouvelle_variable; - } + // Ajout de la variable en tête de la liste l_variable_candidate. - // 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); + } - if ((l_nouvel_element = malloc(sizeof(struct_liste_chainee))) == 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 - (*l_nouvel_element).suivant = (*(*s_etat_processus) - .l_liste_variables_par_niveau).liste; - (*l_nouvel_element).donnee = (struct_objet *) s_variable; - (*l_nouvelle_variable).liste = l_nouvel_element; + 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; + } return(d_absence_erreur); } + logical1 creation_variable(struct_processus *s_etat_processus, struct_variable *s_variable, @@ -502,14 +989,15 @@ recherche_variable(struct_processus *s_e unsigned char *ptr; - unsigned long niveau_appel; + integer8 niveau_appel; if ((*s_etat_processus).s_arbre_variables == NULL) { (*s_etat_processus).erreur_systeme = d_es_variable_introuvable; - return d_faux; + return(d_faux); } + l_variable_courante = (*s_etat_processus).s_arbre_variables; ptr = nom_variable; while((*ptr) != d_code_fin_chaine) @@ -519,16 +1007,19 @@ recherche_variable(struct_processus *s_e if (pointeur < 0) { // Caractère hors de l'alphabet des variables - return(d_erreur); + + (*s_etat_processus).erreur_systeme = d_es_variable_introuvable; + return(d_faux); } - if ((*l_variable_courante).noeud[pointeur] == NULL) + if ((*l_variable_courante).noeuds[pointeur] == NULL) { // Le chemin de la variable candidate n'existe pas. - return(d_erreur); + (*s_etat_processus).erreur_systeme = d_es_variable_introuvable; + return(d_faux); } - l_variable_courante = (*l_variable_courante).noeud[pointeur]; + l_variable_courante = (*l_variable_courante).noeuds[pointeur]; ptr++; } @@ -543,7 +1034,7 @@ recherche_variable(struct_processus *s_e { // Problème : la pile système est vide ! (*s_etat_processus).erreur_systeme = d_es_pile_vide; - return(d_erreur); + return(d_faux); } while((*l_element_courant).retour_definition != 'Y') @@ -553,7 +1044,7 @@ recherche_variable(struct_processus *s_e if (l_element_courant == NULL) { (*s_etat_processus).erreur_systeme = d_es_pile_vide; - return(d_erreur); + return(d_faux); } } @@ -568,7 +1059,7 @@ recherche_variable(struct_processus *s_e (*(*l_variable_courante).feuille).variable; (*s_etat_processus).pointeur_feuille_courante = (*l_variable_courante).feuille; - return(d_absence_erreur); + return(d_vrai); } else { @@ -585,29 +1076,102 @@ recherche_variable(struct_processus *s_e (*s_etat_processus).pointeur_variable_courante = (*(*(*l_variable_courante).feuille).precedent).variable; (*s_etat_processus).pointeur_feuille_courante = - (*l_variable_courante).feuille; + (*(*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).variable).niveau == 0) - && ((*(*(*(*l_variable_courante).feuille).precedent) + 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; + } + + case 1: + { + break; + } + + default: + { + if ((*(*(*(*s_etat_processus).pointeur_feuille_courante) + .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; + } + else if ((*(*(*(*(*s_etat_processus).pointeur_feuille_courante) + .precedent).precedent).variable).niveau == 1) + { (*s_etat_processus).pointeur_feuille_courante = - (*l_variable_courante).feuille; + (*(*(*s_etat_processus).pointeur_feuille_courante) + .precedent).precedent; + (*s_etat_processus).pointeur_variable_courante = + (*(*s_etat_processus).pointeur_feuille_courante) + .variable; + } + else + { + presence_variable = d_faux; } - return(d_absence_erreur); + break; } } } - return(d_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); } @@ -628,7 +1192,21 @@ logical1 retrait_variable(struct_processus *s_etat_processus, unsigned char *nom_variable, unsigned char type) { - logical1 erreur; + 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; + + integer8 niveau; + + (*s_etat_processus).niveau_supprime = d_faux; if (recherche_variable(s_etat_processus, nom_variable) == d_vrai) { @@ -686,7 +1264,7 @@ retrait_variable(struct_processus *s_eta erreur = d_erreur; (*s_etat_processus).erreur_execution = d_ex_variable_verrouillee; - return erreur; + return(erreur); } } @@ -698,23 +1276,201 @@ retrait_variable(struct_processus *s_eta // 2/ ces deux pointeurs sont différents et se contente de retirer // la structure décrivant la variable. - position_supprimee = (*s_etat_processus).position_variable_courante; + 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 + { + // Cas 2 : + // On retire la variable de la liste. + + variable_a_supprimer = (*s_etat_processus) + .pointeur_feuille_courante; - 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).pointeur_feuille_courante).precedent) + .suivant = (*(*s_etat_processus).pointeur_feuille_courante) + .suivant; + (*(*(*s_etat_processus).pointeur_feuille_courante).suivant) + .precedent = (*(*s_etat_processus) + .pointeur_feuille_courante).precedent; + + // Mise à jour du pointeur dans l'arbre des variables. Cette + // mise à jour n'est nécessaire que dans le cas où la variable + // supprimée est en tête de la liste. + + if (variable_a_supprimer == (*((*(*variable_a_supprimer).noeud_pere) + .noeuds[(*(*variable_a_supprimer).noeud) + .indice_tableau_pere])).feuille) + { + (*((*(*variable_a_supprimer).noeud_pere).noeuds + [(*(*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).nombre_variables--; + (*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; + } + + // Dans tous les cas, on retire la variable de la liste des variables + // par niveau. - for(position_courante = position_supprimee; - position_courante < (*s_etat_processus).nombre_variables; - position_courante++) + niveau = (*(*variable_a_supprimer).variable).niveau; + variables_par_niveau = (*s_etat_processus).l_liste_variables_par_niveau; + variable_supprimee = d_faux; + + if (variables_par_niveau != NULL) { - (*s_etat_processus).s_liste_variables[position_courante] = - (*s_etat_processus).s_liste_variables - [position_courante + 1]; + do + { + 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; } else @@ -744,109 +1500,162 @@ retrait_variable(struct_processus *s_eta */ logical1 -retrait_variable_par_niveau(struct_processus *s_etat_processus) +retrait_variables_par_niveau(struct_processus *s_etat_processus) { - unsigned long i; - unsigned long j; + struct_liste_variables *l_element_a_supprimer; - struct_variable *tampon; + // Utilisation du champ (*s_etat_processus).liste_variables_par_niveau. + // La tête de la pile contient toujours les variables de plus haut niveau + // créées. - for(j = 0, i = 0; i < (*s_etat_processus).nombre_variables; i++) + while((*s_etat_processus).l_liste_variables_par_niveau != NULL) { - if ((*s_etat_processus).s_liste_variables[i].niveau <= - (*s_etat_processus).niveau_courant) + if ((*(*s_etat_processus).l_liste_variables_par_niveau).liste == NULL) { - (*s_etat_processus).s_liste_variables[j++] = - (*s_etat_processus).s_liste_variables[i]; + // 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 { - if ((*s_etat_processus).s_liste_variables[i].origine == 'P') + // Le niveau contient des variables. + + if ((*((struct_variable *) (*(*(*s_etat_processus) + .l_liste_variables_par_niveau).liste).donnee)).niveau + <= (*s_etat_processus).niveau_courant) { - if ((*s_etat_processus).s_liste_variables[i] - .variable_statique.adresse != 0) - { - /* - * Gestion des variables statiques - */ - - 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 = - d_es_variable_introuvable; - } + // On a retiré de l'arbre des variables toutes les + // variables de niveau strictement supérieur au niveau + // courant. - (*s_etat_processus).s_liste_variables[i].objet = NULL; - } + break; } - else + + if (((*s_etat_processus).at_exit != NULL) && + ((*s_etat_processus).niveau_courant == 0)) + { + // Il y a une routine ATEXIT enregistrée. On ne détruit pas + // les variables globales qui pourraient y être utilisées. + + break; + } + + while((*(*s_etat_processus).l_liste_variables_par_niveau).liste + != NULL) { - if ((*s_etat_processus).s_liste_variables[i] - .variable_statique.pointeur != NULL) + // 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') { - /* - * Gestion des variables statiques - */ - - 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) + if ((*((struct_variable *) (*(*(*s_etat_processus) + .l_liste_variables_par_niveau).liste).donnee)) + .variable_statique.adresse != 0) { - (*s_etat_processus).s_liste_variables_statiques - [(*s_etat_processus) - .position_variable_statique_courante] - .objet = (*s_etat_processus) - .s_liste_variables[i].objet; + 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 + { + if ((*((struct_variable *) (*(*(*s_etat_processus) + .l_liste_variables_par_niveau).liste).donnee)) + .variable_statique.pointeur != NULL) { - (*s_etat_processus).erreur_systeme = - d_es_variable_introuvable; - return(d_erreur); + /* + * Gestion des variables statiques + */ + + 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; + return(d_erreur); + } + + (*((struct_variable *) (*(*(*s_etat_processus) + .l_liste_variables_par_niveau).liste).donnee)) + .objet = NULL; } + } + + if (retrait_variable(s_etat_processus, + (*((struct_variable *) (*(*(*s_etat_processus) + .l_liste_variables_par_niveau).liste).donnee)).nom, + 'L') == d_erreur) + { + return(d_erreur); + } + + if ((*((struct_variable *) (*(*(*s_etat_processus) + .l_liste_variables_par_niveau).liste).donnee)).niveau + <= (*s_etat_processus).niveau_courant) + { + // On a retiré de l'arbre des variables toutes les + // variables de niveau strictement supérieur au niveau + // courant. - (*s_etat_processus).s_liste_variables[i].objet = NULL; + return(d_absence_erreur); } } - - free((*s_etat_processus).s_liste_variables[i].nom); - liberation(s_etat_processus, - (*s_etat_processus).s_liste_variables[i].objet); } - } - (*s_etat_processus).nombre_variables = j; + // On retire l'élément de la liste doublement chaînée et circulaire. - if ((*s_etat_processus).nombre_variables < - ((*s_etat_processus).nombre_variables_allouees / 2)) - { - (*s_etat_processus).nombre_variables_allouees /= 2; - - if ((tampon = realloc((*s_etat_processus).s_liste_variables, - (*s_etat_processus).nombre_variables_allouees * - sizeof(struct_variable))) == NULL) - { - (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; - return(d_erreur); - } + (*(*(*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; - (*s_etat_processus).s_liste_variables = tampon; + 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); @@ -870,56 +1679,460 @@ void liberation_arbre_variables(struct_processus *s_etat_processus, struct_arbre_variables *arbre, logical1 retrait_definitions) { - int i; + 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; - struct_liste_chainee *l_element_courant; - struct_liste_chainee *l_element_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) + { + return; + } + + 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) + { + 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).noeud[i] != NULL) + if ((*arbre).noeuds[i] != NULL) { - l_element_courant = (*arbre).l_variables; + 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; - while(l_element_courant != NULL) + if (l_element_courant != NULL) + { + do { - l_element_suivant = (*l_element_courant).suivant; + l_element_courant_liste = (*l_element_courant).liste; - if (retrait_definitions == d_vrai) + while(l_element_courant_liste != NULL) { - liberation(s_etat_processus, (*((struct_variable *) - (*l_element_courant).donnee)).objet); - free((*((struct_variable *) (*l_element_courant) - .donnee)).nom); - free((struct_variable *) (*l_element_courant).donnee); - } - else - { - if ((*((struct_variable *) (*l_element_courant).donnee)) - .niveau >= 1) + if ((retrait_definitions == d_vrai) || + ((*((struct_variable *) (*l_element_courant_liste) + .donnee)).niveau >= 1)) { liberation(s_etat_processus, (*((struct_variable *) - (*l_element_courant).donnee)).objet); - free((*((struct_variable *) (*l_element_courant) + (*l_element_courant_liste).donnee)).objet); + free((*((struct_variable *) (*l_element_courant_liste) .donnee)).nom); - free((struct_variable *) (*l_element_courant).donnee); } + + 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; } - free(l_element_courant); + 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); + } + } + + liberation_tableau_noeuds(s_etat_processus, (*arbre).noeuds); + liberation_noeud(s_etat_processus, arbre); + arbre = NULL; + + return; +} + + +/* +================================================================================ + Procédure renvoyant les variables dans un tableau +================================================================================ + Entrée : +-------------------------------------------------------------------------------- + Sortie : +-------------------------------------------------------------------------------- + Effets de bord : néant +================================================================================ +*/ + +static integer8 +nombre_variables_locales(struct_processus *s_etat_processus, + struct_arbre_variables *l_element_courant) +{ + integer8 i; + integer8 n; + + struct_liste_variables *l_variable; + struct_liste_variables_statiques *l_variable_statique; + + if (l_element_courant == NULL) + { + 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 != (*l_element_courant).feuille); + } + + if ((*l_element_courant).feuille_statique != NULL) + { + l_variable_statique = (*l_element_courant).feuille_statique; + + do + { + // 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) + { + n++; } - liberation_arbre_variables(s_etat_processus, (*arbre).noeud[i]); + 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) + { + n += nombre_variables_locales(s_etat_processus, + (*l_element_courant).noeuds[i]); + } + } + + return(n); +} + + +static integer8 +nombre_variables_partagees(struct_processus *s_etat_processus, + struct_arbre_variables_partagees *l_element_courant) +{ + integer8 i; + 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]); } } - free((*arbre).noeud); - free(arbre); + 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]); + } + } + + 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 + { + tableau[position].origine = 'E'; + 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++; + + 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]); + } + } + + // 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 copie de l'arbre des variables @@ -932,13 +2145,299 @@ liberation_arbre_variables(struct_proces ================================================================================ */ -struct_arbre_variables * -copie_arbre_variables(struct_processus *s_etat_processus) +void +copie_arbre_variables(struct_processus *s_etat_processus, struct_processus + *s_nouvel_etat_processus) { // Les définitions sont partagées entre tous les threads et ne sont pas // 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. - return(d_absence_erreur); + // 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 s_variable; + struct_variable_statique s_variable_statique; + + 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) + { + l_niveau_courant = (*l_niveau_courant).precedent; + } + + // Les variables de niveaux 0 et 1 sont accessibles en au plus trois + // itérations (par construction). + + 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 (niveau_0_traite == d_faux) + { + l_element_courant = (*l_niveau_courant).liste; + + while(l_element_courant != NULL) + { + if (ajout_variable(s_nouvel_etat_processus, + (struct_variable *) (*l_element_courant).donnee) + == d_erreur) + { + return; + } + + l_element_courant = (*l_element_courant).suivant; + } + + niveau_0_traite = d_vrai; + } + } + else if ((*((struct_variable *) (*(*l_niveau_courant).liste) + .donnee)).niveau == 1) + { + if (niveau_1_traite == d_faux) + { + l_element_courant = (*l_niveau_courant).liste; + + while(l_element_courant != NULL) + { + s_variable = (*((struct_variable *) + (*l_element_courant).donnee)); + + if ((s_variable.nom = rpl_malloc(s_nouvel_etat_processus, + (strlen((*((struct_variable *) + (*l_element_courant).donnee)).nom) + 1) * + sizeof(unsigned char))) == NULL) + { + (*s_nouvel_etat_processus).erreur_systeme = + d_es_allocation_memoire; + return; + } + + 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) + { + return; + } + + l_element_courant = (*l_element_courant).suivant; + } + + niveau_1_traite = d_vrai; + } + + // Les variables de niveau 0 ayant déjà été copiées, on + // peut sortir de la boucle car toutes les variables sont + // maintenant disponibles dans le fil d'exécution fils. + + break; + } + + l_niveau_courant = (*l_niveau_courant).precedent; + } + + // Copie des variables statiques + + l_element_statique_courant = (*s_etat_processus) + .l_liste_variables_statiques; + + while(l_element_statique_courant != NULL) + { + // Création des branches de l'arbre si nécessaire. + + if ((*s_nouvel_etat_processus).s_arbre_variables == 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; + return; + } + + 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; } @@ -955,7 +2454,7 @@ copie_arbre_variables(struct_processus * */ /* - * Caractères autorisés dans les instructions + * 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 @@ -985,7 +2484,7 @@ initialisation_variables(struct_processu } if (((*s_etat_processus).pointeurs_caracteres_variables = - malloc(longueur_tableau * sizeof(int))) == NULL) + malloc(((size_t) longueur_tableau) * sizeof(int))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return;