--- rpl/src/gestion_variables.c 2011/04/14 13:18:54 1.24 +++ rpl/src/gestion_variables.c 2011/04/19 07:31:33 1.25 @@ -39,52 +39,328 @@ ================================================================================ */ -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; + + struct_arbre_variables *l_variable_courante; - long i; + struct_liste_variables *l_nouvelle_variable; + struct_liste_variables *l_variable_candidate; - struct_variable *s_nouvelle_base; + struct_liste_chainee *l_nouvel_element; - (*s_etat_processus).nombre_variables++; + unsigned char *ptr; - if ((*s_etat_processus).nombre_variables > (*s_etat_processus) - .nombre_variables_allouees) + if ((*s_etat_processus).s_arbre_variables == NULL) { - // La nouvelle variable ne tient pas dans la table courante. Il - // faut donc en augmenter la taille. + 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; - if ((*s_etat_processus).nombre_variables_allouees == 0) + if (((*(*s_etat_processus).arbre_instructions).noeud = + malloc((*s_etat_processus).nombre_caracteres_variables + * sizeof(struct_arbre_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); + } + + for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++) + { + (*(*s_etat_processus).s_arbre_variables).noeud[i] = NULL; + } + } + + 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, + printf("Variable=\"%s\", (*ptr)='%c'\n", (*s_variable).nom, + *ptr)); + + if ((*l_variable_courante).noeud[(*s_etat_processus) + .pointeurs_caracteres_variables[*ptr]] == NULL) + { + // Le noeud n'existe pas encore, on le crée. + + if (((*l_variable_courante).noeud[(*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).noeud[(*s_etat_processus) + .pointeurs_caracteres_variables[*ptr]]).feuille = NULL; + (*(*l_variable_courante).noeud[(*s_etat_processus) + .pointeurs_caracteres_variables[*ptr]]).noeuds_utilises = 0; + + if (((*(*l_variable_courante).noeud[(*s_etat_processus) + .pointeurs_caracteres_variables[*ptr]]).noeud = + 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++) + { + (*(*l_variable_courante).noeud[(*s_etat_processus) + .pointeurs_caracteres_variables[*ptr]]).noeud[i] = NULL; + } + } + + (*l_variable_courante).noeuds_utilises++; + l_variable_courante = (*l_variable_courante).noeud + [(*s_etat_processus).pointeurs_caracteres_variables[*ptr]]; + ptr++; + } + + if ((*l_variable_courante).feuille == NULL) + { + // 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 (((*l_variable_courante).feuille = malloc( + sizeof(struct_liste_variables))) == NULL) + { + (*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; + + // 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); + + if (((*((struct_variable *) (*(*l_variable_courante).feuille).variable)) + .nom = strdup((*s_variable).nom)) == NULL) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return(d_erreur); + } + } + else + { + 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. + + 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 = (*l_variable_courante).feuille; + (*l_nouvelle_variable).precedent = (*(*l_variable_courante).feuille) + .precedent; + (*(*(*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); + + if (((*((struct_variable *) (*(*l_variable_courante).feuille) + .variable)).nom = strdup((*s_variable).nom)) == NULL) + { + (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; + return(d_erreur); + } } 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) + { + // Ajout inconditionnel des variables de niveaux 0 et 1 + } + else { - (*s_etat_processus).nombre_variables_allouees *= 2; + l_variable_candidate = (*(*l_variable_courante).feuille) + .precedent; + } + + (*l_nouvelle_variable).suivant = l_variable_candidate; + (*l_nouvelle_variable).precedent = (*l_variable_candidate) + .precedent; + (*(*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); + + if (((*(*l_nouvelle_variable).variable).nom = + strdup((*s_variable).nom)) == 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) + // 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); + } + + (*l_nouvelle_variable).suivant = l_nouvelle_variable; + (*l_nouvelle_variable).precedent = l_nouvelle_variable; + + (*s_etat_processus).l_liste_variables_par_niveau = l_nouvelle_variable; + } + 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; - (*s_etat_processus).nombre_variables--; return(d_erreur); } - (*s_etat_processus).s_liste_variables = s_nouvelle_base; + (*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; + (*(*(*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; + } + else + { + // Création d'une variable de niveau 0 ou 1 + + l_variable_candidate = (*s_etat_processus).l_liste_variables_par_niveau; + + if ((*((struct_variable *) (*(*(*(*s_etat_processus) + .l_liste_variables_par_niveau).precedent).liste).donnee)) + .niveau > 1) + { + // Ajout inconditionnel des variables de niveaux 0 et 1 + } + else + { + l_variable_candidate = (*(*s_etat_processus) + .l_liste_variables_par_niveau).precedent; + } + + (*l_nouvelle_variable).suivant = l_variable_candidate; + (*l_nouvelle_variable).precedent = (*l_variable_candidate) + .precedent; + (*(*l_variable_candidate).precedent).suivant = l_nouvelle_variable; + (*l_variable_candidate).precedent = 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 = (struct_objet *) s_variable; + (*l_nouvelle_variable).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,71 +466,132 @@ 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 (ajout_variable(s_etat_processus, s_variable) == d_erreur) + { + return(d_erreur); + } + + return(d_absence_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) +{ + int pointeur; + + struct_arbre_variables *l_variable_courante; + struct_liste_pile_systeme *l_element_courant; + + unsigned char *ptr; + + unsigned long niveau_appel; - if ((*s_etat_processus).nombre_variables == 1) + if ((*s_etat_processus).s_arbre_variables == NULL) { - (*s_etat_processus).s_liste_variables[0] = (*s_variable); + (*s_etat_processus).erreur_systeme = d_es_variable_introuvable; + return d_faux; } - else + + ptr = nom_variable; + + while((*ptr) != d_code_fin_chaine) { - for(i = (*s_etat_processus).nombre_variables - 2; i >= 0; i--) + pointeur = (*s_etat_processus).pointeurs_caracteres_variables[*ptr]; + + if (pointeur < 0) { - 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; - } + // Caractère hors de l'alphabet des variables + return(d_erreur); } - if ((*s_variable).niveau > 1) + if ((*l_variable_courante).noeud[pointeur] == NULL) { - // Cas d'une variable locale - (*s_etat_processus).s_liste_variables[i + 1] = (*s_variable); + // Le chemin de la variable candidate n'existe pas. + return(d_erreur); } - else + + l_variable_courante = (*l_variable_courante).noeud[pointeur]; + ptr++; + } + + 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) { - // Cas d'une variable globale - presence = d_faux; + // Problème : la pile système est vide ! + (*s_etat_processus).erreur_systeme = d_es_pile_vide; + return(d_erreur); + } - 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; - } - } + while((*l_element_courant).retour_definition != 'Y') + { + l_element_courant = (*l_element_courant).suivant; - if (presence == d_faux) + if (l_element_courant == NULL) { - (*s_etat_processus).s_liste_variables[0] = (*s_variable); + (*s_etat_processus).erreur_systeme = d_es_pile_vide; + return(d_erreur); } - else - { - (*s_etat_processus).s_liste_variables[i + 1] = (*s_variable); + } + + niveau_appel = (*l_element_courant).niveau_courant; + + if (niveau_appel < (*(*(*l_variable_courante).feuille).variable).niveau) + { + // Une variable locale est accessible puisque créée dans la + // fonction courante. + + (*s_etat_processus).pointeur_variable_courante = + (*(*l_variable_courante).feuille).variable; + (*s_etat_processus).pointeur_feuille_courante = + (*l_variable_courante).feuille; + return(d_absence_erreur); + } + 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, el + // 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; + return(d_absence_erreur); } } } - return(d_absence_erreur); + return(d_erreur); } @@ -275,17 +612,21 @@ 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) { + // Une variable correspondant au nom recherché est accessible. + if (type == 'G') { + if ((*(*s_etat_processus).pointeur_variable_courante).niveau > 1) + { + // 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).position_variable_courante > 0) { while(strcmp((*s_etat_processus).s_liste_variables @@ -371,221 +712,14 @@ retrait_variable(struct_processus *s_eta } 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; + // Aucune variable n'est accessible depuis le point courant du + // programme. - 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; + erreur = d_erreur; (*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; + return(erreur); } @@ -931,4 +1065,5 @@ initialisation_variables(struct_processu return; } + // vim: ts=4