--- rpl/src/gestion_variables.c 2011/06/17 07:55:59 1.31 +++ rpl/src/gestion_variables.c 2011/06/20 17:54:15 1.35 @@ -1,6 +1,6 @@ /* ================================================================================ - RPL/2 (R) version 4.1.0.prerelease.0 + RPL/2 (R) version 4.1.0.prerelease.1 Copyright (C) 1989-2011 Dr. BERTRAND Joël This file is part of RPL/2. @@ -25,13 +25,208 @@ /* ================================================================================ + 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, %d) ", ((struct_variable *) e->donnee)->nom, + 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, %d) ", ((struct_variable *) e->donnee)->nom, + 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 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,8 +239,11 @@ ajout_variable(struct_processus *s_etat_ { 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; @@ -173,11 +371,14 @@ ajout_variable(struct_processus *s_etat_ 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. @@ -219,6 +420,7 @@ ajout_variable(struct_processus *s_etat_ (*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 = @@ -256,13 +458,21 @@ ajout_variable(struct_processus *s_etat_ } 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; } @@ -271,9 +481,21 @@ ajout_variable(struct_processus *s_etat_ (*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) { @@ -307,6 +529,20 @@ ajout_variable(struct_processus *s_etat_ (*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 = malloc(sizeof(struct_liste_chainee))) == 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) @@ -329,54 +565,112 @@ ajout_variable(struct_processus *s_etat_ (*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 if ((*s_variable).niveau <= 1) - { - // Création d'une variable de niveau 0 ou 1 - if ((l_nouvelle_variable = malloc(sizeof(struct_liste_variables))) - == NULL) + // Ajout de la variable en tête de la liste + + 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 = (*(*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++) { - l_variable_candidate = (*(*s_etat_processus) - .l_liste_variables_par_niveau).precedent; + 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; } - (*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; - } + if (niveau_acceptable == d_faux) + { + 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) + .precedent; - // Ajout de la variable en tête de la liste + // 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. - if ((l_nouvel_element = malloc(sizeof(struct_liste_chainee))) == NULL) - { - (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; - return(d_erreur); + 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 = 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 + + 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 = (*(*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; + (*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); } @@ -616,21 +910,23 @@ 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) - .variable; + (*(*(*(*l_variable_courante).feuille).precedent) + .precedent).variable; (*s_etat_processus).pointeur_feuille_courante = - (*l_variable_courante).feuille; + (*(*(*l_variable_courante).feuille).precedent) + .precedent; } return(d_vrai); @@ -657,9 +953,7 @@ recherche_variable_globale(struct_proces { case 0: { - // Nous sommes en présence d'une définition et non d'une - // variable. - + // La variable est une définition. presence_variable = d_faux; break; } @@ -733,6 +1027,7 @@ retrait_variable(struct_processus *s_eta unsigned char *nom_variable, unsigned char type) { logical1 erreur; + logical1 variable_supprimee; struct_arbre_variables *s_arbre_a_supprimer; struct_arbre_variables *s_arbre_courant; @@ -825,12 +1120,16 @@ retrait_variable(struct_processus *s_eta variable_a_supprimer = (*s_etat_processus) .pointeur_feuille_courante; - s_arbre_courant = (*variable_a_supprimer).noeud_pere; - + //s_arbre_courant = (*variable_a_supprimer).noeud_pere; + 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_a_supprimer = s_arbre_courant; @@ -840,6 +1139,8 @@ retrait_variable(struct_processus *s_eta { free((*s_arbre_a_supprimer).noeuds); free(s_arbre_a_supprimer); + + (*s_etat_processus).s_arbre_variables = NULL; break; } @@ -875,6 +1176,26 @@ retrait_variable(struct_processus *s_eta (*(*(*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).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 @@ -882,6 +1203,7 @@ retrait_variable(struct_processus *s_eta 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) { @@ -920,6 +1242,33 @@ retrait_variable(struct_processus *s_eta } free(l_element_courant); + + if ((*variables_par_niveau).liste == NULL) + { + 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; + free(variables_par_niveau); + } + + variable_supprimee = d_vrai; break; } @@ -929,6 +1278,11 @@ retrait_variable(struct_processus *s_eta } } + if (variable_supprimee == d_vrai) + { + break; + } + variables_par_niveau = (*variables_par_niveau).suivant; } while(variables_par_niveau != (*s_etat_processus) @@ -939,6 +1293,8 @@ retrait_variable(struct_processus *s_eta free((*(*variable_a_supprimer).variable).nom); liberation(s_etat_processus, (*(*variable_a_supprimer).variable).objet); + free((*variable_a_supprimer).variable); + free(variable_a_supprimer); erreur = d_absence_erreur; } @@ -1003,6 +1359,8 @@ retrait_variable_par_niveau(struct_proce while((*(*s_etat_processus).l_liste_variables_par_niveau).liste != 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) @@ -1090,6 +1448,17 @@ retrait_variable_par_niveau(struct_proce { 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. + + return(d_absence_erreur); + } } } @@ -1140,6 +1509,11 @@ liberation_arbre_variables(struct_proces // 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) @@ -1209,6 +1583,95 @@ liberation_arbre_variables(struct_proces /* ================================================================================ + Procédure renvoyant les variables dans un tableau +================================================================================ + Entrée : +-------------------------------------------------------------------------------- + Sortie : +-------------------------------------------------------------------------------- + Effets de bord : néant +================================================================================ +*/ + +int +nombre_variables(struct_processus *s_etat_processus, + struct_arbre_variables *l_element_courant) +{ + int i; + int n; + + struct_liste_variables *l_variable; + + 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); + } + + for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++) + { + if ((*l_element_courant).noeuds[i] != NULL) + { + n += nombre_variables(s_etat_processus, + (*l_element_courant).noeuds[i]); + } + } + + return(n); +} + +int +liste_variables(struct_processus *s_etat_processus, + struct_tableau_variables *tableau, int position, + struct_arbre_variables *l_element_courant) +{ + int i; + + struct_liste_variables *l_variable; + + 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; + + position++; + l_variable = (*l_variable).suivant; + } while(l_variable != (*l_element_courant).feuille); + } + + for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++) + { + if ((*l_element_courant).noeuds[i] != NULL) + { + position = liste_variables(s_etat_processus, + tableau, position, (*l_element_courant).noeuds[i]); + } + } + + return(position); +} + +/* +================================================================================ Procédure de copie de l'arbre des variables ================================================================================ Entrée :