File:  [local] / rpl / src / gestion_variables_statiques.c
Revision 1.37: download - view: text, annotated - select for diffs - revision graph
Thu Oct 4 15:21:26 2012 UTC (11 years, 7 months ago) by bertrand
Branches: MAIN
CVS tags: HEAD
Première série de patches pour intégrer la gestion des variables statiques
à l'arbre des variables. Attention, cela compile, mais il reste des choses à
faire. Prière de ne pas utilser en l'état de 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 d'ajout d'un bouchon dans la liste des variables statiques
   29: ================================================================================
   30:   Entrée :
   31: --------------------------------------------------------------------------------
   32:   Sortie :
   33: --------------------------------------------------------------------------------
   34:   Effets de bords : néant
   35: ================================================================================
   36: */
   37: 
   38: // Routine ajoutant à la liste des variables statiques créées un 'bouchon'
   39: // qui est un enregistrement dont la variable est NULL. Cela permet
   40: // d'effacer les variables statiques créées dans une expression évaluées car,
   41: // l'adresse de ces variables changeant à chaque évaluation, elles ne sont
   42: // pas utilisables et constituent une fuite de mémoire
   43: 
   44: logical1
   45: ajout_bouchon_variable_statique(struct_processus *s_etat_processus)
   46: {
   47:     struct_liste_variables_statiques    *l_tete_liste;
   48: 
   49:     l_tete_liste = (*s_etat_processus).l_liste_variables_statiques;
   50:     
   51:     if (((*s_etat_processus).l_liste_variables_statiques =
   52:             malloc(sizeof(struct_liste_variables_statiques))) == NULL)
   53:     {
   54:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
   55:         return(d_erreur);
   56:     }
   57: 
   58:     (*(*s_etat_processus).l_liste_variables_statiques).variable = NULL;
   59:     (*(*s_etat_processus).l_liste_variables_statiques).suivant = l_tete_liste;
   60:     (*(*s_etat_processus).l_liste_variables_statiques).precedent = NULL;
   61:     (*l_tete_liste).precedent = (*s_etat_processus).l_liste_variables_statiques;
   62: 
   63:     return(d_absence_erreur);
   64: }
   65: 
   66: 
   67: /*
   68: ================================================================================
   69:   Routine de retrait des variables statiques
   70: ================================================================================
   71:   Entrée :
   72: --------------------------------------------------------------------------------
   73:   Sortie :
   74: --------------------------------------------------------------------------------
   75:   Effets de bords : néant
   76: ================================================================================
   77: */
   78: 
   79: // Cette routine libère toutes les variables statiques jusqu'au prochain
   80: // bouchon ou jusqu'à la fin de la liste si aucun bouchon n'est rencontré.
   81: 
   82: logical1
   83: retrait_variables_statiques(struct_processus *s_etat_processus)
   84: {
   85:     unsigned char                       registre_mode_execution;
   86: 
   87:     registre_mode_execution = (*s_etat_processus).mode_execution_programme;
   88: 
   89:     while((*s_etat_processus).l_liste_variables_statiques != NULL)
   90:     {
   91:         (*s_etat_processus).mode_execution_programme =
   92:                 ((*(*(*s_etat_processus).l_liste_variables_statiques)
   93:                 .variable).origine == 'P') ? 'Y' : 'N';
   94: 
   95:         if ((*(*s_etat_processus).l_liste_variables_statiques).variable == NULL)
   96:         {
   97:             // On vient de tomber sur un bouchon...
   98:             (*s_etat_processus).l_liste_variables_statiques =
   99:                     (*(*s_etat_processus).l_liste_variables_statiques).suivant;
  100:             free((*(*s_etat_processus).l_liste_variables_statiques).precedent);
  101:             (*(*s_etat_processus).l_liste_variables_statiques).precedent = NULL;
  102:             break;
  103:         }
  104: 
  105:         if (retrait_variable_statique(s_etat_processus, (*(*(*s_etat_processus)
  106:                 .l_liste_variables_statiques).variable).nom,
  107:                 (*(*(*s_etat_processus).l_liste_variables_statiques).variable)
  108:                 .variable_statique) == d_erreur)
  109:         {
  110:             (*s_etat_processus).mode_execution_programme =
  111:                     registre_mode_execution;
  112:             return(d_erreur);
  113:         }
  114:     }
  115: 
  116:     (*s_etat_processus).mode_execution_programme = registre_mode_execution;
  117:     return(d_absence_erreur);
  118: }
  119: 
  120: 
  121: /*
  122: ================================================================================
  123:   Routine de création d'une nouvelle variable statique
  124: ================================================================================
  125:   Entrée :
  126: --------------------------------------------------------------------------------
  127:   Sortie :
  128: --------------------------------------------------------------------------------
  129:   Effets de bords : néant
  130: ================================================================================
  131: */
  132: 
  133: logical1
  134: creation_variable_statique(struct_processus *s_etat_processus,
  135:         struct_variable_statique *s_variable)
  136: {
  137:     struct_arbre_variables                  *l_variable_courante;
  138: 
  139:     struct_liste_variables_statiques        *l_nouvel_element;
  140: 
  141:     unsigned char                           *ptr;
  142: 
  143:     // Ajout de la variable en tête de la liste des variables statiques
  144: 
  145:     if ((l_nouvel_element = malloc(sizeof(struct_liste_variables_statiques)))
  146:             == NULL)
  147:     {
  148:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  149:         return(d_erreur);
  150:     }
  151: 
  152:     if (((*l_nouvel_element).variable = malloc(sizeof(
  153:             struct_variable_statique))) == NULL)
  154:     {
  155:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  156:         return(d_erreur);
  157:     }
  158: 
  159:     (*(*l_nouvel_element).variable) = (*s_variable);
  160:     (*l_nouvel_element).suivant = (*s_etat_processus)
  161:             .l_liste_variables_statiques;
  162:     (*(*s_etat_processus).l_liste_variables_statiques).precedent
  163:             = l_nouvel_element;
  164:     (*l_nouvel_element).precedent = NULL;
  165:     (*s_etat_processus).l_liste_variables_statiques = l_nouvel_element;
  166: 
  167:     // Ajout de la variable à la feuille statique de l'arbre des variables
  168: 
  169:     BUG((*s_etat_processus).s_arbre_variables == NULL,
  170:             uprintf("(*s_etat_processus).s_arbre_variables=NULL\n"));
  171: 
  172:     l_variable_courante = (*s_etat_processus).s_arbre_variables;
  173:     ptr = (*s_variable).nom;
  174: 
  175:     while((*ptr) != d_code_fin_chaine)
  176:     {
  177:         BUG((*s_etat_processus).pointeurs_caracteres_variables[*ptr] < 0,
  178:                 uprintf("Variable=\"%s\", (*ptr)='%c'\n", (*s_variable).nom,
  179:                 *ptr));
  180: 
  181:         // La feuille doit préexister car la variable statique est toujours
  182:         // créée depuis une variable locale.
  183: 
  184:         BUG((*l_variable_courante).noeuds[(*s_etat_processus)
  185:                 .pointeurs_caracteres_variables[*ptr]] == NULL,
  186:                 uprintf("Variable=\"%s\", (*ptr)='%c', nullified folder\n"));
  187: 
  188:         l_variable_courante = (*l_variable_courante).noeuds
  189:                 [(*s_etat_processus).pointeurs_caracteres_variables[*ptr]];
  190:         ptr++;
  191:     }
  192: 
  193:     if ((l_nouvel_element = malloc(sizeof(struct_liste_variables_statiques)))
  194:             == NULL)
  195:     {
  196:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  197:         return(d_erreur);
  198:     }
  199: 
  200:     // Dans la feuille statique de l'arbre des variables, on ne balaie
  201:     // les variables que dans l'ordre. Le champ 'reference' est alors utilisé
  202:     // pour sauvegarder une référence vers la liste des variables statiques
  203:     // pour pouvoir purger l'élément en cas de besoin.
  204: 
  205:     (*l_nouvel_element).suivant = (*l_variable_courante).feuille_statique;
  206:     (*l_nouvel_element).precedent = NULL;
  207:     (*(*l_nouvel_element).suivant).precedent = l_nouvel_element;
  208: 
  209:     (*l_nouvel_element).reference =
  210:             (*s_etat_processus).l_liste_variables_statiques;
  211:     (*l_nouvel_element).variable = (*(*s_etat_processus)
  212:             .l_liste_variables_statiques).variable;
  213:     (*l_variable_courante).feuille_statique = l_nouvel_element;
  214:     return(d_absence_erreur);
  215: }
  216: 
  217: 
  218: /*
  219: ================================================================================
  220:   Procédure de retrait d'une variable statique de la base
  221: ================================================================================
  222:   Entrée :
  223: --------------------------------------------------------------------------------
  224:   Sortie :
  225: --------------------------------------------------------------------------------
  226:   Effets de bord : néant
  227: ================================================================================
  228: */
  229: 
  230: logical1
  231: retrait_variable_statique(struct_processus *s_etat_processus,
  232:         unsigned char *nom_variable, union_position_variable position)
  233: {
  234:     struct_liste_variables_statiques        *l_element_a_supprimer;
  235:     struct_liste_variables_statiques        *l_element_liste_a_supprimer;
  236: 
  237:     logical1                                erreur;
  238: 
  239:     if ((l_element_a_supprimer = recherche_variable_statique(s_etat_processus,
  240:             nom_variable, position, ((*s_etat_processus)
  241:             .mode_execution_programme == 'Y') ? 'P' : 'E')) != NULL)
  242:     {
  243:         // (*s_etat_processus).pointeur_variable_statique_courante
  244:         // pointe sur la variable à éliminer. Cette variable est celle qui
  245:         // est présente dans l'une des feuilles statiques de l'arbre des
  246:         // variables.
  247: 
  248:         l_element_liste_a_supprimer = (*l_element_a_supprimer).reference;
  249: 
  250:         // Suppression de la liste des variables statiques
  251: 
  252:         if ((*l_element_liste_a_supprimer).precedent != NULL)
  253:         {
  254:             (*(*l_element_liste_a_supprimer).precedent).suivant =
  255:                     (*l_element_liste_a_supprimer).suivant;
  256:         }
  257:         else
  258:         {
  259:             (*(*l_element_liste_a_supprimer).suivant).precedent = NULL;
  260:         }
  261: 
  262:         if ((*l_element_liste_a_supprimer).suivant != NULL)
  263:         {
  264:             (*(*l_element_liste_a_supprimer).suivant).precedent =
  265:                     (*l_element_liste_a_supprimer).precedent;
  266:         }
  267:         else
  268:         {
  269:             (*(*l_element_liste_a_supprimer).precedent).suivant = NULL;
  270:         }
  271: 
  272:         free(l_element_liste_a_supprimer);
  273: 
  274:         // Suppression depuis la feuille statique. Le champ 'precedent' ne sert
  275:         // pas car la liste est simplement chaînée.
  276: 
  277:         if ((*l_element_a_supprimer).precedent != NULL)
  278:         {
  279:             (*(*l_element_a_supprimer).precedent).suivant =
  280:                     (*l_element_a_supprimer).suivant;
  281:         }
  282:         else
  283:         {
  284:             (*(*l_element_a_supprimer).suivant).precedent = NULL;
  285:         }
  286: 
  287:         if ((*l_element_a_supprimer).suivant != NULL)
  288:         {
  289:             (*(*l_element_a_supprimer).suivant).precedent =
  290:                     (*l_element_a_supprimer).precedent;
  291:         }
  292:         else
  293:         {
  294:             (*(*l_element_a_supprimer).precedent).suivant = NULL;
  295:         }
  296: 
  297:         liberation(s_etat_processus, (*(*l_element_a_supprimer).variable)
  298:                 .objet);
  299:         free((*(*l_element_a_supprimer).variable).nom);
  300:         free((*l_element_a_supprimer).variable);
  301:         free(l_element_a_supprimer);
  302: 
  303:         erreur = d_absence_erreur;
  304:     }
  305:     else
  306:     {
  307:         erreur = d_erreur;
  308:         (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
  309:     }
  310: 
  311:     return erreur;
  312: }
  313: 
  314: 
  315: /*
  316: ================================================================================
  317:   Procédure de recherche d'une variable statique par son nom dans la base
  318: ================================================================================
  319:   Entrée :
  320: --------------------------------------------------------------------------------
  321:   Sortie :
  322: --------------------------------------------------------------------------------
  323:   Effets de bord : néant
  324: ================================================================================
  325: */
  326: 
  327: struct_liste_variables_statiques *
  328: recherche_variable_statique(struct_processus *s_etat_processus,
  329:         unsigned char *nom_variable, union_position_variable position,
  330:         unsigned char origine)
  331: {
  332:     int                                 pointeur;
  333: 
  334:     struct_arbre_variables              *l_variable_courante;
  335:     struct_liste_variables_statiques    *l_element_courant;
  336: 
  337:     unsigned char                       *ptr;
  338: 
  339:     l_variable_courante = (*s_etat_processus).s_arbre_variables;
  340:     ptr = nom_variable;
  341: 
  342:     while((*ptr) != d_code_fin_chaine)
  343:     {
  344:         pointeur = (*s_etat_processus).pointeurs_caracteres_variables[*ptr];
  345: 
  346:         if (pointeur < 0)
  347:         {
  348:             // Caractère hors de l'alphabet des variables
  349: 
  350:             (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
  351:             return(NULL);
  352:         }
  353: 
  354:         if ((*l_variable_courante).noeuds[pointeur] == NULL)
  355:         {
  356:             // Le chemin de la variable candidate n'existe pas.
  357:             (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
  358:             return(NULL);
  359:         }
  360: 
  361:         l_variable_courante = (*l_variable_courante).noeuds[pointeur];
  362:         ptr++;
  363:     }
  364: 
  365:     if ((*l_variable_courante).feuille_statique != NULL)
  366:     {
  367:         // Il existe au moins une variable statique du nom requis.
  368: 
  369:         l_element_courant = (*l_variable_courante).feuille_statique;
  370: 
  371:         while(l_element_courant != NULL)
  372:         {
  373:             if ((*(*l_element_courant).variable).origine == 'P')
  374:             {
  375:                 if (((*(*l_element_courant).variable).variable_statique.adresse
  376:                         == position.adresse) &&
  377:                         ((*(*l_element_courant).variable).origine == origine))
  378:                 {
  379:                     (*s_etat_processus).pointeur_variable_statique_courante
  380:                             =   (*l_element_courant).variable;
  381:                     return(l_element_courant);
  382:                 }
  383:             }
  384:             else
  385:             {
  386:                 if (((*(*l_element_courant).variable).variable_statique.pointeur
  387:                         == position.pointeur) &&
  388:                         ((*(*l_element_courant).variable).origine == origine))
  389:                 {
  390:                     (*s_etat_processus).pointeur_variable_statique_courante
  391:                             =   (*l_element_courant).variable;
  392:                     return(l_element_courant);
  393:                 }
  394:             }
  395:         }
  396:     }
  397: 
  398:     (*s_etat_processus).pointeur_variable_statique_courante = NULL;
  399:     return(NULL);
  400: }
  401: 
  402: // vim: ts=4

CVSweb interface <joel.bertrand@systella.fr>