--- rpl/src/gestion_variables.c 2011/06/01 18:17:35 1.27 +++ rpl/src/gestion_variables.c 2011/06/08 13:35:15 1.28 @@ -44,10 +44,10 @@ ajout_variable(struct_processus *s_etat_ { int i; - struct_arbre_variables *l_variable_courante; - 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; @@ -64,6 +64,7 @@ ajout_variable(struct_processus *s_etat_ (*(*s_etat_processus).s_arbre_variables).feuille = NULL; (*(*s_etat_processus).s_arbre_variables).noeuds_utilises = 0; + (*(*s_etat_processus).s_arbre_variables).noeud_pere = NULL; if (((*(*s_etat_processus).arbre_instructions).noeud = malloc((*s_etat_processus).nombre_caracteres_variables @@ -75,10 +76,11 @@ 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; @@ -88,12 +90,12 @@ ajout_variable(struct_processus *s_etat_ printf("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. - 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) { @@ -101,13 +103,17 @@ ajout_variable(struct_processus *s_etat_ return(d_erreur); } - (*(*l_variable_courante).noeud[(*s_etat_processus) + (*l_variable_courante).noeuds_utilises++; + (*(*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]]).noeuds_utilises = 0; + (*(*l_variable_courante).noeuds[(*s_etat_processus) + .pointeurs_caracteres_variables[*ptr]]).noeud_pere = + l_variable_precedente; - if (((*(*l_variable_courante).noeud[(*s_etat_processus) - .pointeurs_caracteres_variables[*ptr]]).noeud = + if (((*(*l_variable_courante).noeuds[(*s_etat_processus) + .pointeurs_caracteres_variables[*ptr]]).noeuds = malloc((*s_etat_processus).nombre_caracteres_variables * sizeof(struct_arbre_variables))) == NULL) { @@ -117,13 +123,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++; } @@ -146,6 +153,7 @@ ajout_variable(struct_processus *s_etat_ (*l_variable_courante).feuille; (*(*l_variable_courante).feuille).precedent = (*l_variable_courante).feuille; + (*(*l_variable_courante).feuille).noeud_pere = l_variable_precedente; // Allocation de la variable sur l'élément de la liste. @@ -168,6 +176,13 @@ ajout_variable(struct_processus *s_etat_ } else { + if ((l_nouvelle_variable = malloc(sizeof(struct_liste_variables))) + == NULL) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return(d_erreur); + } + if ((*s_variable).niveau > 1) { // Cas d'une variable locale @@ -182,16 +197,10 @@ ajout_variable(struct_processus *s_etat_ // 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_variable_courante).feuille).precedent).suivant = l_nouvelle_variable; (*(*l_variable_courante).feuille).precedent = @@ -249,6 +258,7 @@ 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_variable_candidate).precedent).suivant = l_nouvelle_variable; (*l_variable_candidate).precedent = l_nouvelle_variable; @@ -287,6 +297,7 @@ 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; (*s_etat_processus).l_liste_variables_par_niveau = l_nouvelle_variable; } @@ -307,6 +318,7 @@ 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; (*(*(*s_etat_processus).l_liste_variables_par_niveau).precedent) .suivant = l_nouvelle_variable; (*(*s_etat_processus).l_liste_variables_par_niveau).precedent = @@ -318,6 +330,13 @@ ajout_variable(struct_processus *s_etat_ { // Création d'une variable de niveau 0 ou 1 + if ((l_nouvelle_variable = malloc(sizeof(struct_liste_variables))) + == NULL) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return(d_erreur); + } + l_variable_candidate = (*s_etat_processus).l_liste_variables_par_niveau; if ((*((struct_variable *) (*(*(*(*s_etat_processus) @@ -335,6 +354,7 @@ 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 = NULL; (*(*l_variable_candidate).precedent).suivant = l_nouvelle_variable; (*l_variable_candidate).precedent = l_nouvelle_variable; } @@ -510,6 +530,7 @@ recherche_variable(struct_processus *s_e return d_faux; } + l_variable_courante = (*s_etat_processus).s_arbre_variables; ptr = nom_variable; while((*ptr) != d_code_fin_chaine) @@ -522,13 +543,13 @@ recherche_variable(struct_processus *s_e return(d_erreur); } - 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); } - l_variable_courante = (*l_variable_courante).noeud[pointeur]; + l_variable_courante = (*l_variable_courante).noeuds[pointeur]; ptr++; } @@ -628,7 +649,18 @@ logical1 retrait_variable(struct_processus *s_etat_processus, unsigned char *nom_variable, unsigned char type) { - logical1 erreur; + logical1 erreur; + + 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; + + unsigned long niveau; if (recherche_variable(s_etat_processus, nom_variable) == d_vrai) { @@ -686,7 +718,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 +730,113 @@ 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_pere; + + BUG((*s_arbre_courant).noeuds_utilises == 0, + uprintf("Freed node !\n")); + (*s_arbre_courant).noeuds_utilises--; - liberation(s_etat_processus, (*s_etat_processus).s_liste_variables - [position_supprimee].objet); - free((*s_etat_processus).s_liste_variables[position_supprimee].nom); + while((*s_arbre_courant).noeuds_utilises == 0) + { + s_arbre_a_supprimer = s_arbre_courant; + s_arbre_courant = (*s_arbre_courant).noeud_pere; - (*s_etat_processus).nombre_variables--; + free((*s_arbre_a_supprimer).noeuds); + free(s_arbre_a_supprimer); - for(position_courante = position_supprimee; - position_courante < (*s_etat_processus).nombre_variables; - position_courante++) + if (s_arbre_courant == NULL) + { + break; + } + + BUG((*s_arbre_courant).noeuds_utilises == 0, + uprintf("Freed node !\n")); + (*s_arbre_courant).noeuds_utilises--; + } + } + else { - (*s_etat_processus).s_liste_variables[position_courante] = - (*s_etat_processus).s_liste_variables - [position_courante + 1]; + // Cas 2 : + // On retire la variable de la liste. + + variable_a_supprimer = (*s_etat_processus) + .pointeur_feuille_courante; + + (*(*(*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; } + // Dans tous les cas, on retire la variable de la liste des variables + // par niveau. + + niveau = (*(*variable_a_supprimer).variable).niveau; + variables_par_niveau = (*s_etat_processus).l_liste_variables_par_niveau; + + while(variables_par_niveau != NULL) + { + 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; + } + } + + l_element_precedent = l_element_courant; + l_element_courant = (*l_element_courant).suivant; + } + } + } + + variables_par_niveau = (*variables_par_niveau).suivant; + } + + // Puis on libère le contenu de la variable. + + free((*(*variable_a_supprimer).variable).nom); + liberation(s_etat_processus, (*(*variable_a_supprimer).variable).objet); + erreur = d_absence_erreur; } else @@ -746,107 +868,133 @@ retrait_variable(struct_processus *s_eta logical1 retrait_variable_par_niveau(struct_processus *s_etat_processus) { - unsigned long i; - unsigned long j; + // 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. - struct_variable *tampon; + struct_liste_variables *l_niveau_suivant; - 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) + l_niveau_suivant = (*(*s_etat_processus).l_liste_variables_par_niveau) + .suivant; + + 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 + + while((*(*s_etat_processus).l_liste_variables_par_niveau).liste + != NULL) { - if ((*s_etat_processus).s_liste_variables[i] - .variable_statique.pointeur != NULL) + // 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') == d_vrai) + { + (*s_etat_processus).s_liste_variables_statiques + [(*s_etat_processus) + .position_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') == d_vrai) + { + (*s_etat_processus).s_liste_variables_statiques + [(*s_etat_processus) + .position_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; } + } - (*s_etat_processus).s_liste_variables[i].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); } } - - 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; - - 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).s_liste_variables = tampon; + free((*s_etat_processus).l_liste_variables_par_niveau); + (*s_etat_processus).l_liste_variables_par_niveau = l_niveau_suivant; } return(d_absence_erreur); @@ -872,54 +1020,75 @@ liberation_arbre_variables(struct_proces { int i; - struct_liste_chainee *l_element_courant; - struct_liste_chainee *l_element_suivant; + 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; + + // 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. 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; + l_element_courant = (*arbre).feuille; while(l_element_courant != NULL) { l_element_suivant = (*l_element_courant).suivant; + free(l_element_courant); + l_element_courant = l_element_suivant; + } + + liberation_arbre_variables(s_etat_processus, (*arbre).noeuds[i], + retrait_definitions); + } + } + + // 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) + { + l_element_courant_liste = (*l_element_courant).liste; - if (retrait_definitions == d_vrai) + while(l_element_courant_liste != NULL) + { + 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); - } - else - { - if ((*((struct_variable *) (*l_element_courant).donnee)) - .niveau >= 1) - { - 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); - } + free((*l_element_courant_liste).donnee); } - free(l_element_courant); - l_element_courant = l_element_suivant; + l_element_suivant_liste = (*l_element_courant_liste).suivant; + free(l_element_courant_liste); + l_element_courant_liste = l_element_suivant_liste; } - liberation_arbre_variables(s_etat_processus, (*arbre).noeud[i]); + l_element_suivant = (*l_element_courant).suivant; + free(l_element_courant); + l_element_courant = l_element_suivant; } } - free((*arbre).noeud); + free((*arbre).noeuds); free(arbre); return; } + /* ================================================================================ Procédure de copie de l'arbre des variables @@ -937,6 +1106,12 @@ copie_arbre_variables(struct_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 sont inaccessibles. + + BUG(1, uprintf("Oops !\n")); return(d_absence_erreur); }