File:  [local] / rpl / src / gestion_variables_statiques.c
Revision 1.39: download - view: text, annotated - select for diffs - revision graph
Sun Oct 7 13:44:08 2012 UTC (11 years, 7 months ago) by bertrand
Branches: MAIN
CVS tags: HEAD
Correction des violations d'accès dans la gestion des variables statiques.

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

CVSweb interface <joel.bertrand@systella.fr>