File:  [local] / rpl / src / gestion_variables_statiques.c
Revision 1.40: download - view: text, annotated - select for diffs - revision graph
Sun Oct 7 21:57:48 2012 UTC (11 years, 6 months ago) by bertrand
Branches: MAIN
CVS tags: HEAD
Patches pour l'insertion des variables statiques dans l'arbre des variables.
Reste un segfault dû au fait que la structure des variables statiques n'est
pas correctement copiée lors de SPAWN.

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

CVSweb interface <joel.bertrand@systella.fr>