--- rpl/src/gestion_variables_statiques.c 2012/10/01 11:05:02 1.36 +++ rpl/src/gestion_variables_statiques.c 2012/10/04 15:21:26 1.37 @@ -25,7 +25,7 @@ /* ================================================================================ - Routine de création d'une nouvelle variable statique + Routine d'ajout d'un bouchon dans la liste des variables statiques ================================================================================ Entrée : -------------------------------------------------------------------------------- @@ -35,80 +35,183 @@ ================================================================================ */ +// Routine ajoutant à la liste des variables statiques créées un 'bouchon' +// qui est un enregistrement dont la variable est NULL. Cela permet +// d'effacer les variables statiques créées dans une expression évaluées car, +// l'adresse de ces variables changeant à chaque évaluation, elles ne sont +// pas utilisables et constituent une fuite de mémoire + logical1 -creation_variable_statique(struct_processus *s_etat_processus, - struct_variable_statique *s_variable) +ajout_bouchon_variable_statique(struct_processus *s_etat_processus) { - struct_variable_statique *s_nouvelle_base; + struct_liste_variables_statiques *l_tete_liste; - long i; + l_tete_liste = (*s_etat_processus).l_liste_variables_statiques; + + if (((*s_etat_processus).l_liste_variables_statiques = + malloc(sizeof(struct_liste_variables_statiques))) == NULL) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return(d_erreur); + } - (*s_etat_processus).nombre_variables_statiques++; + (*(*s_etat_processus).l_liste_variables_statiques).variable = NULL; + (*(*s_etat_processus).l_liste_variables_statiques).suivant = l_tete_liste; + (*(*s_etat_processus).l_liste_variables_statiques).precedent = NULL; + (*l_tete_liste).precedent = (*s_etat_processus).l_liste_variables_statiques; - if ((*s_etat_processus).nombre_variables_statiques > (*s_etat_processus) - .nombre_variables_statiques_allouees) - { - // La nouvelle variable statique ne tient pas dans la table courante. - // Il convient donc d'en augmenter la taille. + return(d_absence_erreur); +} - if ((*s_etat_processus).nombre_variables_statiques_allouees == 0) - { - (*s_etat_processus).nombre_variables_statiques_allouees = - (*s_etat_processus).nombre_variables_statiques; - } - else - { - while((*s_etat_processus).nombre_variables_statiques > - (*s_etat_processus).nombre_variables_statiques_allouees) - { - (*s_etat_processus).nombre_variables_statiques_allouees *= 2; - } - } - if ((s_nouvelle_base = realloc((*s_etat_processus) - .s_liste_variables_statiques, (*s_etat_processus) - .nombre_variables_statiques_allouees * - sizeof(struct_variable_statique))) == NULL) +/* +================================================================================ + Routine de retrait des variables statiques +================================================================================ + Entrée : +-------------------------------------------------------------------------------- + Sortie : +-------------------------------------------------------------------------------- + Effets de bords : néant +================================================================================ +*/ + +// Cette routine libère toutes les variables statiques jusqu'au prochain +// bouchon ou jusqu'à la fin de la liste si aucun bouchon n'est rencontré. + +logical1 +retrait_variables_statiques(struct_processus *s_etat_processus) +{ + unsigned char registre_mode_execution; + + registre_mode_execution = (*s_etat_processus).mode_execution_programme; + + while((*s_etat_processus).l_liste_variables_statiques != NULL) + { + (*s_etat_processus).mode_execution_programme = + ((*(*(*s_etat_processus).l_liste_variables_statiques) + .variable).origine == 'P') ? 'Y' : 'N'; + + if ((*(*s_etat_processus).l_liste_variables_statiques).variable == NULL) + { + // On vient de tomber sur un bouchon... + (*s_etat_processus).l_liste_variables_statiques = + (*(*s_etat_processus).l_liste_variables_statiques).suivant; + free((*(*s_etat_processus).l_liste_variables_statiques).precedent); + (*(*s_etat_processus).l_liste_variables_statiques).precedent = NULL; + break; + } + + if (retrait_variable_statique(s_etat_processus, (*(*(*s_etat_processus) + .l_liste_variables_statiques).variable).nom, + (*(*(*s_etat_processus).l_liste_variables_statiques).variable) + .variable_statique) == d_erreur) { - (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; - (*s_etat_processus).nombre_variables_statiques--; + (*s_etat_processus).mode_execution_programme = + registre_mode_execution; return(d_erreur); } - - (*s_etat_processus).s_liste_variables_statiques = s_nouvelle_base; } - /* - * Positionnement de la variable statique au bon endroit - */ + (*s_etat_processus).mode_execution_programme = registre_mode_execution; + return(d_absence_erreur); +} + + +/* +================================================================================ + Routine de création d'une nouvelle variable statique +================================================================================ + Entrée : +-------------------------------------------------------------------------------- + Sortie : +-------------------------------------------------------------------------------- + Effets de bords : néant +================================================================================ +*/ + +logical1 +creation_variable_statique(struct_processus *s_etat_processus, + struct_variable_statique *s_variable) +{ + struct_arbre_variables *l_variable_courante; + + struct_liste_variables_statiques *l_nouvel_element; + + unsigned char *ptr; - // Nous avons (*s_etat_processus).nombre_variables_statiques - 1 variables - // dans la table qui sera balayée de la fin vers le début. + // Ajout de la variable en tête de la liste des variables statiques - if ((*s_etat_processus).nombre_variables_statiques == 1) + if ((l_nouvel_element = malloc(sizeof(struct_liste_variables_statiques))) + == NULL) { - (*s_etat_processus).s_liste_variables_statiques[0] = (*s_variable); + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return(d_erreur); } - else + + if (((*l_nouvel_element).variable = malloc(sizeof( + struct_variable_statique))) == NULL) { - for(i = (*s_etat_processus).nombre_variables_statiques - 2; i >= 0; i--) - { - if (strcmp((*s_variable).nom, - (*s_etat_processus).s_liste_variables_statiques[i].nom) < 0) - { - (*s_etat_processus).s_liste_variables_statiques[i + 1] = - (*s_etat_processus).s_liste_variables_statiques[i]; - } - else - { - break; - } - } + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return(d_erreur); + } - (*s_etat_processus).s_liste_variables_statiques[i + 1] = (*s_variable); + (*(*l_nouvel_element).variable) = (*s_variable); + (*l_nouvel_element).suivant = (*s_etat_processus) + .l_liste_variables_statiques; + (*(*s_etat_processus).l_liste_variables_statiques).precedent + = l_nouvel_element; + (*l_nouvel_element).precedent = NULL; + (*s_etat_processus).l_liste_variables_statiques = l_nouvel_element; + + // Ajout de la variable à la feuille statique de l'arbre des variables + + BUG((*s_etat_processus).s_arbre_variables == NULL, + uprintf("(*s_etat_processus).s_arbre_variables=NULL\n")); + + l_variable_courante = (*s_etat_processus).s_arbre_variables; + ptr = (*s_variable).nom; + + while((*ptr) != d_code_fin_chaine) + { + BUG((*s_etat_processus).pointeurs_caracteres_variables[*ptr] < 0, + uprintf("Variable=\"%s\", (*ptr)='%c'\n", (*s_variable).nom, + *ptr)); + + // La feuille doit préexister car la variable statique est toujours + // créée depuis une variable locale. + + BUG((*l_variable_courante).noeuds[(*s_etat_processus) + .pointeurs_caracteres_variables[*ptr]] == NULL, + uprintf("Variable=\"%s\", (*ptr)='%c', nullified folder\n")); + + l_variable_courante = (*l_variable_courante).noeuds + [(*s_etat_processus).pointeurs_caracteres_variables[*ptr]]; + ptr++; } - return d_absence_erreur; + if ((l_nouvel_element = malloc(sizeof(struct_liste_variables_statiques))) + == NULL) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return(d_erreur); + } + + // Dans la feuille statique de l'arbre des variables, on ne balaie + // les variables que dans l'ordre. Le champ 'reference' est alors utilisé + // pour sauvegarder une référence vers la liste des variables statiques + // pour pouvoir purger l'élément en cas de besoin. + + (*l_nouvel_element).suivant = (*l_variable_courante).feuille_statique; + (*l_nouvel_element).precedent = NULL; + (*(*l_nouvel_element).suivant).precedent = l_nouvel_element; + + (*l_nouvel_element).reference = + (*s_etat_processus).l_liste_variables_statiques; + (*l_nouvel_element).variable = (*(*s_etat_processus) + .l_liste_variables_statiques).variable; + (*l_variable_courante).feuille_statique = l_nouvel_element; + return(d_absence_erreur); } @@ -128,53 +231,75 @@ logical1 retrait_variable_statique(struct_processus *s_etat_processus, unsigned char *nom_variable, union_position_variable position) { - struct_variable_statique *s_nouvelle_base; - - logical1 erreur; + struct_liste_variables_statiques *l_element_a_supprimer; + struct_liste_variables_statiques *l_element_liste_a_supprimer; - unsigned long position_courante; - unsigned long position_supprimee; + logical1 erreur; - if (recherche_variable_statique(s_etat_processus, nom_variable, - position, ((*s_etat_processus).mode_execution_programme == 'Y') - ? 'P' : 'E') == d_vrai) + if ((l_element_a_supprimer = recherche_variable_statique(s_etat_processus, + nom_variable, position, ((*s_etat_processus) + .mode_execution_programme == 'Y') ? 'P' : 'E')) != NULL) { - if ((*s_etat_processus).nombre_variables_statiques < - ((*s_etat_processus).nombre_variables_statiques_allouees / 2)) - { - (*s_etat_processus).nombre_variables_statiques_allouees /= 2; + // (*s_etat_processus).pointeur_variable_statique_courante + // pointe sur la variable à éliminer. Cette variable est celle qui + // est présente dans l'une des feuilles statiques de l'arbre des + // variables. - if ((s_nouvelle_base = - realloc((*s_etat_processus).s_liste_variables_statiques, - (*s_etat_processus).nombre_variables_statiques_allouees * - sizeof(struct_variable_statique))) == NULL) - { - (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; - return(d_erreur); - } + l_element_liste_a_supprimer = (*l_element_a_supprimer).reference; + + // Suppression de la liste des variables statiques + + if ((*l_element_liste_a_supprimer).precedent != NULL) + { + (*(*l_element_liste_a_supprimer).precedent).suivant = + (*l_element_liste_a_supprimer).suivant; + } + else + { + (*(*l_element_liste_a_supprimer).suivant).precedent = NULL; + } - (*s_etat_processus).s_liste_variables_statiques = s_nouvelle_base; + if ((*l_element_liste_a_supprimer).suivant != NULL) + { + (*(*l_element_liste_a_supprimer).suivant).precedent = + (*l_element_liste_a_supprimer).precedent; + } + else + { + (*(*l_element_liste_a_supprimer).precedent).suivant = NULL; } - position_supprimee = (*s_etat_processus) - .position_variable_statique_courante; + free(l_element_liste_a_supprimer); - liberation(s_etat_processus, (*s_etat_processus) - .s_liste_variables_statiques[position_supprimee].objet); - free((*s_etat_processus).s_liste_variables_statiques - [position_supprimee].nom); + // Suppression depuis la feuille statique. Le champ 'precedent' ne sert + // pas car la liste est simplement chaînée. - (*s_etat_processus).nombre_variables_statiques--; + if ((*l_element_a_supprimer).precedent != NULL) + { + (*(*l_element_a_supprimer).precedent).suivant = + (*l_element_a_supprimer).suivant; + } + else + { + (*(*l_element_a_supprimer).suivant).precedent = NULL; + } - for(position_courante = position_supprimee; position_courante < - (*s_etat_processus).nombre_variables_statiques; - position_courante++) + if ((*l_element_a_supprimer).suivant != NULL) + { + (*(*l_element_a_supprimer).suivant).precedent = + (*l_element_a_supprimer).precedent; + } + else { - (*s_etat_processus).s_liste_variables_statiques[position_courante] - = (*s_etat_processus).s_liste_variables_statiques - [position_courante + 1]; + (*(*l_element_a_supprimer).precedent).suivant = NULL; } + liberation(s_etat_processus, (*(*l_element_a_supprimer).variable) + .objet); + free((*(*l_element_a_supprimer).variable).nom); + free((*l_element_a_supprimer).variable); + free(l_element_a_supprimer); + erreur = d_absence_erreur; } else @@ -199,236 +324,79 @@ retrait_variable_statique(struct_process ================================================================================ */ -logical1 +struct_liste_variables_statiques * recherche_variable_statique(struct_processus *s_etat_processus, unsigned char *nom_variable, union_position_variable position, unsigned char origine) { - logical1 existence_variable; + int pointeur; - long difference; - long difference_inferieure; - long difference_superieure; - - unsigned long borne_inferieure; - unsigned long borne_superieure; - unsigned long moyenne; - unsigned long nombre_iterations_maximal; - unsigned long ordre_iteration; + struct_arbre_variables *l_variable_courante; + struct_liste_variables_statiques *l_element_courant; - if ((*s_etat_processus).nombre_variables_statiques == 0) - { - (*s_etat_processus).erreur_systeme = d_es_variable_introuvable; - return d_faux; - } - - ordre_iteration = 0; - nombre_iterations_maximal = ((unsigned long) - (log((*s_etat_processus).nombre_variables_statiques) / log(2))) + 2; + unsigned char *ptr; - borne_inferieure = 0; - borne_superieure = (*s_etat_processus).nombre_variables_statiques - 1; + l_variable_courante = (*s_etat_processus).s_arbre_variables; + ptr = nom_variable; - do + while((*ptr) != d_code_fin_chaine) { - moyenne = (borne_inferieure + borne_superieure) / 2; - ordre_iteration++; + pointeur = (*s_etat_processus).pointeurs_caracteres_variables[*ptr]; - if ((2 * ((unsigned long) ((borne_inferieure + borne_superieure) / 2))) - == (borne_inferieure + borne_superieure)) + if (pointeur < 0) { - difference = strcmp(nom_variable, - ((*s_etat_processus).s_liste_variables_statiques) - [moyenne].nom); + // Caractère hors de l'alphabet des variables - if (difference != 0) - { - if (difference > 0) - { - borne_inferieure = moyenne; - } - else - { - borne_superieure = moyenne; - } - } + (*s_etat_processus).erreur_systeme = d_es_variable_introuvable; + return(NULL); } - else - { - difference_inferieure = strcmp(nom_variable, - ((*s_etat_processus).s_liste_variables_statiques) - [moyenne].nom); - difference_superieure = strcmp(nom_variable, - ((*s_etat_processus).s_liste_variables_statiques) - [moyenne + 1].nom); - if (difference_inferieure == 0) - { - difference = 0; - } - else if (difference_superieure == 0) - { - difference = 0; - moyenne++; - } - else - { - difference = difference_inferieure; - - if (difference > 0) - { - borne_inferieure = moyenne; - } - else - { - borne_superieure = moyenne; - } - } + 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(NULL); } - } 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; + l_variable_courante = (*l_variable_courante).noeuds[pointeur]; + ptr++; } - else + + if ((*l_variable_courante).feuille_statique != NULL) { - // Reste à rechercher la variable déclarée à la position 'position'... + // Il existe au moins une variable statique du nom requis. - if (((*s_etat_processus).s_liste_variables_statiques)[moyenne] - .origine == 'P') - { - if ((((*s_etat_processus).s_liste_variables_statiques)[moyenne] - .variable_statique.adresse == position.adresse) && - (((*s_etat_processus).s_liste_variables_statiques)[moyenne] - .origine == origine)) - { - existence_variable = d_vrai; - } - else - { - existence_variable = d_faux; - } - } - else - { - if ((((*s_etat_processus).s_liste_variables_statiques)[moyenne] - .variable_statique.pointeur == position.pointeur) && - (((*s_etat_processus).s_liste_variables_statiques)[moyenne] - .origine == origine)) - { - existence_variable = d_vrai; - } - else - { - existence_variable = d_faux; - } - } + l_element_courant = (*l_variable_courante).feuille_statique; - if (existence_variable == d_faux) + while(l_element_courant != NULL) { - // On rembobine. - - if (moyenne > 0) + if ((*(*l_element_courant).variable).origine == 'P') { - while(strcmp(nom_variable, ((*s_etat_processus) - .s_liste_variables_statiques)[moyenne - 1].nom) == 0) + if (((*(*l_element_courant).variable).variable_statique.adresse + == position.adresse) && + ((*(*l_element_courant).variable).origine == origine)) { - moyenne--; - - if (moyenne == 0) - { - break; - } + (*s_etat_processus).pointeur_variable_statique_courante + = (*l_element_courant).variable; + return(l_element_courant); } } - - // Un petit test pour voir si le premier élément du tableau - // peut correspondre au critère de recherche. - - existence_variable = d_faux; - - if (strcmp(((*s_etat_processus).s_liste_variables_statiques) - [moyenne].nom, nom_variable) == 0) - { - if (((*s_etat_processus).s_liste_variables_statiques) - [moyenne].origine == 'P') - { - if ((((*s_etat_processus).s_liste_variables_statiques) - [moyenne].variable_statique.adresse - == position.adresse) && - (((*s_etat_processus).s_liste_variables_statiques) - [moyenne].origine == origine)) - { - existence_variable = d_vrai; - } - } - else - { - if ((((*s_etat_processus).s_liste_variables_statiques) - [moyenne].variable_statique.pointeur - == position.pointeur) && - (((*s_etat_processus).s_liste_variables_statiques) - [moyenne].origine == origine)) - { - existence_variable = d_vrai; - } - } - } - - // Puis on balaye dans le sens croissant. - - if (((moyenne + 1) < (*s_etat_processus) - .nombre_variables_statiques) && - (existence_variable == d_faux)) + else { - while(strcmp(((*s_etat_processus) - .s_liste_variables_statiques)[moyenne + 1].nom, - nom_variable) == 0) + if (((*(*l_element_courant).variable).variable_statique.pointeur + == position.pointeur) && + ((*(*l_element_courant).variable).origine == origine)) { - moyenne++; - - if (((*s_etat_processus).s_liste_variables_statiques) - [moyenne].origine == 'P') - { - if ((((*s_etat_processus).s_liste_variables_statiques) - [moyenne].variable_statique.adresse == - position.adresse) && (((*s_etat_processus) - .s_liste_variables_statiques) - [moyenne].origine == origine)) - { - existence_variable = d_vrai; - break; - } - } - else - { - if ((((*s_etat_processus).s_liste_variables_statiques) - [moyenne].variable_statique.pointeur == - position.pointeur) && (((*s_etat_processus) - .s_liste_variables_statiques) - [moyenne].origine == origine)) - { - existence_variable = d_vrai; - break; - } - } - - if ((moyenne + 1) >= (*s_etat_processus) - .nombre_variables_statiques) - { - break; - } + (*s_etat_processus).pointeur_variable_statique_courante + = (*l_element_courant).variable; + return(l_element_courant); } } } - - (*s_etat_processus).position_variable_statique_courante = moyenne; } - return existence_variable; + (*s_etat_processus).pointeur_variable_statique_courante = NULL; + return(NULL); } // vim: ts=4