File:  [local] / rpl / src / gestion_variables_statiques.c
Revision 1.71: download - view: text, annotated - select for diffs - revision graph
Fri Jan 10 11:15:43 2020 UTC (4 years, 3 months ago) by bertrand
Branches: MAIN
CVS tags: rpl-4_1_32, HEAD
Modification du copyright.

    1: /*
    2: ================================================================================
    3:   RPL/2 (R) version 4.1.32
    4:   Copyright (C) 1989-2020 Dr. BERTRAND Joël
    5: 
    6:   This file is part of RPL/2.
    7: 
    8:   RPL/2 is free software; you can redistribute it and/or modify it
    9:   under the terms of the CeCILL V2 License as published by the french
   10:   CEA, CNRS and INRIA.
   11:  
   12:   RPL/2 is distributed in the hope that it will be useful, but WITHOUT
   13:   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   14:   FITNESS FOR A PARTICULAR PURPOSE.  See the CeCILL V2 License
   15:   for more details.
   16:  
   17:   You should have received a copy of the CeCILL License
   18:   along with RPL/2. If not, write to info@cecill.info.
   19: ================================================================================
   20: */
   21: 
   22: 
   23: #include "rpl-conv.h"
   24: 
   25: 
   26: /*
   27: ================================================================================
   28:   Routine de retrait des variables statiques
   29: ================================================================================
   30:   Entrée :
   31: --------------------------------------------------------------------------------
   32:   Sortie :
   33: --------------------------------------------------------------------------------
   34:   Effets de bords : néant
   35: ================================================================================
   36: */
   37: 
   38: // Cette routine libère toutes les variables statiques de niveau non
   39: // nul, donc attachées à une expression et non un programme.
   40: 
   41: logical1
   42: retrait_variables_statiques_locales(struct_processus *s_etat_processus)
   43: {
   44:     struct_liste_variables_statiques    *l_element_courant;
   45:     struct_liste_variables_statiques    *l_element_suivant;
   46: 
   47:     unsigned char                       registre_mode_execution;
   48: 
   49:     registre_mode_execution = (*s_etat_processus).mode_execution_programme;
   50:     l_element_courant = (*s_etat_processus).l_liste_variables_statiques;
   51: 
   52:     while(l_element_courant != NULL)
   53:     {
   54:         l_element_suivant = (*l_element_courant).suivant;
   55: 
   56:         (*s_etat_processus).mode_execution_programme =
   57:                 ((*(*l_element_courant).variable).origine == 'P') ? 'Y' : 'N';
   58: 
   59:         if ((*(*l_element_courant).variable).niveau > 0)
   60:         {
   61:             if (retrait_variable_statique(s_etat_processus,
   62:                     (*(*l_element_courant).variable).nom,
   63:                     (*(*l_element_courant).variable).variable_statique)
   64:                     == d_erreur)
   65:             {
   66:                 (*s_etat_processus).mode_execution_programme =
   67:                         registre_mode_execution;
   68:                 return(d_erreur);
   69:             }
   70:         }
   71: 
   72:         l_element_courant = l_element_suivant;
   73:     }
   74: 
   75:     (*s_etat_processus).mode_execution_programme = registre_mode_execution;
   76:     return(d_absence_erreur);
   77: }
   78: 
   79: 
   80: /*
   81: ================================================================================
   82:   Routine de création d'une nouvelle variable statique
   83: ================================================================================
   84:   Entrée :
   85: --------------------------------------------------------------------------------
   86:   Sortie :
   87: --------------------------------------------------------------------------------
   88:   Effets de bords : néant
   89: ================================================================================
   90: */
   91: 
   92: logical1
   93: creation_variable_statique(struct_processus *s_etat_processus,
   94:         struct_variable_statique *s_variable)
   95: {
   96:     int                                     i;
   97: 
   98:     struct_arbre_variables                  *l_variable_courante;
   99: 
  100:     struct_liste_variables_statiques        *l_nouvel_element;
  101: 
  102:     unsigned char                           *ptr;
  103: 
  104:     // Ajout de la variable en tête de la liste des variables statiques
  105: 
  106:     if ((l_nouvel_element = malloc(sizeof(struct_liste_variables_statiques)))
  107:             == NULL)
  108:     {
  109:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  110:         return(d_erreur);
  111:     }
  112: 
  113:     if (((*l_nouvel_element).variable = malloc(sizeof(
  114:             struct_variable_statique))) == NULL)
  115:     {
  116:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  117:         return(d_erreur);
  118:     }
  119: 
  120:     (*(*l_nouvel_element).variable) = (*s_variable);
  121: 
  122:     (*l_nouvel_element).suivant = (*s_etat_processus)
  123:             .l_liste_variables_statiques;
  124:     (*l_nouvel_element).precedent = NULL;
  125: 
  126:     if ((*s_etat_processus).l_liste_variables_statiques != NULL)
  127:     {
  128:         (*(*s_etat_processus).l_liste_variables_statiques).precedent
  129:                 = l_nouvel_element;
  130:     }
  131: 
  132:     (*s_etat_processus).l_liste_variables_statiques = l_nouvel_element;
  133: 
  134:     // Ajout de la variable à la feuille statique de l'arbre des variables
  135: 
  136:     if ((*s_etat_processus).s_arbre_variables == NULL)
  137:     {
  138:         if (((*s_etat_processus).s_arbre_variables =
  139:                     allocation_noeud(s_etat_processus)) == NULL)
  140:         {
  141:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  142:             return(d_erreur);
  143:         }
  144: 
  145:         (*(*s_etat_processus).s_arbre_variables).feuille = NULL;
  146:         (*(*s_etat_processus).s_arbre_variables).feuille_statique = NULL;
  147:         (*(*s_etat_processus).s_arbre_variables).noeuds_utilises = 0;
  148:         (*(*s_etat_processus).s_arbre_variables).indice_tableau_pere = -1;
  149:         (*(*s_etat_processus).s_arbre_variables).noeud_pere = NULL;
  150: 
  151:         if (((*(*s_etat_processus).s_arbre_variables).noeuds =
  152:                 allocation_tableau_noeuds(s_etat_processus)) == NULL)
  153:         {
  154:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  155:             return(d_erreur);
  156:         }
  157: 
  158:         for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
  159:         {
  160:             (*(*s_etat_processus).s_arbre_variables).noeuds[i] = NULL;
  161:         }
  162:     }
  163: 
  164:     l_variable_courante = (*s_etat_processus).s_arbre_variables;
  165:     ptr = (*s_variable).nom;
  166: 
  167:     while((*ptr) != d_code_fin_chaine)
  168:     {
  169:         BUG((*s_etat_processus).pointeurs_caracteres_variables[*ptr] < 0,
  170:                 uprintf("Variable=\"%s\", (*ptr)='%c'\n", (*s_variable).nom,
  171:                 *ptr));
  172: 
  173:         if ((*l_variable_courante).noeuds[(*s_etat_processus)
  174:                 .pointeurs_caracteres_variables[*ptr]] == NULL)
  175:         {
  176:             // Le noeud n'existe pas encore, on le crée et on le marque
  177:             // comme utilisé dans la structure parente.
  178: 
  179:             if (((*l_variable_courante).noeuds[(*s_etat_processus)
  180:                     .pointeurs_caracteres_variables[*ptr]] =
  181:                     allocation_noeud(s_etat_processus)) == NULL)
  182:             {
  183:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  184:                 return(d_erreur);
  185:             }
  186: 
  187:             (*l_variable_courante).noeuds_utilises++;
  188: 
  189:             // La feuille est par défaut vide et aucun élément du tableau noeuds
  190:             // (les branches qui peuvent être issues de ce nouveau noeud)
  191:             // n'est encore utilisée.
  192: 
  193:             (*(*l_variable_courante).noeuds[(*s_etat_processus)
  194:                     .pointeurs_caracteres_variables[*ptr]]).feuille = NULL;
  195:             (*(*l_variable_courante).noeuds[(*s_etat_processus)
  196:                     .pointeurs_caracteres_variables[*ptr]]).feuille_statique
  197:                     = NULL;
  198:             (*(*l_variable_courante).noeuds[(*s_etat_processus)
  199:                     .pointeurs_caracteres_variables[*ptr]]).noeuds_utilises = 0;
  200: 
  201:             // Le champ noeud_pere de la structure créée pointe sur
  202:             // la structure parente et l'indice tableau_pere correspond à la
  203:             // position réelle dans le tableau noeuds[] de la structure parente
  204:             // du noeud courant. Cette valeur sera utilisée lors de la
  205:             // destruction du noeud pour annuler le pointeur contenu dans
  206:             // le tableau noeuds[] de la structure parente.
  207: 
  208:             (*(*l_variable_courante).noeuds[(*s_etat_processus)
  209:                     .pointeurs_caracteres_variables[*ptr]]).noeud_pere =
  210:                     l_variable_courante;
  211:             (*(*l_variable_courante).noeuds[(*s_etat_processus)
  212:                     .pointeurs_caracteres_variables[*ptr]])
  213:                     .indice_tableau_pere = (*s_etat_processus)
  214:                     .pointeurs_caracteres_variables[*ptr];
  215: 
  216:             // Allocation du tableau noeuds[] et initialisation à zéro de
  217:             // tous les pointeurs.
  218: 
  219:             if (((*(*l_variable_courante).noeuds[(*s_etat_processus)
  220:                     .pointeurs_caracteres_variables[*ptr]]).noeuds =
  221:                     allocation_tableau_noeuds(s_etat_processus)) == NULL)
  222:             {
  223:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  224:                 return(d_erreur);
  225:             }
  226: 
  227:             for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
  228:             {
  229:                 (*(*l_variable_courante).noeuds[(*s_etat_processus)
  230:                         .pointeurs_caracteres_variables[*ptr]]).noeuds[i]
  231:                         = NULL;
  232:             }
  233:         }
  234: 
  235:         l_variable_courante = (*l_variable_courante).noeuds
  236:                 [(*s_etat_processus).pointeurs_caracteres_variables[*ptr]];
  237:         ptr++;
  238:     }
  239: 
  240:     if ((l_nouvel_element = malloc(sizeof(struct_liste_variables_statiques)))
  241:             == NULL)
  242:     {
  243:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  244:         return(d_erreur);
  245:     }
  246: 
  247:     // Dans la feuille statique de l'arbre des variables, on ne balaie
  248:     // les variables que dans l'ordre. Le champ 'reference' est alors utilisé
  249:     // pour sauvegarder une référence vers la liste des variables statiques
  250:     // pour pouvoir purger l'élément en cas de besoin.
  251: 
  252:     (*l_nouvel_element).suivant = (*l_variable_courante).feuille_statique;
  253:     (*l_nouvel_element).precedent = NULL;
  254: 
  255:     if ((*l_nouvel_element).suivant != NULL)
  256:     {
  257:         (*(*l_nouvel_element).suivant).precedent = l_nouvel_element;
  258:     }
  259: 
  260:     (*l_nouvel_element).reference =
  261:             (*s_etat_processus).l_liste_variables_statiques;
  262:     (*l_nouvel_element).variable = (*(*s_etat_processus)
  263:             .l_liste_variables_statiques).variable;
  264:     (*l_variable_courante).feuille_statique = l_nouvel_element;
  265:     (*l_nouvel_element).feuille = l_variable_courante;
  266: 
  267:     return(d_absence_erreur);
  268: }
  269: 
  270: 
  271: /*
  272: ================================================================================
  273:   Procédure de retrait d'une variable statique de la base
  274: ================================================================================
  275:   Entrée :
  276: --------------------------------------------------------------------------------
  277:   Sortie :
  278: --------------------------------------------------------------------------------
  279:   Effets de bord : néant
  280: ================================================================================
  281: */
  282: 
  283: logical1
  284: retrait_variable_statique(struct_processus *s_etat_processus,
  285:         unsigned char *nom_variable, union_position_variable position)
  286: {
  287:     struct_liste_variables_statiques        *l_element_a_supprimer;
  288:     struct_liste_variables_statiques        *l_element_liste_a_supprimer;
  289: 
  290:     logical1                                erreur;
  291: 
  292:     if ((l_element_a_supprimer = recherche_variable_statique(s_etat_processus,
  293:             nom_variable, position, ((*s_etat_processus)
  294:             .mode_execution_programme == 'Y') ? 'P' : 'E')) != NULL)
  295:     {
  296:         // (*s_etat_processus).pointeur_variable_statique_courante
  297:         // pointe sur la variable à éliminer. Cette variable est celle qui
  298:         // est présente dans l'une des feuilles statiques de l'arbre des
  299:         // variables.
  300: 
  301:         l_element_liste_a_supprimer = (*l_element_a_supprimer).reference;
  302: 
  303:         // Suppression de la liste des variables statiques
  304: 
  305:         if ((*l_element_liste_a_supprimer).precedent != NULL)
  306:         {
  307:             // L'élément à supprimer n'est pas le premier de la liste.
  308: 
  309:             (*(*l_element_liste_a_supprimer).precedent).suivant =
  310:                     (*l_element_liste_a_supprimer).suivant;
  311: 
  312:             if ((*l_element_liste_a_supprimer).suivant != NULL)
  313:             {
  314:                 // Il y a un élément suivant. On le chaîne.
  315:                 (*(*l_element_liste_a_supprimer).suivant).precedent = NULL;
  316:             }
  317:         }
  318:         else
  319:         {
  320:             // L'élement est le premier de la liste. S'il y a un élément
  321:             // suivant, on le chaîne.
  322: 
  323:             if ((*l_element_liste_a_supprimer).suivant != NULL)
  324:             {
  325:                 (*(*l_element_liste_a_supprimer).suivant).precedent = NULL;
  326:             }
  327: 
  328:             (*s_etat_processus).l_liste_variables_statiques =
  329:                     (*l_element_liste_a_supprimer).suivant;
  330:         }
  331: 
  332:         free(l_element_liste_a_supprimer);
  333: 
  334:         // Suppression depuis la feuille statique. Le champ 'precedent' ne sert
  335:         // pas car la liste est simplement chaînée.
  336: 
  337:         if ((*l_element_a_supprimer).precedent != NULL)
  338:         {
  339:             // L'élément n'est pas le premier de la liste.
  340: 
  341:             (*(*l_element_a_supprimer).precedent).suivant =
  342:                     (*l_element_a_supprimer).suivant;
  343: 
  344:             if ((*l_element_a_supprimer).suivant != NULL)
  345:             {
  346:                 (*(*l_element_a_supprimer).suivant).precedent =
  347:                         (*l_element_a_supprimer).precedent;
  348:             }
  349:             else
  350:             {
  351:                 (*(*l_element_a_supprimer).precedent).suivant = NULL;
  352:             }
  353:         }
  354:         else
  355:         {
  356:             // L'élément est le premier de la liste.
  357: 
  358:             if ((*l_element_a_supprimer).suivant != NULL)
  359:             {
  360:                 (*(*l_element_a_supprimer).suivant).precedent = NULL;
  361:             }
  362: 
  363:             (*(*l_element_a_supprimer).feuille).feuille_statique
  364:                     = (*l_element_a_supprimer).suivant;
  365:         }
  366: 
  367:         liberation(s_etat_processus, (*(*l_element_a_supprimer).variable)
  368:                 .objet);
  369:         free((*(*l_element_a_supprimer).variable).nom);
  370:         free((*l_element_a_supprimer).variable);
  371:         free(l_element_a_supprimer);
  372: 
  373:         erreur = d_absence_erreur;
  374:     }
  375:     else
  376:     {
  377:         erreur = d_erreur;
  378:         (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
  379:     }
  380: 
  381:     return(erreur);
  382: }
  383: 
  384: 
  385: /*
  386: ================================================================================
  387:   Procédure de recherche d'une variable statique par son nom dans la base
  388: ================================================================================
  389:   Entrée :
  390: --------------------------------------------------------------------------------
  391:   Sortie :
  392: --------------------------------------------------------------------------------
  393:   Effets de bord : néant
  394: ================================================================================
  395: */
  396: 
  397: struct_liste_variables_statiques *
  398: recherche_variable_statique(struct_processus *s_etat_processus,
  399:         unsigned char *nom_variable, union_position_variable position,
  400:         unsigned char origine)
  401: {
  402:     int                                 pointeur;
  403: 
  404:     struct_arbre_variables              *l_variable_courante;
  405:     struct_liste_variables_statiques    *l_element_courant;
  406: 
  407:     unsigned char                       *ptr;
  408: 
  409:     l_variable_courante = (*s_etat_processus).s_arbre_variables;
  410:     ptr = nom_variable;
  411: 
  412:     while((*ptr) != d_code_fin_chaine)
  413:     {
  414:         pointeur = (*s_etat_processus).pointeurs_caracteres_variables[*ptr];
  415: 
  416:         if (pointeur < 0)
  417:         {
  418:             // Caractère hors de l'alphabet des variables
  419: 
  420:             (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
  421:             return(NULL);
  422:         }
  423: 
  424:         if ((*l_variable_courante).noeuds[pointeur] == NULL)
  425:         {
  426:             // Le chemin de la variable candidate n'existe pas.
  427:             (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
  428:             return(NULL);
  429:         }
  430: 
  431:         l_variable_courante = (*l_variable_courante).noeuds[pointeur];
  432:         ptr++;
  433:     }
  434: 
  435:     if ((*l_variable_courante).feuille_statique != NULL)
  436:     {
  437:         // Il existe au moins une variable statique du nom requis.
  438: 
  439:         l_element_courant = (*l_variable_courante).feuille_statique;
  440: 
  441:         while(l_element_courant != NULL)
  442:         {
  443:             if ((*(*l_element_courant).variable).origine == 'P')
  444:             {
  445:                 if (((*(*l_element_courant).variable).variable_statique.adresse
  446:                         == position.adresse) &&
  447:                         ((*(*l_element_courant).variable).origine == origine))
  448:                 {
  449:                     (*s_etat_processus).pointeur_variable_statique_courante
  450:                             = (*l_element_courant).variable;
  451:                     return(l_element_courant);
  452:                 }
  453:             }
  454:             else
  455:             {
  456:                 if (((*(*l_element_courant).variable).variable_statique.pointeur
  457:                         == position.pointeur) &&
  458:                         ((*(*l_element_courant).variable).origine == origine))
  459:                 {
  460:                     (*s_etat_processus).pointeur_variable_statique_courante
  461:                             = (*l_element_courant).variable;
  462:                     return(l_element_courant);
  463:                 }
  464:             }
  465: 
  466:             l_element_courant = (*l_element_courant).suivant;
  467:         }
  468:     }
  469: 
  470:     (*s_etat_processus).pointeur_variable_statique_courante = NULL;
  471:     return(NULL);
  472: }
  473: 
  474: // vim: ts=4

CVSweb interface <joel.bertrand@systella.fr>