File:  [local] / rpl / src / gestion_variables_statiques.c
Revision 1.42: download - view: text, annotated - select for diffs - revision graph
Thu Dec 13 16:59:41 2012 UTC (11 years, 4 months ago) by bertrand
Branches: MAIN
CVS tags: HEAD
Première série de patches pour inclure les variables partagées dans
l'arbre des variables. Attention, le résultat ne compile pas.

    1: /*
    2: ================================================================================
    3:   RPL/2 (R) version 4.1.11
    4:   Copyright (C) 1989-2012 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).feuille_partagee = NULL;
  148:         (*(*s_etat_processus).s_arbre_variables).noeuds_utilises = 0;
  149:         (*(*s_etat_processus).s_arbre_variables).indice_tableau_pere = -1;
  150:         (*(*s_etat_processus).s_arbre_variables).noeud_pere = NULL;
  151:         INITIALISATION_MUTEX((*(*s_etat_processus).s_arbre_variables)
  152:                 .mutex_feuille_partagee);
  153: 
  154:         if (((*(*s_etat_processus).s_arbre_variables).noeuds =
  155:                 allocation_tableau_noeuds(s_etat_processus)) == NULL)
  156:         {
  157:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  158:             return(d_erreur);
  159:         }
  160: 
  161:         for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
  162:         {
  163:             (*(*s_etat_processus).s_arbre_variables).noeuds[i] = NULL;
  164:         }
  165:     }
  166: 
  167:     l_variable_courante = (*s_etat_processus).s_arbre_variables;
  168:     ptr = (*s_variable).nom;
  169: 
  170:     while((*ptr) != d_code_fin_chaine)
  171:     {
  172:         BUG((*s_etat_processus).pointeurs_caracteres_variables[*ptr] < 0,
  173:                 uprintf("Variable=\"%s\", (*ptr)='%c'\n", (*s_variable).nom,
  174:                 *ptr));
  175: 
  176:         if ((*l_variable_courante).noeuds[(*s_etat_processus)
  177:                 .pointeurs_caracteres_variables[*ptr]] == NULL)
  178:         {
  179:             // Le noeud n'existe pas encore, on le crée et on le marque
  180:             // comme utilisé dans la structure parente.
  181: 
  182:             if (((*l_variable_courante).noeuds[(*s_etat_processus)
  183:                     .pointeurs_caracteres_variables[*ptr]] =
  184:                     allocation_noeud(s_etat_processus)) == NULL)
  185:             {
  186:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  187:                 return(d_erreur);
  188:             }
  189: 
  190:             (*l_variable_courante).noeuds_utilises++;
  191: 
  192:             // La feuille est par défaut vide et aucun élément du tableau noeuds
  193:             // (les branches qui peuvent être issues de ce nouveau noeud)
  194:             // n'est encore utilisée.
  195: 
  196:             (*(*l_variable_courante).noeuds[(*s_etat_processus)
  197:                     .pointeurs_caracteres_variables[*ptr]]).feuille = NULL;
  198:             (*(*l_variable_courante).noeuds[(*s_etat_processus)
  199:                     .pointeurs_caracteres_variables[*ptr]]).feuille_statique
  200:                     = NULL;
  201:             (*(*l_variable_courante).noeuds[(*s_etat_processus)
  202:                     .pointeurs_caracteres_variables[*ptr]]).feuille_partagee
  203:                     = NULL;
  204:             (*(*l_variable_courante).noeuds[(*s_etat_processus)
  205:                     .pointeurs_caracteres_variables[*ptr]]).noeuds_utilises = 0;
  206:             INITIALISATION_MUTEX((*(*l_variable_courante).noeuds
  207:                     [(*s_etat_processus).pointeurs_caracteres_variables[*ptr]])
  208:                     .mutex_feuille_partagee);
  209: 
  210:             // Le champ noeud_pere de la structure créée pointe sur
  211:             // la structure parente et l'indice tableau_pere correspond à la
  212:             // position réelle dans le tableau noeuds[] de la structure parente
  213:             // du noeud courant. Cette valeur sera utilisée lors de la
  214:             // destruction du noeud pour annuler le pointeur contenu dans
  215:             // le tableau noeuds[] de la structure parente.
  216: 
  217:             (*(*l_variable_courante).noeuds[(*s_etat_processus)
  218:                     .pointeurs_caracteres_variables[*ptr]]).noeud_pere =
  219:                     l_variable_courante;
  220:             (*(*l_variable_courante).noeuds[(*s_etat_processus)
  221:                     .pointeurs_caracteres_variables[*ptr]])
  222:                     .indice_tableau_pere = (*s_etat_processus)
  223:                     .pointeurs_caracteres_variables[*ptr];
  224: 
  225:             // Allocation du tableau noeuds[] et initialisation à zéro de
  226:             // tous les pointeurs.
  227: 
  228:             if (((*(*l_variable_courante).noeuds[(*s_etat_processus)
  229:                     .pointeurs_caracteres_variables[*ptr]]).noeuds =
  230:                     allocation_tableau_noeuds(s_etat_processus)) == NULL)
  231:             {
  232:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  233:                 return(d_erreur);
  234:             }
  235: 
  236:             for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
  237:             {
  238:                 (*(*l_variable_courante).noeuds[(*s_etat_processus)
  239:                         .pointeurs_caracteres_variables[*ptr]]).noeuds[i]
  240:                         = NULL;
  241:             }
  242:         }
  243: 
  244:         l_variable_courante = (*l_variable_courante).noeuds
  245:                 [(*s_etat_processus).pointeurs_caracteres_variables[*ptr]];
  246:         ptr++;
  247:     }
  248: 
  249:     if ((l_nouvel_element = malloc(sizeof(struct_liste_variables_statiques)))
  250:             == NULL)
  251:     {
  252:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  253:         return(d_erreur);
  254:     }
  255: 
  256:     // Dans la feuille statique de l'arbre des variables, on ne balaie
  257:     // les variables que dans l'ordre. Le champ 'reference' est alors utilisé
  258:     // pour sauvegarder une référence vers la liste des variables statiques
  259:     // pour pouvoir purger l'élément en cas de besoin.
  260: 
  261:     (*l_nouvel_element).suivant = (*l_variable_courante).feuille_statique;
  262:     (*l_nouvel_element).precedent = NULL;
  263: 
  264:     if ((*l_nouvel_element).suivant != NULL)
  265:     {
  266:         (*(*l_nouvel_element).suivant).precedent = l_nouvel_element;
  267:     }
  268: 
  269:     (*l_nouvel_element).reference =
  270:             (*s_etat_processus).l_liste_variables_statiques;
  271:     (*l_nouvel_element).variable = (*(*s_etat_processus)
  272:             .l_liste_variables_statiques).variable;
  273:     (*l_variable_courante).feuille_statique = l_nouvel_element;
  274:     (*l_nouvel_element).feuille = l_variable_courante;
  275: 
  276:     return(d_absence_erreur);
  277: }
  278: 
  279: 
  280: /*
  281: ================================================================================
  282:   Procédure de retrait d'une variable statique de la base
  283: ================================================================================
  284:   Entrée :
  285: --------------------------------------------------------------------------------
  286:   Sortie :
  287: --------------------------------------------------------------------------------
  288:   Effets de bord : néant
  289: ================================================================================
  290: */
  291: 
  292: logical1
  293: retrait_variable_statique(struct_processus *s_etat_processus,
  294:         unsigned char *nom_variable, union_position_variable position)
  295: {
  296:     struct_liste_variables_statiques        *l_element_a_supprimer;
  297:     struct_liste_variables_statiques        *l_element_liste_a_supprimer;
  298: 
  299:     logical1                                erreur;
  300: 
  301:     if ((l_element_a_supprimer = recherche_variable_statique(s_etat_processus,
  302:             nom_variable, position, ((*s_etat_processus)
  303:             .mode_execution_programme == 'Y') ? 'P' : 'E')) != NULL)
  304:     {
  305:         // (*s_etat_processus).pointeur_variable_statique_courante
  306:         // pointe sur la variable à éliminer. Cette variable est celle qui
  307:         // est présente dans l'une des feuilles statiques de l'arbre des
  308:         // variables.
  309: 
  310:         l_element_liste_a_supprimer = (*l_element_a_supprimer).reference;
  311: 
  312:         // Suppression de la liste des variables statiques
  313: 
  314:         if ((*l_element_liste_a_supprimer).precedent != NULL)
  315:         {
  316:             // L'élément à supprimer n'est pas le premier de la liste.
  317: 
  318:             (*(*l_element_liste_a_supprimer).precedent).suivant =
  319:                     (*l_element_liste_a_supprimer).suivant;
  320: 
  321:             if ((*l_element_liste_a_supprimer).suivant != NULL)
  322:             {
  323:                 // Il y a un élément suivant. On le chaîne.
  324:                 (*(*l_element_liste_a_supprimer).suivant).precedent = NULL;
  325:             }
  326:         }
  327:         else
  328:         {
  329:             // L'élement est le premier de la liste. S'il y a un élément
  330:             // suivant, on le chaîne.
  331: 
  332:             if ((*l_element_liste_a_supprimer).suivant != NULL)
  333:             {
  334:                 (*(*l_element_liste_a_supprimer).suivant).precedent = NULL;
  335:             }
  336: 
  337:             (*s_etat_processus).l_liste_variables_statiques =
  338:                     (*l_element_liste_a_supprimer).suivant;
  339:         }
  340: 
  341:         free(l_element_liste_a_supprimer);
  342: 
  343:         // Suppression depuis la feuille statique. Le champ 'precedent' ne sert
  344:         // pas car la liste est simplement chaînée.
  345: 
  346:         if ((*l_element_a_supprimer).precedent != NULL)
  347:         {
  348:             // L'élément n'est pas le premier de la liste.
  349: 
  350:             (*(*l_element_a_supprimer).precedent).suivant =
  351:                     (*l_element_a_supprimer).suivant;
  352: 
  353:             if ((*l_element_a_supprimer).suivant != NULL)
  354:             {
  355:                 (*(*l_element_a_supprimer).suivant).precedent =
  356:                         (*l_element_a_supprimer).precedent;
  357:             }
  358:             else
  359:             {
  360:                 (*(*l_element_a_supprimer).precedent).suivant = NULL;
  361:             }
  362:         }
  363:         else
  364:         {
  365:             // L'élément est le premier de la liste.
  366: 
  367:             if ((*l_element_a_supprimer).suivant != NULL)
  368:             {
  369:                 (*(*l_element_a_supprimer).suivant).precedent = NULL;
  370:             }
  371: 
  372:             (*(*l_element_a_supprimer).feuille).feuille_statique
  373:                     = (*l_element_a_supprimer).suivant;
  374:         }
  375: 
  376:         liberation(s_etat_processus, (*(*l_element_a_supprimer).variable)
  377:                 .objet);
  378:         free((*(*l_element_a_supprimer).variable).nom);
  379:         free((*l_element_a_supprimer).variable);
  380:         free(l_element_a_supprimer);
  381: 
  382:         erreur = d_absence_erreur;
  383:     }
  384:     else
  385:     {
  386:         erreur = d_erreur;
  387:         (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
  388:     }
  389: 
  390:     return erreur;
  391: }
  392: 
  393: 
  394: /*
  395: ================================================================================
  396:   Procédure de recherche d'une variable statique par son nom dans la base
  397: ================================================================================
  398:   Entrée :
  399: --------------------------------------------------------------------------------
  400:   Sortie :
  401: --------------------------------------------------------------------------------
  402:   Effets de bord : néant
  403: ================================================================================
  404: */
  405: 
  406: struct_liste_variables_statiques *
  407: recherche_variable_statique(struct_processus *s_etat_processus,
  408:         unsigned char *nom_variable, union_position_variable position,
  409:         unsigned char origine)
  410: {
  411:     int                                 pointeur;
  412: 
  413:     struct_arbre_variables              *l_variable_courante;
  414:     struct_liste_variables_statiques    *l_element_courant;
  415: 
  416:     unsigned char                       *ptr;
  417: 
  418:     l_variable_courante = (*s_etat_processus).s_arbre_variables;
  419:     ptr = nom_variable;
  420: 
  421:     while((*ptr) != d_code_fin_chaine)
  422:     {
  423:         pointeur = (*s_etat_processus).pointeurs_caracteres_variables[*ptr];
  424: 
  425:         if (pointeur < 0)
  426:         {
  427:             // Caractère hors de l'alphabet des variables
  428: 
  429:             (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
  430:             return(NULL);
  431:         }
  432: 
  433:         if ((*l_variable_courante).noeuds[pointeur] == NULL)
  434:         {
  435:             // Le chemin de la variable candidate n'existe pas.
  436:             (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
  437:             return(NULL);
  438:         }
  439: 
  440:         l_variable_courante = (*l_variable_courante).noeuds[pointeur];
  441:         ptr++;
  442:     }
  443: 
  444:     if ((*l_variable_courante).feuille_statique != NULL)
  445:     {
  446:         // Il existe au moins une variable statique du nom requis.
  447: 
  448:         l_element_courant = (*l_variable_courante).feuille_statique;
  449: 
  450:         while(l_element_courant != NULL)
  451:         {
  452:             if ((*(*l_element_courant).variable).origine == 'P')
  453:             {
  454:                 if (((*(*l_element_courant).variable).variable_statique.adresse
  455:                         == position.adresse) &&
  456:                         ((*(*l_element_courant).variable).origine == origine))
  457:                 {
  458:                     (*s_etat_processus).pointeur_variable_statique_courante
  459:                             = (*l_element_courant).variable;
  460:                     return(l_element_courant);
  461:                 }
  462:             }
  463:             else
  464:             {
  465:                 if (((*(*l_element_courant).variable).variable_statique.pointeur
  466:                         == position.pointeur) &&
  467:                         ((*(*l_element_courant).variable).origine == origine))
  468:                 {
  469:                     (*s_etat_processus).pointeur_variable_statique_courante
  470:                             = (*l_element_courant).variable;
  471:                     return(l_element_courant);
  472:                 }
  473:             }
  474: 
  475:             l_element_courant = (*l_element_courant).suivant;
  476:         }
  477:     }
  478: 
  479:     (*s_etat_processus).pointeur_variable_statique_courante = NULL;
  480:     return(NULL);
  481: }
  482: 
  483: // vim: ts=4

CVSweb interface <joel.bertrand@systella.fr>