--- rpl/src/gestion_variables.c 2011/04/14 13:18:54 1.24 +++ rpl/src/gestion_variables.c 2011/06/19 17:48:27 1.33 @@ -25,13 +25,178 @@ /* ================================================================================ + 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"); + + 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).feuille != NULL) + { + printf("Feuille %p\n", (*arbre).feuille); + + 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); + } + + 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 : -------------------------------------------------------------------------------- @@ -39,52 +204,433 @@ ================================================================================ */ -logical1 -creation_variable(struct_processus *s_etat_processus, - struct_variable *s_variable, - unsigned char autorisation_creation_variable_statique, - unsigned char autorisation_creation_variable_partagee) +static logical1 +ajout_variable(struct_processus *s_etat_processus, struct_variable *s_variable) { - logical1 presence; + int i; + + logical1 niveau_acceptable; + + struct_liste_variables *l_nouvelle_variable; + struct_liste_variables *l_variable_candidate; + + struct_arbre_variables *l_variable_courante; + struct_arbre_variables *l_variable_precedente; + + struct_liste_chainee *l_nouvel_element; + + unsigned char *ptr; + + void *pointeur_variable_cree; + + if ((*s_etat_processus).s_arbre_variables == NULL) + { + if (((*s_etat_processus).s_arbre_variables = + malloc(sizeof(struct_arbre_variables))) == 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).noeuds_utilises = 0; + (*(*s_etat_processus).s_arbre_variables).indice_tableau_pere = -1; + (*(*s_etat_processus).s_arbre_variables).noeud_pere = NULL; + + if (((*(*s_etat_processus).s_arbre_variables).noeuds = + malloc((*s_etat_processus).nombre_caracteres_variables + * sizeof(struct_arbre_variables))) == NULL) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return(d_erreur); + } + + for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++) + { + (*(*s_etat_processus).s_arbre_variables).noeuds[i] = NULL; + } + } + + l_variable_precedente = NULL; + l_variable_courante = (*s_etat_processus).s_arbre_variables; + ptr = (*s_variable).nom; - long i; + while((*ptr) != d_code_fin_chaine) + { + BUG((*s_etat_processus).pointeurs_caracteres_variables[*ptr] < 0, + printf("Variable=\"%s\", (*ptr)='%c'\n", (*s_variable).nom, + *ptr)); + + if ((*l_variable_courante).noeuds[(*s_etat_processus) + .pointeurs_caracteres_variables[*ptr]] == NULL) + { + // Le noeud n'existe pas encore, on le crée et on le marque + // comme utilisé dans la structure parente. + + if (((*l_variable_courante).noeuds[(*s_etat_processus) + .pointeurs_caracteres_variables[*ptr]] = + malloc(sizeof(struct_arbre_variables))) == NULL) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return(d_erreur); + } + + (*l_variable_courante).noeuds_utilises++; + + // La feuille est par défaut vide et aucun élément du tableau noeuds + // (les branches qui peuvent être issues de ce nouveau noeud) + // n'est encore utilisée. + + (*(*l_variable_courante).noeuds[(*s_etat_processus) + .pointeurs_caracteres_variables[*ptr]]).feuille = NULL; + (*(*l_variable_courante).noeuds[(*s_etat_processus) + .pointeurs_caracteres_variables[*ptr]]).noeuds_utilises = 0; + + // Le champ noeud_pere de la structure créée pointe sur + // la structure parente et l'indice tableau_pere correspond à la + // position réelle dans le tableau noeuds[] de la structure parente + // du noeud courant. Cette valeur sera utilisée lors de la + // destruction du noeud pour annuler le pointeur contenu dans + // le tableau noeuds[] de la structure parente. + + (*(*l_variable_courante).noeuds[(*s_etat_processus) + .pointeurs_caracteres_variables[*ptr]]).noeud_pere = + l_variable_courante; + (*(*l_variable_courante).noeuds[(*s_etat_processus) + .pointeurs_caracteres_variables[*ptr]]) + .indice_tableau_pere = (*s_etat_processus) + .pointeurs_caracteres_variables[*ptr]; + + // Allocation du tableau noeuds[] et initialisation à zéro de + // tous les pointeurs. + + if (((*(*l_variable_courante).noeuds[(*s_etat_processus) + .pointeurs_caracteres_variables[*ptr]]).noeuds = + malloc((*s_etat_processus).nombre_caracteres_variables + * sizeof(struct_arbre_variables))) == NULL) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return(d_erreur); + } - struct_variable *s_nouvelle_base; + for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++) + { + (*(*l_variable_courante).noeuds[(*s_etat_processus) + .pointeurs_caracteres_variables[*ptr]]).noeuds[i] + = NULL; + } + } - (*s_etat_processus).nombre_variables++; + l_variable_precedente = l_variable_courante; + l_variable_courante = (*l_variable_courante).noeuds + [(*s_etat_processus).pointeurs_caracteres_variables[*ptr]]; + ptr++; + } - if ((*s_etat_processus).nombre_variables > (*s_etat_processus) - .nombre_variables_allouees) + if ((*l_variable_courante).feuille == NULL) { - // La nouvelle variable ne tient pas dans la table courante. Il - // faut donc en augmenter la taille. + // Aucune variable de même nom préexiste. On alloue le premier + // élément de la liste doublement chaînée contenant toutes les + // variables de même nom. Cette liste boucle en premier lieu sur + // elle-même. - if ((*s_etat_processus).nombre_variables_allouees == 0) + if (((*l_variable_courante).feuille = malloc( + sizeof(struct_liste_variables))) == NULL) { - (*s_etat_processus).nombre_variables_allouees = - (*s_etat_processus).nombre_variables; + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return(d_erreur); + } + + (*(*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) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return(d_erreur); + } + + (*((struct_variable *) (*(*l_variable_courante).feuille).variable)) = + (*s_variable); + pointeur_variable_cree = (*(*l_variable_courante).feuille).variable; + } + else + { + 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 + + // Si le niveau de la dernière variable de même nom est + // supérieur au niveau de la variable locale que l'on veut + // enregistrer dans la liste, cette liste est incohérente. + + BUG((*(*(*l_variable_courante).feuille).variable).niveau >= + (*s_variable).niveau, + printf("Variable=\"%s\"\n", (*s_variable).nom)); + + // On ajoute la variable à la liste existante. + + (*l_nouvelle_variable).suivant = (*l_variable_courante).feuille; + (*l_nouvelle_variable).precedent = (*(*l_variable_courante).feuille) + .precedent; + (*l_nouvelle_variable).noeud_pere = l_variable_precedente; + (*l_nouvelle_variable).noeud = l_variable_courante; + (*(*(*l_variable_courante).feuille).precedent).suivant = + l_nouvelle_variable; + (*(*l_variable_courante).feuille).precedent = + l_nouvelle_variable; + (*l_variable_courante).feuille = l_nouvelle_variable; + + if (((*(*l_variable_courante).feuille).variable = + malloc(sizeof(struct_variable))) == NULL) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return(d_erreur); + } + + (*((struct_variable *) (*(*l_variable_courante).feuille).variable)) + = (*s_variable); + pointeur_variable_cree = (*(*l_variable_courante).feuille).variable; } else { - while((*s_etat_processus).nombre_variables > - (*s_etat_processus).nombre_variables_allouees) + // Cas d'une variable globale (niveau 0 [définitions] ou 1 + // [variables globales]) + + l_variable_candidate = (*l_variable_courante).feuille; + + do + { + // S'il y a déjà une variable de même niveau, la pile + // est incohérente. + + BUG((*(*l_variable_candidate).variable).niveau == + (*s_variable).niveau, + printf("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)); + + if ((*(*(*(*l_variable_courante).feuille).precedent).variable) + .niveau > 1) { - (*s_etat_processus).nombre_variables_allouees *= 2; + // Ajout inconditionnel des variables de niveaux 0 et 1 } + else + { + l_variable_candidate = (*(*l_variable_courante).feuille) + .precedent; + } + + (*l_nouvelle_variable).suivant = l_variable_candidate; + (*l_nouvelle_variable).precedent = (*l_variable_candidate) + .precedent; + (*l_nouvelle_variable).noeud_pere = l_variable_precedente; + (*l_nouvelle_variable).noeud = l_variable_courante; + (*(*l_variable_candidate).precedent).suivant = l_nouvelle_variable; + (*l_variable_candidate).precedent = l_nouvelle_variable; + + if (((*l_nouvelle_variable).variable = + malloc(sizeof(struct_variable))) == NULL) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return(d_erreur); + } + + (*(*l_nouvelle_variable).variable) = (*s_variable); + pointeur_variable_cree = (*l_nouvelle_variable).variable; + } + } + + // Ajout de la variable nouvellement créée à la liste par niveaux. + // Le pointeur contenu dans la structure de description du processus indique + // toujours le plus haut niveau utilisé. + + if ((*s_etat_processus).l_liste_variables_par_niveau == NULL) + { + // Le niveau courant n'existe pas. Il est créé. + + if ((l_nouvelle_variable = malloc(sizeof(struct_liste_variables))) + == NULL) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return(d_erreur); } - if ((s_nouvelle_base = realloc((*s_etat_processus).s_liste_variables, - (*s_etat_processus).nombre_variables_allouees * - sizeof(struct_variable))) == NULL) + (*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 = malloc(sizeof(struct_liste_chainee))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; - (*s_etat_processus).nombre_variables--; return(d_erreur); } - (*s_etat_processus).s_liste_variables = s_nouvelle_base; + (*l_nouvel_element).suivant = (*(*s_etat_processus) + .l_liste_variables_par_niveau).liste; + (*l_nouvel_element).donnee = pointeur_variable_cree; + (*(*s_etat_processus).l_liste_variables_par_niveau).liste = + l_nouvel_element; } + else if ((*s_variable).niveau > (*((struct_variable *) + (*(*(*s_etat_processus).l_liste_variables_par_niveau).liste) + .donnee)).niveau) + { + // Le niveau courant n'existe pas. Il est créé. + + if ((l_nouvelle_variable = malloc(sizeof(struct_liste_variables))) + == NULL) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return(d_erreur); + } + + (*l_nouvelle_variable).suivant = (*s_etat_processus) + .l_liste_variables_par_niveau; + (*l_nouvelle_variable).precedent = (*(*s_etat_processus) + .l_liste_variables_par_niveau).precedent; + (*l_nouvelle_variable).noeud_pere = NULL; + (*l_nouvelle_variable).liste = NULL; + (*(*(*s_etat_processus).l_liste_variables_par_niveau).precedent) + .suivant = l_nouvelle_variable; + (*(*s_etat_processus).l_liste_variables_par_niveau) + .precedent = l_nouvelle_variable; + + (*s_etat_processus).l_liste_variables_par_niveau = l_nouvelle_variable; + + // Ajout de la variable en tête de la liste + + if ((l_nouvel_element = 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; + + for(i = 0; i <= 2; i++) + { + 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; + } + + 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; + + // On ne peut créer qu'une variable de niveau supérieur ou égal à + // 1 lors de l'exécution normale d'un programme. Les variables + // de niveau 0 sont créées à l'initialisation et relèvent du + // cas précédent car il n'existe lors de leur création aucun + // niveau non nul. + + BUG((*s_variable).niveau == 0, + uprintf("Attempt to create a level-0 variable!\n")); + + (*l_nouvelle_variable).suivant = l_variable_candidate; + (*l_nouvelle_variable).precedent = (*l_variable_candidate) + .precedent; + (*l_nouvelle_variable).noeud_pere = NULL; + (*l_nouvelle_variable).liste = NULL; + (*(*l_variable_candidate).precedent).suivant = l_nouvelle_variable; + (*l_variable_candidate).precedent = l_nouvelle_variable; + + l_variable_candidate = l_nouvelle_variable; + } + + // Ajout de la variable en tête de la liste l_variable_candidate. + if ((l_nouvel_element = 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; + } + + return(d_absence_erreur); +} + + +logical1 +creation_variable(struct_processus *s_etat_processus, + struct_variable *s_variable, + unsigned char autorisation_creation_variable_statique, + unsigned char autorisation_creation_variable_partagee) +{ if ((*s_etat_processus).mode_execution_programme == 'Y') { (*s_variable).origine = 'P'; @@ -190,68 +736,13 @@ creation_variable(struct_processus *s_et } /* - * Positionnement de la variable au bon endroit + * Recherche de la feuille correspondante dans l'arbre des variables. + * Si cette feuille n'existe pas, elle est créée. */ - // Nous avons (*s_etat_processus).nombre_variables - 1 variables dans la - // table qui sera balayée de la fin vers le début. - - if ((*s_etat_processus).nombre_variables == 1) + if (ajout_variable(s_etat_processus, s_variable) == d_erreur) { - (*s_etat_processus).s_liste_variables[0] = (*s_variable); - } - else - { - for(i = (*s_etat_processus).nombre_variables - 2; i >= 0; i--) - { - if (strcmp((*s_variable).nom, - (*s_etat_processus).s_liste_variables[i].nom) < 0) - { - (*s_etat_processus).s_liste_variables[i + 1] = - (*s_etat_processus).s_liste_variables[i]; - } - else - { - break; - } - } - - if ((*s_variable).niveau > 1) - { - // Cas d'une variable locale - (*s_etat_processus).s_liste_variables[i + 1] = (*s_variable); - } - else - { - // Cas d'une variable globale - presence = d_faux; - - for(; i >= 0; i--) - { - if ((strcmp((*s_variable).nom, - (*s_etat_processus).s_liste_variables[i].nom) == 0) - && ((*s_etat_processus).s_liste_variables[i].niveau - != 0)) - { - (*s_etat_processus).s_liste_variables[i + 1] = - (*s_etat_processus).s_liste_variables[i]; - } - else - { - presence = d_vrai; - break; - } - } - - if (presence == d_faux) - { - (*s_etat_processus).s_liste_variables[0] = (*s_variable); - } - else - { - (*s_etat_processus).s_liste_variables[i + 1] = (*s_variable); - } - } + return(d_erreur); } return(d_absence_erreur); @@ -260,10 +751,9 @@ creation_variable(struct_processus *s_et /* ================================================================================ - Procédure de retrait d'une variable de la base + Procédure de recherche d'une variable par son nom dans la base ================================================================================ - Entrée : type 'G' ou 'L' selon que l'on retire une variable locale (incluant - les globales) ou strictement globale. + Entrée : -------------------------------------------------------------------------------- Sortie : -------------------------------------------------------------------------------- @@ -272,118 +762,208 @@ creation_variable(struct_processus *s_et */ logical1 -retrait_variable(struct_processus *s_etat_processus, - unsigned char *nom_variable, unsigned char type) +recherche_variable(struct_processus *s_etat_processus, + unsigned char *nom_variable) { - struct_variable *s_nouvelle_base; + int pointeur; - logical1 erreur; + struct_arbre_variables *l_variable_courante; + struct_liste_pile_systeme *l_element_courant; - unsigned long position_courante; - unsigned long position_supprimee; + unsigned char *ptr; - if (recherche_variable(s_etat_processus, nom_variable) == d_vrai) + unsigned long niveau_appel; + + if ((*s_etat_processus).s_arbre_variables == NULL) { - if (type == 'G') + (*s_etat_processus).erreur_systeme = d_es_variable_introuvable; + return(d_faux); + } + + l_variable_courante = (*s_etat_processus).s_arbre_variables; + ptr = nom_variable; + + while((*ptr) != d_code_fin_chaine) + { + pointeur = (*s_etat_processus).pointeurs_caracteres_variables[*ptr]; + + if (pointeur < 0) { - if ((*s_etat_processus).position_variable_courante > 0) - { - while(strcmp((*s_etat_processus).s_liste_variables - [(*s_etat_processus).position_variable_courante] - .nom, nom_variable) == 0) - { - (*s_etat_processus).position_variable_courante--; + // Caractère hors de l'alphabet des variables - if ((*s_etat_processus).position_variable_courante >= - (*s_etat_processus).nombre_variables) - { - erreur = d_erreur; - (*s_etat_processus).erreur_execution = - d_ex_variable_non_definie; - return erreur; - } - } + (*s_etat_processus).erreur_systeme = d_es_variable_introuvable; + return(d_faux); + } - (*s_etat_processus).position_variable_courante++; - } + if ((*l_variable_courante).noeuds[pointeur] == NULL) + { + // Le chemin de la variable candidate n'existe pas. + (*s_etat_processus).erreur_systeme = d_es_variable_introuvable; + return(d_faux); + } - if ((*s_etat_processus).s_liste_variables - [(*s_etat_processus).position_variable_courante] - .niveau != 1) - { - erreur = d_erreur; - (*s_etat_processus).erreur_execution = - d_ex_variable_non_definie; - return erreur; - } + l_variable_courante = (*l_variable_courante).noeuds[pointeur]; + ptr++; + } - if ((*s_etat_processus).s_liste_variables - [(*s_etat_processus).position_variable_courante] - .variable_verrouillee == d_vrai) + if ((*l_variable_courante).feuille != NULL) + { + // Il existe une pile de variables de même nom. Le sommet de la + // pile est la variable de niveau le plus haut. + + l_element_courant = (*s_etat_processus).l_base_pile_systeme; + + if (l_element_courant == NULL) + { + // Problème : la pile système est vide ! + (*s_etat_processus).erreur_systeme = d_es_pile_vide; + return(d_faux); + } + + while((*l_element_courant).retour_definition != 'Y') + { + l_element_courant = (*l_element_courant).suivant; + + if (l_element_courant == NULL) { - erreur = d_erreur; - (*s_etat_processus).erreur_execution = - d_ex_variable_verrouillee; - return erreur; + (*s_etat_processus).erreur_systeme = d_es_pile_vide; + return(d_faux); } } - if ((*s_etat_processus).nombre_variables < - ((*s_etat_processus).nombre_variables_allouees / 2)) + niveau_appel = (*l_element_courant).niveau_courant; + + if (niveau_appel < (*(*(*l_variable_courante).feuille).variable).niveau) { - (*s_etat_processus).nombre_variables_allouees /= 2; + // Une variable locale est accessible puisque créée dans la + // fonction courante. - // (*s_etat_processus).nombre_variables est forcément - // supérieur à 1 (la décrémentation est postérieure). Ce test - // est vrai lorsque le nombre de variables allouées est - // strictement supérieur à 2. + (*s_etat_processus).pointeur_variable_courante = + (*(*l_variable_courante).feuille).variable; + (*s_etat_processus).pointeur_feuille_courante = + (*l_variable_courante).feuille; + return(d_vrai); + } + else + { + // Aucune variable locale n'est accessible depuis la fonction. + // Dans ce cas, on prend la variable de niveau le plus bas + // si ce niveau est inférieur ou égal à 1 (variable globale + // ou fonction définie par l'utilisateur). Si le niveau de la + // plus ancienne variable est strictement supérieur à 1, il + // s'agit d'une variable locale inaccessible. + + if ((*(*(*(*l_variable_courante).feuille).precedent).variable) + .niveau <= 1) + { + (*s_etat_processus).pointeur_variable_courante = + (*(*(*l_variable_courante).feuille).precedent).variable; + (*s_etat_processus).pointeur_feuille_courante = + (*(*l_variable_courante).feuille).precedent; + + // S'il existe une variable de niveau 0 et une seconde de + // niveau 1, la variable de niveau 0 (fonction) est masquée + // par celle de niveau 1. + + if (((*(*(*(*l_variable_courante).feuille).precedent) + .variable).niveau == 0) && ((*(*(*(* + (*l_variable_courante).feuille).precedent).precedent) + .variable).niveau == 1)) + { + (*s_etat_processus).pointeur_variable_courante = + (*(*(*(*l_variable_courante).feuille).precedent) + .precedent).variable; + (*s_etat_processus).pointeur_feuille_courante = + (*(*(*l_variable_courante).feuille).precedent) + .precedent; + } - if ((s_nouvelle_base = - 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); + return(d_vrai); } - - (*s_etat_processus).s_liste_variables = s_nouvelle_base; } + } + + (*s_etat_processus).erreur_systeme = d_es_variable_introuvable; + return(d_faux); +} - position_supprimee = (*s_etat_processus).position_variable_courante; - liberation(s_etat_processus, (*s_etat_processus).s_liste_variables - [position_supprimee].objet); - free((*s_etat_processus).s_liste_variables[position_supprimee].nom); +logical1 +recherche_variable_globale(struct_processus *s_etat_processus, + unsigned char *nom) +{ + logical1 presence_variable; - (*s_etat_processus).nombre_variables--; + presence_variable = recherche_variable(s_etat_processus, nom); - for(position_courante = position_supprimee; - position_courante < (*s_etat_processus).nombre_variables; - position_courante++) + if (presence_variable == d_vrai) + { + switch((*(*s_etat_processus).pointeur_variable_courante).niveau) { - (*s_etat_processus).s_liste_variables[position_courante] = - (*s_etat_processus).s_liste_variables - [position_courante + 1]; - } + case 0: + { + // La variable est une définition. + presence_variable = d_faux; + break; + } - erreur = d_absence_erreur; + 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 = + (*(*(*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; + } + + break; + } + } } - else + + if (presence_variable == d_vrai) { - erreur = d_erreur; - (*s_etat_processus).erreur_systeme = d_es_variable_introuvable; + 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 erreur; + return(presence_variable); } /* ================================================================================ - Procédure de recherche d'une variable par son nom dans la base + Procédure de retrait d'une variable de la base ================================================================================ - Entrée : + Entrée : type 'G' ou 'L' selon que l'on retire une variable locale (incluant + les globales) ou strictement globale. -------------------------------------------------------------------------------- Sortie : -------------------------------------------------------------------------------- @@ -392,200 +972,263 @@ retrait_variable(struct_processus *s_eta */ logical1 -recherche_variable(struct_processus *s_etat_processus, - unsigned char *nom_variable) +retrait_variable(struct_processus *s_etat_processus, + unsigned char *nom_variable, unsigned char type) { - logical1 existence_variable; + logical1 erreur; - long difference; - long difference_inferieure; - long difference_superieure; + struct_arbre_variables *s_arbre_a_supprimer; + struct_arbre_variables *s_arbre_courant; + struct_arbre_variables *noeud_courant; - struct_liste_pile_systeme *l_element_courant; - - unsigned long borne_inferieure; - unsigned long borne_superieure; - unsigned long moyenne; - unsigned long niveau_appel; - unsigned long nombre_iterations_maximal; - unsigned long ordre_iteration; - - if ((*s_etat_processus).nombre_variables == 0) - { - (*s_etat_processus).erreur_systeme = d_es_variable_introuvable; - return d_faux; - } + struct_liste_chainee *l_element_courant; + struct_liste_chainee *l_element_precedent; - ordre_iteration = 0; - nombre_iterations_maximal = ((unsigned long) - (log((*s_etat_processus).nombre_variables) / log(2))) + 2; + struct_liste_variables *variable_a_supprimer; + struct_liste_variables *variables_par_niveau; - borne_inferieure = 0; - borne_superieure = (*s_etat_processus).nombre_variables - 1; + unsigned long niveau; - do + if (recherche_variable(s_etat_processus, nom_variable) == d_vrai) { - moyenne = (borne_inferieure + borne_superieure) / 2; - ordre_iteration++; + // Une variable correspondant au nom recherché est accessible. - if (((borne_inferieure + borne_superieure) % 2) == 0) + if (type == 'G') { - difference = strcmp(nom_variable, - ((*s_etat_processus).s_liste_variables)[moyenne].nom); - - if (difference != 0) + if ((*(*s_etat_processus).pointeur_variable_courante).niveau > 1) { - if (difference > 0) + // La variable obtenue est une variable locale. il faut + // s'assurer qu'il existe une variable de niveau 1 de même + // nom sur la feuille. + + if ((*(*(*(*s_etat_processus).pointeur_feuille_courante) + .precedent).variable).niveau <= 1) { - borne_inferieure = moyenne; + (*s_etat_processus).pointeur_feuille_courante = + (*(*s_etat_processus).pointeur_feuille_courante) + .precedent; + (*s_etat_processus).pointeur_variable_courante = + (*(*s_etat_processus).pointeur_feuille_courante) + .variable; + + // Si la variable retournée est de niveau 0, on regarde + // un peu plus loin si une variable de niveau 1 existe. + + if (((*(*(*s_etat_processus).pointeur_feuille_courante) + .variable).niveau == 0) && + ((*(*(*(*s_etat_processus) + .pointeur_feuille_courante).precedent).variable) + .niveau == 1)) + { + (*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 { - borne_superieure = moyenne; + // Aucune variable globale (niveau 1) n'existe. + + erreur = d_erreur; + (*s_etat_processus).erreur_execution = + d_ex_variable_non_definie; + return(erreur); } } - } - else - { - difference_inferieure = strcmp(nom_variable, - ((*s_etat_processus).s_liste_variables)[moyenne].nom); - difference_superieure = strcmp(nom_variable, - ((*s_etat_processus).s_liste_variables)[moyenne + 1].nom); - if (difference_inferieure == 0) - { - difference = 0; - } - else if (difference_superieure == 0) - { - difference = 0; - moyenne++; - } - else + if ((*(*s_etat_processus).pointeur_variable_courante) + .variable_verrouillee == d_vrai) { - difference = difference_inferieure; - - if (difference > 0) - { - borne_inferieure = moyenne; - } - else - { - borne_superieure = moyenne; - } + erreur = d_erreur; + (*s_etat_processus).erreur_execution = + d_ex_variable_verrouillee; + return(erreur); } } - } while((difference != 0) && - (ordre_iteration <= nombre_iterations_maximal)); - if (ordre_iteration > nombre_iterations_maximal) - { - existence_variable = d_faux; - (*s_etat_processus).erreur_systeme = d_es_variable_introuvable; - } - else - { - if ((moyenne + 1) < (*s_etat_processus).nombre_variables) + // Suppression de la variable de la liste. + // Deux cas peuvent survenir : + // 1/ les pointeurs sur la variable et la variable suivante + // sont identiques et on supprime la variable ainsi que la feuille + // associée ; + // 2/ ces deux pointeurs sont différents et se contente de retirer + // la structure décrivant la variable. + + if ((*s_etat_processus).pointeur_feuille_courante == + (*(*s_etat_processus).pointeur_feuille_courante).suivant) { - while(strcmp(((*s_etat_processus).s_liste_variables) - [moyenne + 1].nom, nom_variable) == 0) + // 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; + noeud_courant = (*variable_a_supprimer).noeud; + (*s_arbre_courant).noeuds[(*noeud_courant).indice_tableau_pere] + = NULL; + + BUG((*s_arbre_courant).noeuds_utilises == 0, + uprintf("Freed node !\n")); + (*s_arbre_courant).noeuds_utilises--; + + while((*s_arbre_courant).noeuds_utilises == 0) { - moyenne++; + s_arbre_a_supprimer = s_arbre_courant; + s_arbre_courant = (*s_arbre_courant).noeud_pere; - if ((moyenne + 1) >= (*s_etat_processus).nombre_variables) + if (s_arbre_courant == NULL) { + free((*s_arbre_a_supprimer).noeuds); + free(s_arbre_a_supprimer); 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; + + free((*s_arbre_a_supprimer).noeuds); + free(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. - (*s_etat_processus).position_variable_courante = moyenne; + variable_a_supprimer = (*s_etat_processus) + .pointeur_feuille_courante; - if ((*s_etat_processus).s_liste_variables[(*s_etat_processus) - .position_variable_courante].niveau > 1) - { - // La variable trouvée est une variable locale. - // On vérifie qu'elle est accessible à la définition - // 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; - niveau_appel = (*s_etat_processus).niveau_courant; - l_element_courant = (*s_etat_processus).l_base_pile_systeme; + // 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 (l_element_courant == NULL) + if (variable_a_supprimer == (*((*(*variable_a_supprimer).noeud_pere) + .noeuds[(*(*variable_a_supprimer).noeud) + .indice_tableau_pere])).feuille) { - (*s_etat_processus).erreur_systeme = d_es_pile_vide; - existence_variable = d_faux; - - return existence_variable; + (*((*(*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; } - while((*l_element_courant).retour_definition != 'Y') - { - l_element_courant = (*l_element_courant).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; - if (l_element_courant == NULL) - { - (*s_etat_processus).erreur_systeme = d_es_pile_vide; - existence_variable = d_faux; + noeud_courant = NULL; + } - return existence_variable; - } - } + // Dans tous les cas, on retire la variable de la liste des variables + // par niveau. - niveau_appel = (*l_element_courant).niveau_courant; + niveau = (*(*variable_a_supprimer).variable).niveau; + variables_par_niveau = (*s_etat_processus).l_liste_variables_par_niveau; - if (niveau_appel < (*s_etat_processus).s_liste_variables - [(*s_etat_processus).position_variable_courante].niveau) - { - existence_variable = d_vrai; - } - else + if (variables_par_niveau != NULL) + { + do { - existence_variable = d_faux; - - // La variable locale n'est pas accessible. On regarde si par - // hasard il existe une variable globale. + l_element_courant = (*variables_par_niveau).liste; - while((*s_etat_processus).position_variable_courante != 0) + if (l_element_courant != NULL) { - if (strcmp(((*s_etat_processus).s_liste_variables) - [(*s_etat_processus).position_variable_courante - 1] .nom, nom_variable) == 0) - { - (*s_etat_processus).position_variable_courante--; - } - else + if ((*((struct_variable *) (*l_element_courant).donnee)) + .niveau == niveau) { - if ((*s_etat_processus).s_liste_variables - [(*s_etat_processus).position_variable_courante] - .niveau <= 1) + // On parcourt le bon niveau. + + l_element_precedent = NULL; + + while(l_element_courant != NULL) { - existence_variable = d_vrai; - } + // 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; + } + + free(l_element_courant); + break; + } - break; + l_element_precedent = l_element_courant; + l_element_courant = (*l_element_courant).suivant; + } } } - if ((strcmp(((*s_etat_processus).s_liste_variables) - [(*s_etat_processus).position_variable_courante].nom, - nom_variable) == 0) && ((*s_etat_processus) - .s_liste_variables[(*s_etat_processus) - .position_variable_courante].niveau <= 1)) - { - existence_variable = d_vrai; - } - } + variables_par_niveau = (*variables_par_niveau).suivant; + + } while(variables_par_niveau != (*s_etat_processus) + .l_liste_variables_par_niveau); } - else - { - // La variable trouvée est soit un pointeur sur une définition - // (niveau 0), soit une variable globale (niveau 1). - existence_variable = d_vrai; + // Puis on libère le contenu de la variable. + + 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; + + if (noeud_courant != NULL) + { + free((*noeud_courant).noeuds); + free(noeud_courant); } } + else + { + // Aucune variable n'est accessible depuis le point courant du + // programme. - return existence_variable; + erreur = d_erreur; + (*s_etat_processus).erreur_systeme = d_es_variable_introuvable; + } + + return(erreur); } @@ -605,107 +1248,140 @@ recherche_variable(struct_processus *s_e logical1 retrait_variable_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') - { - 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; - } + // Le niveau contient des variables. - (*s_etat_processus).s_liste_variables[i].objet = NULL; - } + 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. + + 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; + // 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).s_liste_variables = tampon; + (*(*(*s_etat_processus).l_liste_variables_par_niveau).precedent).suivant + = (*(*s_etat_processus).l_liste_variables_par_niveau).suivant; + (*(*(*s_etat_processus).l_liste_variables_par_niveau).suivant).precedent + = (*(*s_etat_processus).l_liste_variables_par_niveau).precedent; + + l_element_a_supprimer = (*s_etat_processus) + .l_liste_variables_par_niveau; + (*s_etat_processus).l_liste_variables_par_niveau = + (*l_element_a_supprimer).suivant; + free(l_element_a_supprimer); } return(d_absence_erreur); @@ -731,54 +1407,172 @@ 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. + + l_element_courant = (*arbre).feuille; + + if (l_element_courant != NULL) + { + do + { + l_element_suivant = (*l_element_courant).suivant; + free(l_element_courant); + l_element_courant = l_element_suivant; + } while(l_element_courant != (*arbre).feuille); + } 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); + } + } + + // Suppression de la liste des variables par niveau. - while(l_element_courant != NULL) + if (arbre == (*s_etat_processus).s_arbre_variables) + { + l_element_courant = (*s_etat_processus).l_liste_variables_par_niveau; + + 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); + free((*l_element_courant_liste).donnee); } + + l_element_suivant_liste = + (*l_element_courant_liste).suivant; + free(l_element_courant_liste); + l_element_courant_liste = l_element_suivant_liste; } + l_element_suivant = (*l_element_courant).suivant; free(l_element_courant); l_element_courant = l_element_suivant; - } - - liberation_arbre_variables(s_etat_processus, (*arbre).noeud[i]); + } while(l_element_courant != (*s_etat_processus) + .l_liste_variables_par_niveau); } } - free((*arbre).noeud); + free((*arbre).noeuds); free(arbre); return; } + +/* +================================================================================ + 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 @@ -796,6 +1590,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); } @@ -931,4 +1731,5 @@ initialisation_variables(struct_processu return; } + // vim: ts=4