/* ================================================================================ RPL/2 (R) version 4.1.11 Copyright (C) 1989-2012 Dr. BERTRAND Joël This file is part of RPL/2. RPL/2 is free software; you can redistribute it and/or modify it under the terms of the CeCILL V2 License as published by the french CEA, CNRS and INRIA. RPL/2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL V2 License for more details. You should have received a copy of the CeCILL License along with RPL/2. If not, write to info@cecill.info. ================================================================================ */ #include "rpl-conv.h" /* ================================================================================ Routine d'ajout d'un bouchon dans la liste des variables statiques ================================================================================ Entrée : -------------------------------------------------------------------------------- Sortie : -------------------------------------------------------------------------------- Effets de bords : néant ================================================================================ */ // 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 ajout_bouchon_variable_statique(struct_processus *s_etat_processus) { struct_liste_variables_statiques *l_tete_liste; 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).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; return(d_absence_erreur); } /* ================================================================================ 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).mode_execution_programme = registre_mode_execution; return(d_erreur); } } (*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; // Ajout de la variable en tête de la liste des variables statiques if ((l_nouvel_element = malloc(sizeof(struct_liste_variables_statiques))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(d_erreur); } if (((*l_nouvel_element).variable = malloc(sizeof( struct_variable_statique))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(d_erreur); } (*(*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++; } 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); } /* ================================================================================ Procédure de retrait d'une variable statique de la base ================================================================================ Entrée : -------------------------------------------------------------------------------- Sortie : -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ logical1 retrait_variable_statique(struct_processus *s_etat_processus, unsigned char *nom_variable, union_position_variable position) { struct_liste_variables_statiques *l_element_a_supprimer; struct_liste_variables_statiques *l_element_liste_a_supprimer; logical1 erreur; if ((l_element_a_supprimer = recherche_variable_statique(s_etat_processus, nom_variable, position, ((*s_etat_processus) .mode_execution_programme == 'Y') ? 'P' : 'E')) != NULL) { // (*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. 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; } 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; } free(l_element_liste_a_supprimer); // Suppression depuis la feuille statique. Le champ 'precedent' ne sert // pas car la liste est simplement chaînée. 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; } if ((*l_element_a_supprimer).suivant != NULL) { (*(*l_element_a_supprimer).suivant).precedent = (*l_element_a_supprimer).precedent; } else { (*(*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 { erreur = d_erreur; (*s_etat_processus).erreur_systeme = d_es_variable_introuvable; } return erreur; } /* ================================================================================ Procédure de recherche d'une variable statique par son nom dans la base ================================================================================ Entrée : -------------------------------------------------------------------------------- Sortie : -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ struct_liste_variables_statiques * recherche_variable_statique(struct_processus *s_etat_processus, unsigned char *nom_variable, union_position_variable position, unsigned char origine) { int pointeur; struct_arbre_variables *l_variable_courante; struct_liste_variables_statiques *l_element_courant; unsigned char *ptr; 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) { // Caractère hors de l'alphabet des variables (*s_etat_processus).erreur_systeme = d_es_variable_introuvable; return(NULL); } 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); } l_variable_courante = (*l_variable_courante).noeuds[pointeur]; ptr++; } if ((*l_variable_courante).feuille_statique != NULL) { // Il existe au moins une variable statique du nom requis. l_element_courant = (*l_variable_courante).feuille_statique; while(l_element_courant != NULL) { if ((*(*l_element_courant).variable).origine == 'P') { if (((*(*l_element_courant).variable).variable_statique.adresse == position.adresse) && ((*(*l_element_courant).variable).origine == origine)) { (*s_etat_processus).pointeur_variable_statique_courante = (*l_element_courant).variable; return(l_element_courant); } } else { if (((*(*l_element_courant).variable).variable_statique.pointeur == position.pointeur) && ((*(*l_element_courant).variable).origine == origine)) { (*s_etat_processus).pointeur_variable_statique_courante = (*l_element_courant).variable; return(l_element_courant); } } } } (*s_etat_processus).pointeur_variable_statique_courante = NULL; return(NULL); } // vim: ts=4