File:  [local] / rpl / src / gestion_variables_statiques.c
Revision 1.38: download - view: text, annotated - select for diffs - revision graph
Sun Oct 7 08:18:35 2012 UTC (11 years, 7 months ago) by bertrand
Branches: MAIN
CVS tags: HEAD
Autre série de patches pour les variables statiques. Attention, il
reste une erreur de violation d'accès.

    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: printf("<0>\n");
  107:     if ((l_nouvel_element = malloc(sizeof(struct_liste_variables_statiques)))
  108:             == NULL)
  109:     {
  110:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  111:         return(d_erreur);
  112:     }
  113: 
  114:     if (((*l_nouvel_element).variable = malloc(sizeof(
  115:             struct_variable_statique))) == NULL)
  116:     {
  117:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  118:         return(d_erreur);
  119:     }
  120: 
  121:     (*(*l_nouvel_element).variable) = (*s_variable);
  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: printf("<1>\n");
  293:     if ((l_element_a_supprimer = recherche_variable_statique(s_etat_processus,
  294:             nom_variable, position, ((*s_etat_processus)
  295:             .mode_execution_programme == 'Y') ? 'P' : 'E')) != NULL)
  296:     {
  297: printf("<2>\n");
  298:         // (*s_etat_processus).pointeur_variable_statique_courante
  299:         // pointe sur la variable à éliminer. Cette variable est celle qui
  300:         // est présente dans l'une des feuilles statiques de l'arbre des
  301:         // variables.
  302: 
  303:         l_element_liste_a_supprimer = (*l_element_a_supprimer).reference;
  304: 
  305:         // Suppression de la liste des variables statiques
  306: 
  307:         if ((*l_element_liste_a_supprimer).precedent != NULL)
  308:         {
  309:             (*(*l_element_liste_a_supprimer).precedent).suivant =
  310:                     (*l_element_liste_a_supprimer).suivant;
  311:         }
  312:         else
  313:         {
  314:             if ((*l_element_liste_a_supprimer).suivant != NULL)
  315:             {
  316:                 (*(*l_element_liste_a_supprimer).suivant).precedent = NULL;
  317:             }
  318: 
  319:             (*s_etat_processus).l_liste_variables_statiques =
  320:                     (*l_element_liste_a_supprimer).suivant;
  321:         }
  322: 
  323:         if ((*l_element_liste_a_supprimer).suivant != NULL)
  324:         {
  325:             (*(*l_element_liste_a_supprimer).suivant).precedent =
  326:                     (*l_element_liste_a_supprimer).precedent;
  327:         }
  328:         else
  329:         {
  330:             (*(*l_element_liste_a_supprimer).precedent).suivant = NULL;
  331:         }
  332: 
  333:         free(l_element_liste_a_supprimer);
  334: 
  335:         // Suppression depuis la feuille statique. Le champ 'precedent' ne sert
  336:         // pas car la liste est simplement chaînée.
  337: 
  338:         if ((*l_element_a_supprimer).precedent != NULL)
  339:         {
  340:             (*(*l_element_a_supprimer).precedent).suivant =
  341:                     (*l_element_a_supprimer).suivant;
  342:         }
  343:         else
  344:         {
  345:             (*(*l_element_a_supprimer).suivant).precedent = NULL;
  346:             (*(*l_element_a_supprimer).feuille).feuille_statique
  347:                     = (*l_element_a_supprimer).suivant;
  348:         }
  349: 
  350:         if ((*l_element_a_supprimer).suivant != NULL)
  351:         {
  352:             (*(*l_element_a_supprimer).suivant).precedent =
  353:                     (*l_element_a_supprimer).precedent;
  354:         }
  355:         else
  356:         {
  357:             (*(*l_element_a_supprimer).precedent).suivant = NULL;
  358:         }
  359: 
  360:         liberation(s_etat_processus, (*(*l_element_a_supprimer).variable)
  361:                 .objet);
  362:         free((*(*l_element_a_supprimer).variable).nom);
  363:         free((*l_element_a_supprimer).variable);
  364:         free(l_element_a_supprimer);
  365: 
  366:         erreur = d_absence_erreur;
  367:     }
  368:     else
  369:     {
  370:         erreur = d_erreur;
  371:         (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
  372:     }
  373: 
  374:     return erreur;
  375: }
  376: 
  377: 
  378: /*
  379: ================================================================================
  380:   Procédure de recherche d'une variable statique par son nom dans la base
  381: ================================================================================
  382:   Entrée :
  383: --------------------------------------------------------------------------------
  384:   Sortie :
  385: --------------------------------------------------------------------------------
  386:   Effets de bord : néant
  387: ================================================================================
  388: */
  389: 
  390: struct_liste_variables_statiques *
  391: recherche_variable_statique(struct_processus *s_etat_processus,
  392:         unsigned char *nom_variable, union_position_variable position,
  393:         unsigned char origine)
  394: {
  395:     int                                 pointeur;
  396: 
  397:     struct_arbre_variables              *l_variable_courante;
  398:     struct_liste_variables_statiques    *l_element_courant;
  399: 
  400:     unsigned char                       *ptr;
  401: 
  402:     l_variable_courante = (*s_etat_processus).s_arbre_variables;
  403:     ptr = nom_variable;
  404: 
  405:     while((*ptr) != d_code_fin_chaine)
  406:     {
  407:         pointeur = (*s_etat_processus).pointeurs_caracteres_variables[*ptr];
  408: 
  409:         if (pointeur < 0)
  410:         {
  411:             // Caractère hors de l'alphabet des variables
  412: 
  413:             (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
  414:             return(NULL);
  415:         }
  416: 
  417:         if ((*l_variable_courante).noeuds[pointeur] == NULL)
  418:         {
  419:             // Le chemin de la variable candidate n'existe pas.
  420:             (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
  421:             return(NULL);
  422:         }
  423: 
  424:         l_variable_courante = (*l_variable_courante).noeuds[pointeur];
  425:         ptr++;
  426:     }
  427: 
  428:     if ((*l_variable_courante).feuille_statique != NULL)
  429:     {
  430:         // Il existe au moins une variable statique du nom requis.
  431: 
  432:         l_element_courant = (*l_variable_courante).feuille_statique;
  433: 
  434:         while(l_element_courant != NULL)
  435:         {
  436:             if ((*(*l_element_courant).variable).origine == 'P')
  437:             {
  438:                 if (((*(*l_element_courant).variable).variable_statique.adresse
  439:                         == position.adresse) &&
  440:                         ((*(*l_element_courant).variable).origine == origine))
  441:                 {
  442:                     (*s_etat_processus).pointeur_variable_statique_courante
  443:                             = (*l_element_courant).variable;
  444:                     return(l_element_courant);
  445:                 }
  446:             }
  447:             else
  448:             {
  449:                 if (((*(*l_element_courant).variable).variable_statique.pointeur
  450:                         == position.pointeur) &&
  451:                         ((*(*l_element_courant).variable).origine == origine))
  452:                 {
  453:                     (*s_etat_processus).pointeur_variable_statique_courante
  454:                             = (*l_element_courant).variable;
  455:                     return(l_element_courant);
  456:                 }
  457:             }
  458: 
  459:             l_element_courant = (*l_element_courant).suivant;
  460:         }
  461:     }
  462: 
  463:     (*s_etat_processus).pointeur_variable_statique_courante = NULL;
  464:     return(NULL);
  465: }
  466: 
  467: // vim: ts=4

CVSweb interface <joel.bertrand@systella.fr>