/* ================================================================================ RPL/2 (R) version 4.0.24 Copyright (C) 1989-2011 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 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. -------------------------------------------------------------------------------- Sortie : -------------------------------------------------------------------------------- Effets de bords : néant ================================================================================ */ logical1 creation_variable(struct_processus *s_etat_processus, struct_variable *s_variable, unsigned char autorisation_creation_variable_statique, unsigned char autorisation_creation_variable_partagee) { logical1 presence; long i; struct_variable *s_nouvelle_base; (*s_etat_processus).nombre_variables++; if ((*s_etat_processus).nombre_variables > (*s_etat_processus) .nombre_variables_allouees) { // La nouvelle variable ne tient pas dans la table courante. Il // faut donc en augmenter la taille. if ((*s_etat_processus).nombre_variables_allouees == 0) { (*s_etat_processus).nombre_variables_allouees = (*s_etat_processus).nombre_variables; } else { while((*s_etat_processus).nombre_variables > (*s_etat_processus).nombre_variables_allouees) { (*s_etat_processus).nombre_variables_allouees *= 2; } } 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; (*s_etat_processus).nombre_variables--; return(d_erreur); } (*s_etat_processus).s_liste_variables = s_nouvelle_base; } if ((*s_etat_processus).mode_execution_programme == 'Y') { (*s_variable).origine = 'P'; } else { (*s_variable).origine = 'E'; } if ((*s_variable).niveau == 0) { // Un point d'entrée de définition est verrouillé. if ((*s_variable).origine == 'P') { (*s_variable).variable_statique.adresse = 0; (*s_variable).variable_partagee.adresse = 0; } else { (*s_variable).variable_statique.pointeur = NULL; (*s_variable).variable_partagee.pointeur = NULL; } (*s_variable).variable_verrouillee = d_vrai; } else if ((*s_variable).niveau == 1) { // Une variable globale ne peut être statique. if ((*s_variable).origine == 'P') { (*s_variable).variable_statique.adresse = 0; (*s_variable).variable_partagee.adresse = 0; } else { (*s_variable).variable_statique.pointeur = NULL; (*s_variable).variable_partagee.pointeur = NULL; } (*s_variable).variable_verrouillee = d_faux; } else { // 0 -> variable volatile // adresse de création -> variable statique if (autorisation_creation_variable_statique == 'V') { if (autorisation_creation_variable_partagee == 'S') { // On force la création d'une variable partagée if ((*s_variable).origine == 'P') { (*s_variable).variable_statique.adresse = 0; (*s_variable).variable_partagee.adresse = (*s_etat_processus).position_courante; } else { (*s_variable).variable_statique.pointeur = NULL; (*s_variable).variable_partagee.pointeur = (*s_etat_processus).objet_courant; } } else { // On force la création d'une variable volatile if ((*s_variable).origine == 'P') { (*s_variable).variable_statique.adresse = 0; (*s_variable).variable_partagee.adresse = 0; } else { (*s_variable).variable_statique.pointeur = NULL; (*s_variable).variable_partagee.pointeur = NULL; } } } else { // On force la création d'une variable statique. if ((*s_variable).origine == 'P') { (*s_variable).variable_statique.adresse = (*s_etat_processus).position_courante; (*s_variable).variable_partagee.adresse = 0; } else { (*s_variable).variable_statique.pointeur = (*s_etat_processus).objet_courant; (*s_variable).variable_partagee.pointeur = 0; } } (*s_variable).variable_verrouillee = d_faux; } /* * Positionnement de la variable au bon endroit */ // 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) { (*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_absence_erreur); } /* ================================================================================ Procédure de retrait d'une variable de la base ================================================================================ Entrée : type 'G' ou 'L' selon que l'on retire une variable locale (incluant les globales) ou strictement globale. -------------------------------------------------------------------------------- Sortie : -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ logical1 retrait_variable(struct_processus *s_etat_processus, unsigned char *nom_variable, unsigned char type) { struct_variable *s_nouvelle_base; logical1 erreur; unsigned long position_courante; unsigned long position_supprimee; if (recherche_variable(s_etat_processus, nom_variable) == d_vrai) { if (type == 'G') { 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--; 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).position_variable_courante++; } 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; } if ((*s_etat_processus).s_liste_variables [(*s_etat_processus).position_variable_courante] .variable_verrouillee == d_vrai) { erreur = d_erreur; (*s_etat_processus).erreur_execution = d_ex_variable_verrouillee; return erreur; } } if ((*s_etat_processus).nombre_variables < ((*s_etat_processus).nombre_variables_allouees / 2)) { (*s_etat_processus).nombre_variables_allouees /= 2; // (*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. 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); } (*s_etat_processus).s_liste_variables = s_nouvelle_base; } 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); (*s_etat_processus).nombre_variables--; for(position_courante = position_supprimee; position_courante < (*s_etat_processus).nombre_variables; position_courante++) { (*s_etat_processus).s_liste_variables[position_courante] = (*s_etat_processus).s_liste_variables [position_courante + 1]; } 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 par son nom dans la base ================================================================================ Entrée : -------------------------------------------------------------------------------- Sortie : -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ logical1 recherche_variable(struct_processus *s_etat_processus, unsigned char *nom_variable) { logical1 existence_variable; long difference; long difference_inferieure; long difference_superieure; 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; } ordre_iteration = 0; nombre_iterations_maximal = ((unsigned long) (log((*s_etat_processus).nombre_variables) / log(2))) + 2; borne_inferieure = 0; borne_superieure = (*s_etat_processus).nombre_variables - 1; do { moyenne = (borne_inferieure + borne_superieure) / 2; ordre_iteration++; if (((borne_inferieure + borne_superieure) % 2) == 0) { difference = strcmp(nom_variable, ((*s_etat_processus).s_liste_variables)[moyenne].nom); if (difference != 0) { if (difference > 0) { borne_inferieure = moyenne; } else { borne_superieure = moyenne; } } } 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 { difference = difference_inferieure; if (difference > 0) { borne_inferieure = moyenne; } else { borne_superieure = moyenne; } } } } 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) { while(strcmp(((*s_etat_processus).s_liste_variables) [moyenne + 1].nom, nom_variable) == 0) { moyenne++; if ((moyenne + 1) >= (*s_etat_processus).nombre_variables) { break; } } } (*s_etat_processus).position_variable_courante = moyenne; 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. niveau_appel = (*s_etat_processus).niveau_courant; l_element_courant = (*s_etat_processus).l_base_pile_systeme; if (l_element_courant == NULL) { (*s_etat_processus).erreur_systeme = d_es_pile_vide; existence_variable = d_faux; return existence_variable; } while((*l_element_courant).retour_definition != 'Y') { l_element_courant = (*l_element_courant).suivant; if (l_element_courant == NULL) { (*s_etat_processus).erreur_systeme = d_es_pile_vide; existence_variable = d_faux; return existence_variable; } } niveau_appel = (*l_element_courant).niveau_courant; if (niveau_appel < (*s_etat_processus).s_liste_variables [(*s_etat_processus).position_variable_courante].niveau) { existence_variable = d_vrai; } else { existence_variable = d_faux; // La variable locale n'est pas accessible. On regarde si par // hasard il existe une variable globale. while((*s_etat_processus).position_variable_courante != 0) { 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 ((*s_etat_processus).s_liste_variables [(*s_etat_processus).position_variable_courante] .niveau <= 1) { existence_variable = d_vrai; } break; } } 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; } } } 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; } } return existence_variable; } /* ================================================================================ Procédure de retrait des variables de niveau strictement supérieur au niveau courant ================================================================================ Entrée : -------------------------------------------------------------------------------- Sortie : -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ logical1 retrait_variable_par_niveau(struct_processus *s_etat_processus) { unsigned long i; unsigned long j; struct_variable *tampon; for(j = 0, i = 0; i < (*s_etat_processus).nombre_variables; i++) { if ((*s_etat_processus).s_liste_variables[i].niveau <= (*s_etat_processus).niveau_courant) { (*s_etat_processus).s_liste_variables[j++] = (*s_etat_processus).s_liste_variables[i]; } 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; } (*s_etat_processus).s_liste_variables[i].objet = NULL; } } else { if ((*s_etat_processus).s_liste_variables[i] .variable_statique.pointeur != NULL) { /* * 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; } (*s_etat_processus).s_liste_variables[i].objet = NULL; } } free((*s_etat_processus).s_liste_variables[i].nom); liberation(s_etat_processus, (*s_etat_processus).s_liste_variables[i].objet); } } (*s_etat_processus).nombre_variables = j; if ((*s_etat_processus).nombre_variables < ((*s_etat_processus).nombre_variables_allouees / 2)) { (*s_etat_processus).nombre_variables_allouees /= 2; if ((tampon = realloc((*s_etat_processus).s_liste_variables, (*s_etat_processus).nombre_variables_allouees * sizeof(struct_variable))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(d_erreur); } (*s_etat_processus).s_liste_variables = tampon; } return(d_absence_erreur); } // vim: ts=4