File:  [local] / rpl / src / gestion_variables.c
Revision 1.33: download - view: text, annotated - select for diffs - revision graph
Sun Jun 19 17:48:27 2011 UTC (12 years, 10 months ago) by bertrand
Branches: MAIN
CVS tags: HEAD
Correction de problèmes de pointeurs et de fuites de mémoire dans
la nouvelle gestion des variables. Ces nouvelles routines semblent maintenant
fonctionner sans problème dans le cas monothread et non compilé. Je
ne constate plus de fuite de mémoire ni d'opérations de lecture ou d'écriture
scabreuses.

    1: /*
    2: ================================================================================
    3:   RPL/2 (R) version 4.1.0.prerelease.0
    4:   Copyright (C) 1989-2011 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:   Fonction de debug
   29: ================================================================================
   30:   Entrée :
   31: --------------------------------------------------------------------------------
   32:   Sortie :
   33: --------------------------------------------------------------------------------
   34:   Effets de bords : néant
   35: ================================================================================
   36: */
   37: 
   38: static void
   39: liste_variables_par_niveaux(struct_processus *s_etat_processus)
   40: {
   41:     int                     c;
   42: 
   43:     logical1                fin;
   44: 
   45:     struct_liste_variables  *l;
   46: 
   47:     struct_liste_chainee    *e;
   48: 
   49:     printf("===========================================================\n");
   50:     printf("  Liste des variables par niveaux\n");
   51:     printf("===========================================================\n");
   52: 
   53:     printf("Backward\n");
   54:     l = (*s_etat_processus).l_liste_variables_par_niveau;
   55:     c = 0;
   56:     fin = d_faux;
   57: 
   58:     do
   59:     {
   60:         l = l->precedent;
   61:         e = l->liste;
   62: 
   63:         while(e != NULL)
   64:         {
   65:             printf("%s (%p, %d) ", ((struct_variable *) e->donnee)->nom,
   66:                     e->donnee, ((struct_variable *) e->donnee)->niveau);
   67:             e = e->suivant;
   68:             c++;
   69:             if (c > 100)
   70:             {
   71:                 fin = d_vrai;
   72:                 break;
   73:             }
   74:         }
   75: 
   76:         printf("\n");
   77: 
   78:     } while(l != (*s_etat_processus).l_liste_variables_par_niveau);
   79: 
   80:     printf("Forward\n");
   81:     l = (*s_etat_processus).l_liste_variables_par_niveau;
   82:     c = 0;
   83: 
   84:     do
   85:     {
   86:         e = l->liste;
   87: 
   88:         while(e != NULL)
   89:         {
   90:             printf("%s (%p, %d) ", ((struct_variable *) e->donnee)->nom,
   91:                     e->donnee, ((struct_variable *) e->donnee)->niveau);
   92:             e = e->suivant;
   93:             c++;
   94:             if (c > 100) exit(0);
   95:         }
   96: 
   97:         printf("\n");
   98: 
   99:         l = l->suivant;
  100:     } while(l != (*s_etat_processus).l_liste_variables_par_niveau);
  101: 
  102:     printf("===========================================================\n");
  103: 
  104:     if (fin == d_vrai) exit(0);
  105: 
  106:     return;
  107: }
  108: 
  109: static void
  110: liste_variables_tas(struct_processus *s_etat_processus,
  111:         struct_arbre_variables *arbre)
  112: {
  113:     int                     c;
  114:     int                     i;
  115: 
  116:     logical1                fin;
  117: 
  118:     struct_liste_variables  *l;
  119: 
  120:     fin = d_faux;
  121: 
  122:     if ((*arbre).feuille != NULL)
  123:     {
  124:         printf("Feuille %p\n", (*arbre).feuille);
  125: 
  126:         printf("  Backward\n");
  127: 
  128:         l = (*arbre).feuille;
  129:         c = 0;
  130:         fin = d_faux;
  131: 
  132:         do
  133:         {
  134:             l = l->precedent;
  135:             c++;
  136:             if (c > 100)
  137:             {
  138:                 fin = d_vrai;
  139:                 break;
  140:             }
  141:             printf("    %s (%p, %d)\n", l->variable->nom, l->variable,
  142:                     l->variable->niveau);
  143:         } while((*arbre).feuille != l);
  144: 
  145:         printf("  Forward\n");
  146: 
  147:         l = (*arbre).feuille;
  148:         c = 0;
  149: 
  150:         do
  151:         {
  152:             c++;
  153:             if (c > 100) exit(0);
  154:             printf("    %s (%p, %d)\n", l->variable->nom, l->variable,
  155:                     l->variable->niveau);
  156:             l = l->suivant;
  157:         } while((*arbre).feuille != l);
  158:     }
  159: 
  160:     for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
  161:     {
  162:         if ((*arbre).noeuds[i] != NULL)
  163:         {
  164:             liste_variables_tas(s_etat_processus, (*arbre).noeuds[i]);
  165:         }
  166:     }
  167: 
  168:     if (fin == d_vrai) exit(0);
  169: 
  170:     return;
  171: }
  172: 
  173: 
  174: static void
  175: liste_variables_par_feuilles(struct_processus *s_etat_processus)
  176: {
  177:     printf("===========================================================\n");
  178:     printf("  Liste des variables sur le tas\n");
  179:     printf("===========================================================\n");
  180: 
  181:     liste_variables_tas(s_etat_processus,
  182:             (*s_etat_processus).s_arbre_variables);
  183: 
  184:     printf("===========================================================\n");
  185: 
  186:     return;
  187: }
  188: 
  189: 
  190: /*
  191: ================================================================================
  192:   Routine de création d'une nouvelle variable
  193: ================================================================================
  194:   Entrée : autorisation_creation_variable_statique vaut 'v' ou 's'.
  195:   dans le cas 'v', la variable est volatile.
  196:   dans le cas 's', elle est statique.
  197:   Entrée : autorisation_creation_variable_partagee vaut 'p' ou 's'.
  198:   dans le cas 'p', la variable est privée.
  199:   dans le cas 's', elle est partagée.
  200: --------------------------------------------------------------------------------
  201:   Sortie :
  202: --------------------------------------------------------------------------------
  203:   Effets de bords : néant
  204: ================================================================================
  205: */
  206: 
  207: static logical1
  208: ajout_variable(struct_processus *s_etat_processus, struct_variable *s_variable)
  209: {
  210:     int                         i;
  211: 
  212:     logical1                    niveau_acceptable;
  213: 
  214:     struct_liste_variables      *l_nouvelle_variable;
  215:     struct_liste_variables      *l_variable_candidate;
  216: 
  217:     struct_arbre_variables      *l_variable_courante;
  218:     struct_arbre_variables      *l_variable_precedente;
  219: 
  220:     struct_liste_chainee        *l_nouvel_element;
  221: 
  222:     unsigned char               *ptr;
  223: 
  224:     void                        *pointeur_variable_cree;
  225: 
  226:     if ((*s_etat_processus).s_arbre_variables == NULL)
  227:     {
  228:         if (((*s_etat_processus).s_arbre_variables =
  229:                 malloc(sizeof(struct_arbre_variables))) == NULL)
  230:         {
  231:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  232:             return(d_erreur);
  233:         }
  234: 
  235:         (*(*s_etat_processus).s_arbre_variables).feuille = NULL;
  236:         (*(*s_etat_processus).s_arbre_variables).noeuds_utilises = 0;
  237:         (*(*s_etat_processus).s_arbre_variables).indice_tableau_pere = -1;
  238:         (*(*s_etat_processus).s_arbre_variables).noeud_pere = NULL;
  239: 
  240:         if (((*(*s_etat_processus).s_arbre_variables).noeuds =
  241:                 malloc((*s_etat_processus).nombre_caracteres_variables
  242:                 * sizeof(struct_arbre_variables))) == NULL)
  243:         {
  244:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  245:             return(d_erreur);
  246:         }
  247: 
  248:         for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
  249:         {
  250:             (*(*s_etat_processus).s_arbre_variables).noeuds[i] = NULL;
  251:         }
  252:     }
  253: 
  254:     l_variable_precedente = NULL;
  255:     l_variable_courante = (*s_etat_processus).s_arbre_variables;
  256:     ptr = (*s_variable).nom;
  257: 
  258:     while((*ptr) != d_code_fin_chaine)
  259:     {
  260:         BUG((*s_etat_processus).pointeurs_caracteres_variables[*ptr] < 0,
  261:                 printf("Variable=\"%s\", (*ptr)='%c'\n", (*s_variable).nom,
  262:                 *ptr));
  263: 
  264:         if ((*l_variable_courante).noeuds[(*s_etat_processus)
  265:                 .pointeurs_caracteres_variables[*ptr]] == NULL)
  266:         {
  267:             // Le noeud n'existe pas encore, on le crée et on le marque
  268:             // comme utilisé dans la structure parente.
  269: 
  270:             if (((*l_variable_courante).noeuds[(*s_etat_processus)
  271:                     .pointeurs_caracteres_variables[*ptr]] =
  272:                     malloc(sizeof(struct_arbre_variables))) == NULL)
  273:             {
  274:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  275:                 return(d_erreur);
  276:             }
  277: 
  278:             (*l_variable_courante).noeuds_utilises++;
  279: 
  280:             // La feuille est par défaut vide et aucun élément du tableau noeuds
  281:             // (les branches qui peuvent être issues de ce nouveau noeud)
  282:             // n'est encore utilisée.
  283: 
  284:             (*(*l_variable_courante).noeuds[(*s_etat_processus)
  285:                     .pointeurs_caracteres_variables[*ptr]]).feuille = NULL;
  286:             (*(*l_variable_courante).noeuds[(*s_etat_processus)
  287:                     .pointeurs_caracteres_variables[*ptr]]).noeuds_utilises = 0;
  288: 
  289:             // Le champ noeud_pere de la structure créée pointe sur
  290:             // la structure parente et l'indice tableau_pere correspond à la
  291:             // position réelle dans le tableau noeuds[] de la structure parente
  292:             // du noeud courant. Cette valeur sera utilisée lors de la
  293:             // destruction du noeud pour annuler le pointeur contenu dans
  294:             // le tableau noeuds[] de la structure parente.
  295: 
  296:             (*(*l_variable_courante).noeuds[(*s_etat_processus)
  297:                     .pointeurs_caracteres_variables[*ptr]]).noeud_pere =
  298:                     l_variable_courante;
  299:             (*(*l_variable_courante).noeuds[(*s_etat_processus)
  300:                     .pointeurs_caracteres_variables[*ptr]])
  301:                     .indice_tableau_pere = (*s_etat_processus)
  302:                     .pointeurs_caracteres_variables[*ptr];
  303: 
  304:             // Allocation du tableau noeuds[] et initialisation à zéro de
  305:             // tous les pointeurs.
  306: 
  307:             if (((*(*l_variable_courante).noeuds[(*s_etat_processus)
  308:                     .pointeurs_caracteres_variables[*ptr]]).noeuds =
  309:                     malloc((*s_etat_processus).nombre_caracteres_variables
  310:                     * sizeof(struct_arbre_variables))) == NULL)
  311:             {
  312:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  313:                 return(d_erreur);
  314:             }
  315: 
  316:             for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
  317:             {
  318:                 (*(*l_variable_courante).noeuds[(*s_etat_processus)
  319:                         .pointeurs_caracteres_variables[*ptr]]).noeuds[i]
  320:                         = NULL;
  321:             }
  322:         }
  323: 
  324:         l_variable_precedente = l_variable_courante;
  325:         l_variable_courante = (*l_variable_courante).noeuds
  326:                 [(*s_etat_processus).pointeurs_caracteres_variables[*ptr]];
  327:         ptr++;
  328:     }
  329: 
  330:     if ((*l_variable_courante).feuille == NULL)
  331:     {
  332:         // Aucune variable de même nom préexiste. On alloue le premier
  333:         // élément de la liste doublement chaînée contenant toutes les
  334:         // variables de même nom. Cette liste boucle en premier lieu sur
  335:         // elle-même.
  336: 
  337:         if (((*l_variable_courante).feuille = malloc(
  338:                 sizeof(struct_liste_variables))) == NULL)
  339:         {
  340:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  341:             return(d_erreur);
  342:         }
  343: 
  344:         (*(*l_variable_courante).feuille).suivant =
  345:                 (*l_variable_courante).feuille;
  346:         (*(*l_variable_courante).feuille).precedent =
  347:                 (*l_variable_courante).feuille;
  348:         (*(*l_variable_courante).feuille).noeud_pere = l_variable_precedente;
  349:         (*(*l_variable_courante).feuille).noeud = l_variable_courante;
  350: 
  351:         // Allocation de la variable sur l'élément de la liste.
  352: 
  353:         if (((*(*l_variable_courante).feuille).variable =
  354:                 malloc(sizeof(struct_variable))) == NULL)
  355:         { 
  356:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  357:             return(d_erreur);
  358:         }
  359: 
  360:         (*((struct_variable *) (*(*l_variable_courante).feuille).variable)) =
  361:                 (*s_variable);
  362:         pointeur_variable_cree = (*(*l_variable_courante).feuille).variable;
  363:     }
  364:     else
  365:     {
  366:         if ((l_nouvelle_variable = malloc(sizeof(struct_liste_variables)))
  367:                 == NULL)
  368:         {
  369:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  370:             return(d_erreur);
  371:         }
  372: 
  373:         if ((*s_variable).niveau > 1)
  374:         {
  375:             // Cas d'une variable locale
  376: 
  377:             // Si le niveau de la dernière variable de même nom est
  378:             // supérieur au niveau de la variable locale que l'on veut
  379:             // enregistrer dans la liste, cette liste est incohérente.
  380: 
  381:             BUG((*(*(*l_variable_courante).feuille).variable).niveau >=
  382:                     (*s_variable).niveau,
  383:                     printf("Variable=\"%s\"\n", (*s_variable).nom));
  384: 
  385:             // On ajoute la variable à la liste existante.
  386: 
  387:             (*l_nouvelle_variable).suivant = (*l_variable_courante).feuille;
  388:             (*l_nouvelle_variable).precedent = (*(*l_variable_courante).feuille)
  389:                     .precedent;
  390:             (*l_nouvelle_variable).noeud_pere = l_variable_precedente;
  391:             (*l_nouvelle_variable).noeud = l_variable_courante;
  392:             (*(*(*l_variable_courante).feuille).precedent).suivant =
  393:                     l_nouvelle_variable;
  394:             (*(*l_variable_courante).feuille).precedent =
  395:                     l_nouvelle_variable;
  396:             (*l_variable_courante).feuille = l_nouvelle_variable;
  397: 
  398:             if (((*(*l_variable_courante).feuille).variable =
  399:                     malloc(sizeof(struct_variable))) == NULL)
  400:             { 
  401:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  402:                 return(d_erreur);
  403:             }
  404: 
  405:             (*((struct_variable *) (*(*l_variable_courante).feuille).variable))
  406:                     = (*s_variable);
  407:             pointeur_variable_cree = (*(*l_variable_courante).feuille).variable;
  408:         }
  409:         else
  410:         {
  411:             // Cas d'une variable globale (niveau 0 [définitions] ou 1
  412:             // [variables globales])
  413: 
  414:             l_variable_candidate = (*l_variable_courante).feuille;
  415: 
  416:             do
  417:             {
  418:                 // S'il y a déjà une variable de même niveau, la pile
  419:                 // est incohérente.
  420: 
  421:                 BUG((*(*l_variable_candidate).variable).niveau ==
  422:                         (*s_variable).niveau,
  423:                         printf("Variable=\"%s\"\n", (*s_variable).nom));
  424: 
  425:                 l_variable_candidate = (*l_variable_candidate).precedent;
  426:             } while((l_variable_candidate != (*l_variable_courante).feuille) &&
  427:                     ((*(*l_variable_candidate).variable).niveau <= 1));
  428: 
  429:             if ((*(*(*(*l_variable_courante).feuille).precedent).variable)
  430:                     .niveau > 1)
  431:             {
  432:                 // Ajout inconditionnel des variables de niveaux 0 et 1
  433:             }
  434:             else
  435:             {
  436:                 l_variable_candidate = (*(*l_variable_courante).feuille)
  437:                         .precedent;
  438:             }
  439: 
  440:             (*l_nouvelle_variable).suivant = l_variable_candidate;
  441:             (*l_nouvelle_variable).precedent = (*l_variable_candidate)
  442:                     .precedent;
  443:             (*l_nouvelle_variable).noeud_pere = l_variable_precedente;
  444:             (*l_nouvelle_variable).noeud = l_variable_courante;
  445:             (*(*l_variable_candidate).precedent).suivant = l_nouvelle_variable;
  446:             (*l_variable_candidate).precedent = l_nouvelle_variable;
  447: 
  448:             if (((*l_nouvelle_variable).variable =
  449:                     malloc(sizeof(struct_variable))) == NULL)
  450:             { 
  451:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  452:                 return(d_erreur);
  453:             }
  454: 
  455:             (*(*l_nouvelle_variable).variable) = (*s_variable);
  456:             pointeur_variable_cree = (*l_nouvelle_variable).variable;
  457:         }
  458:     }
  459: 
  460:     // Ajout de la variable nouvellement créée à la liste par niveaux.
  461:     // Le pointeur contenu dans la structure de description du processus indique
  462:     // toujours le plus haut niveau utilisé.
  463: 
  464:     if ((*s_etat_processus).l_liste_variables_par_niveau == NULL)
  465:     {
  466:         // Le niveau courant n'existe pas. Il est créé.
  467: 
  468:         if ((l_nouvelle_variable = malloc(sizeof(struct_liste_variables)))
  469:                 == NULL)
  470:         {
  471:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  472:             return(d_erreur);
  473:         }
  474: 
  475:         (*l_nouvelle_variable).suivant = l_nouvelle_variable;
  476:         (*l_nouvelle_variable).precedent = l_nouvelle_variable;
  477:         (*l_nouvelle_variable).noeud_pere = NULL;
  478:         (*l_nouvelle_variable).liste = NULL;
  479: 
  480:         (*s_etat_processus).l_liste_variables_par_niveau = l_nouvelle_variable;
  481: 
  482:         // Ajout de la variable en tête de la liste
  483: 
  484:         if ((l_nouvel_element = malloc(sizeof(struct_liste_chainee))) == NULL)
  485:         {
  486:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  487:             return(d_erreur);
  488:         }
  489: 
  490:         (*l_nouvel_element).suivant = (*(*s_etat_processus)
  491:                 .l_liste_variables_par_niveau).liste;
  492:         (*l_nouvel_element).donnee = pointeur_variable_cree;
  493:         (*(*s_etat_processus).l_liste_variables_par_niveau).liste =
  494:                 l_nouvel_element;
  495:     }
  496:     else if ((*s_variable).niveau > (*((struct_variable *)
  497:             (*(*(*s_etat_processus).l_liste_variables_par_niveau).liste)
  498:             .donnee)).niveau)
  499:     {
  500:         // Le niveau courant n'existe pas. Il est créé.
  501: 
  502:         if ((l_nouvelle_variable = malloc(sizeof(struct_liste_variables)))
  503:                 == NULL)
  504:         {
  505:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  506:             return(d_erreur);
  507:         }
  508: 
  509:         (*l_nouvelle_variable).suivant = (*s_etat_processus)
  510:                 .l_liste_variables_par_niveau;
  511:         (*l_nouvelle_variable).precedent = (*(*s_etat_processus)
  512:                 .l_liste_variables_par_niveau).precedent;
  513:         (*l_nouvelle_variable).noeud_pere = NULL;
  514:         (*l_nouvelle_variable).liste = NULL;
  515:         (*(*(*s_etat_processus).l_liste_variables_par_niveau).precedent)
  516:                 .suivant = l_nouvelle_variable;
  517:         (*(*s_etat_processus).l_liste_variables_par_niveau)
  518:                 .precedent = l_nouvelle_variable;
  519: 
  520:         (*s_etat_processus).l_liste_variables_par_niveau = l_nouvelle_variable;
  521: 
  522:         // Ajout de la variable en tête de la liste
  523: 
  524:         if ((l_nouvel_element = malloc(sizeof(struct_liste_chainee))) == NULL)
  525:         {
  526:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  527:             return(d_erreur);
  528:         }
  529: 
  530:         (*l_nouvel_element).suivant = (*(*s_etat_processus)
  531:                 .l_liste_variables_par_niveau).liste;
  532:         (*l_nouvel_element).donnee = pointeur_variable_cree;
  533:         (*(*s_etat_processus).l_liste_variables_par_niveau).liste =
  534:                 l_nouvel_element;
  535:     }
  536:     else if ((*s_variable).niveau <= 1)
  537:     {
  538:         // Création d'une variable de niveau 0 ou 1. Il convient de
  539:         // chercher dans la liste si un niveau 0 ou 1 préexiste. Pour cela, on
  540:         // regarde la position courante et les deux précédentes.
  541: 
  542:         l_variable_candidate = (*s_etat_processus).l_liste_variables_par_niveau;
  543:         niveau_acceptable = d_faux;
  544: 
  545:         for(i = 0; i <= 2; i++)
  546:         {
  547:             if ((*l_variable_candidate).liste == NULL)
  548:             {
  549:                 continue;
  550:             }
  551: 
  552:             if ((*((struct_variable *) (*(*l_variable_candidate)
  553:                     .liste).donnee)).niveau == (*s_variable).niveau)
  554:             {
  555:                 niveau_acceptable = d_vrai;
  556:                 break;
  557:             }
  558: 
  559:             l_variable_candidate = (*l_variable_candidate).precedent;
  560:         }
  561: 
  562:         if (niveau_acceptable == d_faux)
  563:         {
  564:             if ((l_nouvelle_variable = malloc(sizeof(struct_liste_variables)))
  565:                     == NULL)
  566:             {
  567:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  568:                 return(d_erreur);
  569:             }
  570: 
  571:             l_variable_candidate =
  572:                     (*(*s_etat_processus).l_liste_variables_par_niveau)
  573:                     .precedent;
  574: 
  575:             // On ne peut créer qu'une variable de niveau supérieur ou égal à
  576:             // 1 lors de l'exécution normale d'un programme. Les variables
  577:             // de niveau 0 sont créées à l'initialisation et relèvent du
  578:             // cas précédent car il n'existe lors de leur création aucun
  579:             // niveau non nul.
  580: 
  581:             BUG((*s_variable).niveau == 0,
  582:                     uprintf("Attempt to create a level-0 variable!\n"));
  583: 
  584:             (*l_nouvelle_variable).suivant = l_variable_candidate;
  585:             (*l_nouvelle_variable).precedent = (*l_variable_candidate)
  586:                     .precedent;
  587:             (*l_nouvelle_variable).noeud_pere = NULL;
  588:             (*l_nouvelle_variable).liste = NULL;
  589:             (*(*l_variable_candidate).precedent).suivant = l_nouvelle_variable;
  590:             (*l_variable_candidate).precedent = l_nouvelle_variable;
  591: 
  592:             l_variable_candidate = l_nouvelle_variable;
  593:         }
  594: 
  595:         // Ajout de la variable en tête de la liste l_variable_candidate.
  596: 
  597:         if ((l_nouvel_element = malloc(sizeof(struct_liste_chainee))) == NULL)
  598:         {
  599:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  600:             return(d_erreur);
  601:         }
  602: 
  603:         (*l_nouvel_element).suivant = (*l_variable_candidate).liste;
  604:         (*l_nouvel_element).donnee = pointeur_variable_cree;
  605:         (*l_variable_candidate).liste = l_nouvel_element;
  606:     }
  607:     else
  608:     {
  609:         // Ajout de la variable en tête de la liste
  610: 
  611:         if ((l_nouvel_element = malloc(sizeof(struct_liste_chainee))) == NULL)
  612:         {
  613:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  614:             return(d_erreur);
  615:         }
  616: 
  617:         (*l_nouvel_element).suivant = (*(*s_etat_processus)
  618:                 .l_liste_variables_par_niveau).liste;
  619:         (*l_nouvel_element).donnee = pointeur_variable_cree;
  620:         (*(*s_etat_processus).l_liste_variables_par_niveau).liste =
  621:                 l_nouvel_element;
  622:     }
  623: 
  624:     return(d_absence_erreur);
  625: }
  626: 
  627: 
  628: logical1
  629: creation_variable(struct_processus *s_etat_processus,
  630:         struct_variable *s_variable,
  631:         unsigned char autorisation_creation_variable_statique,
  632:         unsigned char autorisation_creation_variable_partagee)
  633: {
  634:     if ((*s_etat_processus).mode_execution_programme == 'Y')
  635:     {
  636:         (*s_variable).origine = 'P';
  637:     }
  638:     else
  639:     {
  640:         (*s_variable).origine = 'E';
  641:     }
  642: 
  643:     if ((*s_variable).niveau == 0)
  644:     {
  645:         // Un point d'entrée de définition est verrouillé.
  646: 
  647:         if ((*s_variable).origine == 'P')
  648:         {
  649:             (*s_variable).variable_statique.adresse = 0;
  650:             (*s_variable).variable_partagee.adresse = 0;
  651:         }
  652:         else
  653:         {
  654:             (*s_variable).variable_statique.pointeur = NULL;
  655:             (*s_variable).variable_partagee.pointeur = NULL;
  656:         }
  657: 
  658:         (*s_variable).variable_verrouillee = d_vrai;
  659:     }
  660:     else if ((*s_variable).niveau == 1)
  661:     {
  662:         // Une variable globale ne peut être statique.
  663: 
  664:         if ((*s_variable).origine == 'P')
  665:         {
  666:             (*s_variable).variable_statique.adresse = 0;
  667:             (*s_variable).variable_partagee.adresse = 0;
  668:         }
  669:         else
  670:         {
  671:             (*s_variable).variable_statique.pointeur = NULL;
  672:             (*s_variable).variable_partagee.pointeur = NULL;
  673:         }
  674: 
  675:         (*s_variable).variable_verrouillee = d_faux;
  676:     }
  677:     else
  678:     {
  679:         // 0 -> variable volatile
  680:         // adresse de création -> variable statique
  681: 
  682:         if (autorisation_creation_variable_statique == 'V')
  683:         {
  684:             if (autorisation_creation_variable_partagee == 'S')
  685:             {
  686:                 // On force la création d'une variable partagée
  687: 
  688:                 if ((*s_variable).origine == 'P')
  689:                 {
  690:                     (*s_variable).variable_statique.adresse = 0;
  691:                     (*s_variable).variable_partagee.adresse =
  692:                             (*s_etat_processus).position_courante;
  693:                 }
  694:                 else
  695:                 {
  696:                     (*s_variable).variable_statique.pointeur = NULL;
  697:                     (*s_variable).variable_partagee.pointeur =
  698:                             (*s_etat_processus).objet_courant;
  699:                 }
  700:             }
  701:             else
  702:             {
  703:                 // On force la création d'une variable volatile
  704: 
  705:                 if ((*s_variable).origine == 'P')
  706:                 {
  707:                     (*s_variable).variable_statique.adresse = 0;
  708:                     (*s_variable).variable_partagee.adresse = 0;
  709:                 }
  710:                 else
  711:                 {
  712:                     (*s_variable).variable_statique.pointeur = NULL;
  713:                     (*s_variable).variable_partagee.pointeur = NULL;
  714:                 }
  715:             }
  716:         }
  717:         else
  718:         {
  719:             // On force la création d'une variable statique.
  720: 
  721:             if ((*s_variable).origine == 'P')
  722:             {
  723:                 (*s_variable).variable_statique.adresse =
  724:                         (*s_etat_processus).position_courante;
  725:                 (*s_variable).variable_partagee.adresse = 0;
  726:             }
  727:             else
  728:             {
  729:                 (*s_variable).variable_statique.pointeur =
  730:                         (*s_etat_processus).objet_courant;
  731:                 (*s_variable).variable_partagee.pointeur = 0;
  732:             }
  733:         }
  734: 
  735:         (*s_variable).variable_verrouillee = d_faux;
  736:     }
  737: 
  738:     /*
  739:      * Recherche de la feuille correspondante dans l'arbre des variables.
  740:      * Si cette feuille n'existe pas, elle est créée.
  741:      */
  742: 
  743:     if (ajout_variable(s_etat_processus, s_variable) == d_erreur)
  744:     {
  745:         return(d_erreur);
  746:     }
  747: 
  748:     return(d_absence_erreur);
  749: }
  750: 
  751: 
  752: /*
  753: ================================================================================
  754:   Procédure de recherche d'une variable par son nom dans la base
  755: ================================================================================
  756:   Entrée :
  757: --------------------------------------------------------------------------------
  758:   Sortie :
  759: --------------------------------------------------------------------------------
  760:   Effets de bord : néant
  761: ================================================================================
  762: */
  763: 
  764: logical1
  765: recherche_variable(struct_processus *s_etat_processus,
  766:         unsigned char *nom_variable)
  767: {
  768:     int                         pointeur;
  769: 
  770:     struct_arbre_variables      *l_variable_courante;
  771:     struct_liste_pile_systeme   *l_element_courant;
  772: 
  773:     unsigned char               *ptr;
  774: 
  775:     unsigned long               niveau_appel;
  776: 
  777:     if ((*s_etat_processus).s_arbre_variables == NULL)
  778:     {
  779:         (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
  780:         return(d_faux);
  781:     }
  782: 
  783:     l_variable_courante = (*s_etat_processus).s_arbre_variables;
  784:     ptr = nom_variable;
  785: 
  786:     while((*ptr) != d_code_fin_chaine)
  787:     {
  788:         pointeur = (*s_etat_processus).pointeurs_caracteres_variables[*ptr];
  789: 
  790:         if (pointeur < 0)
  791:         {
  792:             // Caractère hors de l'alphabet des variables
  793: 
  794:             (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
  795:             return(d_faux);
  796:         }
  797: 
  798:         if ((*l_variable_courante).noeuds[pointeur] == NULL)
  799:         {
  800:             // Le chemin de la variable candidate n'existe pas.
  801:             (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
  802:             return(d_faux);
  803:         }
  804: 
  805:         l_variable_courante = (*l_variable_courante).noeuds[pointeur];
  806:         ptr++;
  807:     }
  808: 
  809:     if ((*l_variable_courante).feuille != NULL)
  810:     {
  811:         // Il existe une pile de variables de même nom. Le sommet de la
  812:         // pile est la variable de niveau le plus haut.
  813: 
  814:         l_element_courant = (*s_etat_processus).l_base_pile_systeme;
  815: 
  816:         if (l_element_courant == NULL)
  817:         {
  818:             // Problème : la pile système est vide !
  819:             (*s_etat_processus).erreur_systeme = d_es_pile_vide;
  820:             return(d_faux);
  821:         }
  822: 
  823:         while((*l_element_courant).retour_definition != 'Y')
  824:         {
  825:             l_element_courant = (*l_element_courant).suivant;
  826: 
  827:             if (l_element_courant == NULL)
  828:             {
  829:                 (*s_etat_processus).erreur_systeme = d_es_pile_vide;
  830:                 return(d_faux);
  831:             }
  832:         }
  833: 
  834:         niveau_appel = (*l_element_courant).niveau_courant;
  835: 
  836:         if (niveau_appel < (*(*(*l_variable_courante).feuille).variable).niveau)
  837:         {
  838:             // Une variable locale est accessible puisque créée dans la
  839:             // fonction courante.
  840: 
  841:             (*s_etat_processus).pointeur_variable_courante =
  842:                     (*(*l_variable_courante).feuille).variable;
  843:             (*s_etat_processus).pointeur_feuille_courante =
  844:                     (*l_variable_courante).feuille;
  845:             return(d_vrai);
  846:         }
  847:         else
  848:         {
  849:             // Aucune variable locale n'est accessible depuis la fonction.
  850:             // Dans ce cas, on prend la variable de niveau le plus bas
  851:             // si ce niveau est inférieur ou égal à 1 (variable globale
  852:             // ou fonction définie par l'utilisateur). Si le niveau de la
  853:             // plus ancienne variable est strictement supérieur à 1, il
  854:             // s'agit d'une variable locale inaccessible.
  855: 
  856:             if ((*(*(*(*l_variable_courante).feuille).precedent).variable)
  857:                     .niveau <= 1)
  858:             {
  859:                 (*s_etat_processus).pointeur_variable_courante =
  860:                         (*(*(*l_variable_courante).feuille).precedent).variable;
  861:                 (*s_etat_processus).pointeur_feuille_courante =
  862:                         (*(*l_variable_courante).feuille).precedent;
  863: 
  864:                 // S'il existe une variable de niveau 0 et une seconde de
  865:                 // niveau 1, la variable de niveau 0 (fonction) est masquée
  866:                 // par celle de niveau 1.
  867: 
  868:                 if (((*(*(*(*l_variable_courante).feuille).precedent)
  869:                         .variable).niveau == 0) && ((*(*(*(*
  870:                         (*l_variable_courante).feuille).precedent).precedent)
  871:                         .variable).niveau == 1))
  872:                 {
  873:                     (*s_etat_processus).pointeur_variable_courante =
  874:                             (*(*(*(*l_variable_courante).feuille).precedent)
  875:                             .precedent).variable;
  876:                     (*s_etat_processus).pointeur_feuille_courante =
  877:                             (*(*(*l_variable_courante).feuille).precedent)
  878:                             .precedent;
  879:                 }
  880: 
  881:                 return(d_vrai);
  882:             }
  883:         }
  884:     }
  885: 
  886:     (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
  887:     return(d_faux);
  888: }
  889: 
  890: 
  891: logical1
  892: recherche_variable_globale(struct_processus *s_etat_processus,
  893:         unsigned char *nom)
  894: {
  895:     logical1            presence_variable;
  896: 
  897:     presence_variable = recherche_variable(s_etat_processus, nom);
  898: 
  899:     if (presence_variable == d_vrai)
  900:     {
  901:         switch((*(*s_etat_processus).pointeur_variable_courante).niveau)
  902:         {
  903:             case 0:
  904:             {
  905:                 // La variable est une définition.
  906:                 presence_variable = d_faux;
  907:                 break;
  908:             }
  909: 
  910:             case 1:
  911:             {
  912:                 break;
  913:             }
  914: 
  915:             default:
  916:             {
  917:                 if ((*(*(*(*s_etat_processus).pointeur_feuille_courante)
  918:                         .precedent).variable).niveau == 1)
  919:                 {
  920:                     (*s_etat_processus).pointeur_feuille_courante =
  921:                             (*(*s_etat_processus).pointeur_feuille_courante)
  922:                             .precedent;
  923:                     (*s_etat_processus).pointeur_variable_courante =
  924:                             (*(*s_etat_processus).pointeur_feuille_courante)
  925:                             .variable;
  926:                 }
  927:                 else if ((*(*(*(*(*s_etat_processus).pointeur_feuille_courante)
  928:                         .precedent).precedent).variable).niveau == 1)
  929:                 {
  930:                     (*s_etat_processus).pointeur_feuille_courante =
  931:                             (*(*(*s_etat_processus).pointeur_feuille_courante)
  932:                             .precedent).precedent;
  933:                     (*s_etat_processus).pointeur_variable_courante =
  934:                             (*(*s_etat_processus).pointeur_feuille_courante)
  935:                             .variable;
  936:                 }
  937:                 else
  938:                 {
  939:                     presence_variable = d_faux;
  940:                 }
  941: 
  942:                 break;
  943:             }
  944:         }
  945:     }
  946: 
  947:     if (presence_variable == d_vrai)
  948:     {
  949:         if ((*(*s_etat_processus).pointeur_variable_courante).objet == NULL)
  950:         {
  951:             // La variable n'est pas globale, elle est partagée.
  952:             presence_variable = d_faux;
  953:             (*s_etat_processus).erreur_execution = d_ex_variable_partagee;
  954:         }
  955:     }
  956: 
  957:     return(presence_variable);
  958: }
  959: 
  960: 
  961: /*
  962: ================================================================================
  963:   Procédure de retrait d'une variable de la base
  964: ================================================================================
  965:   Entrée : type 'G' ou 'L' selon que l'on retire une variable locale (incluant
  966:            les globales) ou strictement globale.
  967: --------------------------------------------------------------------------------
  968:   Sortie :
  969: --------------------------------------------------------------------------------
  970:   Effets de bord : néant
  971: ================================================================================
  972: */
  973: 
  974: logical1
  975: retrait_variable(struct_processus *s_etat_processus,
  976:         unsigned char *nom_variable, unsigned char type)
  977: {
  978:     logical1                    erreur;
  979: 
  980:     struct_arbre_variables      *s_arbre_a_supprimer;
  981:     struct_arbre_variables      *s_arbre_courant;
  982:     struct_arbre_variables      *noeud_courant;
  983: 
  984:     struct_liste_chainee        *l_element_courant;
  985:     struct_liste_chainee        *l_element_precedent;
  986: 
  987:     struct_liste_variables      *variable_a_supprimer;
  988:     struct_liste_variables      *variables_par_niveau;
  989: 
  990:     unsigned long               niveau;
  991: 
  992:     if (recherche_variable(s_etat_processus, nom_variable) == d_vrai)
  993:     {
  994:         // Une variable correspondant au nom recherché est accessible.
  995: 
  996:         if (type == 'G')
  997:         {
  998:             if ((*(*s_etat_processus).pointeur_variable_courante).niveau > 1)
  999:             {
 1000:                 // La variable obtenue est une variable locale. il faut
 1001:                 // s'assurer qu'il existe une variable de niveau 1 de même
 1002:                 // nom sur la feuille.
 1003: 
 1004:                 if ((*(*(*(*s_etat_processus).pointeur_feuille_courante)
 1005:                         .precedent).variable).niveau <= 1)
 1006:                 {
 1007:                     (*s_etat_processus).pointeur_feuille_courante =
 1008:                             (*(*s_etat_processus).pointeur_feuille_courante)
 1009:                             .precedent;
 1010:                     (*s_etat_processus).pointeur_variable_courante =
 1011:                             (*(*s_etat_processus).pointeur_feuille_courante)
 1012:                             .variable;
 1013: 
 1014:                     // Si la variable retournée est de niveau 0, on regarde
 1015:                     // un peu plus loin si une variable de niveau 1 existe.
 1016: 
 1017:                     if (((*(*(*s_etat_processus).pointeur_feuille_courante)
 1018:                             .variable).niveau == 0) &&
 1019:                             ((*(*(*(*s_etat_processus)
 1020:                             .pointeur_feuille_courante).precedent).variable)
 1021:                             .niveau == 1))
 1022:                     {
 1023:                         (*s_etat_processus).pointeur_feuille_courante =
 1024:                                 (*(*s_etat_processus).pointeur_feuille_courante)
 1025:                                 .precedent;
 1026:                         (*s_etat_processus).pointeur_variable_courante =
 1027:                                 (*(*s_etat_processus).pointeur_feuille_courante)
 1028:                                 .variable;
 1029:                     }
 1030:                 }
 1031:                 else
 1032:                 {
 1033:                     // Aucune variable globale (niveau 1) n'existe.
 1034: 
 1035:                     erreur = d_erreur;
 1036:                     (*s_etat_processus).erreur_execution =
 1037:                             d_ex_variable_non_definie;
 1038:                     return(erreur);
 1039:                 }
 1040:             }
 1041: 
 1042:             if ((*(*s_etat_processus).pointeur_variable_courante)
 1043:                     .variable_verrouillee == d_vrai)
 1044:             {
 1045:                 erreur = d_erreur;
 1046:                 (*s_etat_processus).erreur_execution =
 1047:                         d_ex_variable_verrouillee;
 1048:                 return(erreur);
 1049:             }
 1050:         }
 1051: 
 1052:         // Suppression de la variable de la liste.
 1053:         // Deux cas peuvent survenir :
 1054:         // 1/ les pointeurs sur la variable et la variable suivante
 1055:         // sont identiques et on supprime la variable ainsi que la feuille
 1056:         // associée ;
 1057:         // 2/ ces deux pointeurs sont différents et se contente de retirer
 1058:         // la structure décrivant la variable.
 1059: 
 1060:         if ((*s_etat_processus).pointeur_feuille_courante ==
 1061:                 (*(*s_etat_processus).pointeur_feuille_courante).suivant)
 1062:         {
 1063:             // Cas 1 :
 1064:             // On retire la variable du noeud en décrémentant le nombre
 1065:             // de feuilles de ce noeud. Si le nombre de feuilles du noeud
 1066:             // est nul, on retire les noeuds récursivement jusqu'à obtenir
 1067:             // un nombre non nul de feuilles utilisées (ou la racine des
 1068:             // variables).
 1069: 
 1070:             variable_a_supprimer = (*s_etat_processus)
 1071:                     .pointeur_feuille_courante;
 1072:             s_arbre_courant = (*variable_a_supprimer).noeud_pere;
 1073:             noeud_courant = (*variable_a_supprimer).noeud;
 1074:             (*s_arbre_courant).noeuds[(*noeud_courant).indice_tableau_pere]
 1075:                     = NULL;
 1076: 
 1077:             BUG((*s_arbre_courant).noeuds_utilises == 0,
 1078:                     uprintf("Freed node !\n"));
 1079:             (*s_arbre_courant).noeuds_utilises--;
 1080: 
 1081:             while((*s_arbre_courant).noeuds_utilises == 0)
 1082:             {
 1083:                 s_arbre_a_supprimer = s_arbre_courant;
 1084:                 s_arbre_courant = (*s_arbre_courant).noeud_pere;
 1085: 
 1086:                 if (s_arbre_courant == NULL)
 1087:                 {
 1088:                     free((*s_arbre_a_supprimer).noeuds);
 1089:                     free(s_arbre_a_supprimer);
 1090:                     break;
 1091:                 }
 1092: 
 1093:                 // s_arbre_a_supprimer contient la structure de feuille qui
 1094:                 // vient d'être libérée. Il s'agit maintenant
 1095:                 // d'annuler le pointeur dans le tableau noeuds de la structure
 1096:                 // pointée par noeud_pere, soit s_arbre_courant.
 1097: 
 1098:                 BUG((*s_arbre_a_supprimer).indice_tableau_pere < 0,
 1099:                         uprintf("Invalid pointer !\n"));
 1100:                 (*s_arbre_courant).noeuds[(*s_arbre_a_supprimer)
 1101:                         .indice_tableau_pere] = NULL;
 1102: 
 1103:                 free((*s_arbre_a_supprimer).noeuds);
 1104:                 free(s_arbre_a_supprimer);
 1105: 
 1106:                 BUG((*s_arbre_courant).noeuds_utilises == 0,
 1107:                         uprintf("Freed node !\n"));
 1108:                 (*s_arbre_courant).noeuds_utilises--;
 1109:             }
 1110:         }
 1111:         else
 1112:         {
 1113:             // Cas 2 :
 1114:             // On retire la variable de la liste.
 1115: 
 1116:             variable_a_supprimer = (*s_etat_processus)
 1117:                     .pointeur_feuille_courante;
 1118: 
 1119:             (*(*(*s_etat_processus).pointeur_feuille_courante).precedent)
 1120:                     .suivant = (*(*s_etat_processus).pointeur_feuille_courante)
 1121:                     .suivant;
 1122:             (*(*(*s_etat_processus).pointeur_feuille_courante).suivant)
 1123:                     .precedent = (*(*s_etat_processus)
 1124:                     .pointeur_feuille_courante).precedent;
 1125: 
 1126:             // Mise à jour du pointeur dans l'arbre des variables. Cette
 1127:             // mise à jour n'est nécessaire que dans le cas où la variable
 1128:             // supprimée est en tête de la liste.
 1129: 
 1130:             if (variable_a_supprimer == (*((*(*variable_a_supprimer).noeud_pere)
 1131:                     .noeuds[(*(*variable_a_supprimer).noeud)
 1132:                     .indice_tableau_pere])).feuille)
 1133:             {
 1134:                 (*((*(*variable_a_supprimer).noeud_pere).noeuds
 1135:                         [(*(*variable_a_supprimer).noeud).indice_tableau_pere]))
 1136:                         .feuille = (*(*((*(*variable_a_supprimer).noeud_pere)
 1137:                         .noeuds[(*(*variable_a_supprimer).noeud)
 1138:                         .indice_tableau_pere])).feuille).suivant;
 1139:             }
 1140: 
 1141:             (*s_etat_processus).pointeur_feuille_courante =
 1142:                     (*(*s_etat_processus).pointeur_feuille_courante).suivant;
 1143:             (*s_etat_processus).pointeur_variable_courante =
 1144:                     (*(*s_etat_processus).pointeur_feuille_courante).variable;
 1145: 
 1146:             noeud_courant = NULL;
 1147:         }
 1148: 
 1149:         // Dans tous les cas, on retire la variable de la liste des variables
 1150:         // par niveau.
 1151: 
 1152:         niveau = (*(*variable_a_supprimer).variable).niveau;
 1153:         variables_par_niveau = (*s_etat_processus).l_liste_variables_par_niveau;
 1154: 
 1155:         if (variables_par_niveau != NULL)
 1156:         {
 1157:             do
 1158:             {
 1159:                 l_element_courant = (*variables_par_niveau).liste;
 1160: 
 1161:                 if (l_element_courant != NULL)
 1162:                 {
 1163:                     if ((*((struct_variable *) (*l_element_courant).donnee))
 1164:                             .niveau == niveau)
 1165:                     {
 1166:                         // On parcourt le bon niveau.
 1167: 
 1168:                         l_element_precedent = NULL;
 1169: 
 1170:                         while(l_element_courant != NULL)
 1171:                         {
 1172:                             // Tant que l_element_courant est non nul, il reste
 1173:                             // des variables à explorer dans le niveau courant.
 1174: 
 1175:                             if ((*l_element_courant).donnee ==
 1176:                                     (void *) (*variable_a_supprimer).variable)
 1177:                             {
 1178:                                 // On a trouvé la variable à supprimer.
 1179: 
 1180:                                 if (l_element_precedent == NULL)
 1181:                                 {
 1182:                                     (*variables_par_niveau).liste =
 1183:                                             (*l_element_courant).suivant;
 1184:                                 }
 1185:                                 else
 1186:                                 {
 1187:                                     (*l_element_precedent).suivant =
 1188:                                             (*l_element_courant).suivant;
 1189:                                 }
 1190: 
 1191:                                 free(l_element_courant);
 1192:                                 break;
 1193:                             }
 1194: 
 1195:                             l_element_precedent = l_element_courant;
 1196:                             l_element_courant = (*l_element_courant).suivant;
 1197:                         }
 1198:                     }
 1199:                 }
 1200: 
 1201:                 variables_par_niveau = (*variables_par_niveau).suivant;
 1202: 
 1203:             } while(variables_par_niveau != (*s_etat_processus)
 1204:                     .l_liste_variables_par_niveau);
 1205:         }
 1206: 
 1207:         // Puis on libère le contenu de la variable.
 1208: 
 1209:         free((*(*variable_a_supprimer).variable).nom);
 1210:         liberation(s_etat_processus, (*(*variable_a_supprimer).variable).objet);
 1211:         free((*variable_a_supprimer).variable);
 1212:         free(variable_a_supprimer);
 1213: 
 1214:         erreur = d_absence_erreur;
 1215: 
 1216:         if (noeud_courant != NULL)
 1217:         {
 1218:             free((*noeud_courant).noeuds);
 1219:             free(noeud_courant);
 1220:         }
 1221:     }
 1222:     else
 1223:     {
 1224:         // Aucune variable n'est accessible depuis le point courant du
 1225:         // programme.
 1226: 
 1227:         erreur = d_erreur;
 1228:         (*s_etat_processus).erreur_systeme = d_es_variable_introuvable;
 1229:     }
 1230: 
 1231:     return(erreur);
 1232: }
 1233: 
 1234: 
 1235: /*
 1236: ================================================================================
 1237:   Procédure de retrait des variables de niveau strictement supérieur au
 1238:   niveau courant
 1239: ================================================================================
 1240:   Entrée :
 1241: --------------------------------------------------------------------------------
 1242:   Sortie :
 1243: --------------------------------------------------------------------------------
 1244:   Effets de bord : néant
 1245: ================================================================================
 1246: */
 1247: 
 1248: logical1
 1249: retrait_variable_par_niveau(struct_processus *s_etat_processus)
 1250: {
 1251:     struct_liste_variables          *l_element_a_supprimer;
 1252: 
 1253:     // Utilisation du champ (*s_etat_processus).liste_variables_par_niveau.
 1254:     // La tête de la pile contient toujours les variables de plus haut niveau
 1255:     // créées.
 1256: 
 1257:     while((*s_etat_processus).l_liste_variables_par_niveau != NULL)
 1258:     {
 1259:         if ((*(*s_etat_processus).l_liste_variables_par_niveau).liste == NULL)
 1260:         {
 1261:             // Si le niveau ne contient aucune variable, on le détruit.
 1262:             // Le pointeur sur la chaîne est déjà nul et il ne reste rien à
 1263:             // faire.
 1264:         }
 1265:         else
 1266:         {
 1267:             // Le niveau contient des variables.
 1268: 
 1269:             if ((*((struct_variable *) (*(*(*s_etat_processus)
 1270:                     .l_liste_variables_par_niveau).liste).donnee)).niveau
 1271:                     <= (*s_etat_processus).niveau_courant)
 1272:             {
 1273:                 // On a retiré de l'arbre des variables toutes les
 1274:                 // variables de niveau strictement supérieur au niveau
 1275:                 // courant.
 1276: 
 1277:                 break;
 1278:             }
 1279: 
 1280:             while((*(*s_etat_processus).l_liste_variables_par_niveau).liste
 1281:                     != NULL)
 1282:             {
 1283:                 // Sauvegarde des variables statiques.
 1284: 
 1285:                 if ((*((struct_variable *) (*(*(*s_etat_processus)
 1286:                         .l_liste_variables_par_niveau).liste).donnee)).origine
 1287:                         == 'P')
 1288:                 {
 1289:                     if ((*((struct_variable *) (*(*(*s_etat_processus)
 1290:                             .l_liste_variables_par_niveau).liste).donnee))
 1291:                             .variable_statique.adresse != 0)
 1292:                     {
 1293:                         if (recherche_variable_statique(s_etat_processus,
 1294:                                 (*((struct_variable *) (*(*(*s_etat_processus)
 1295:                                 .l_liste_variables_par_niveau).liste).donnee))
 1296:                                 .nom, (*((struct_variable *)
 1297:                                 (*(*(*s_etat_processus)
 1298:                                 .l_liste_variables_par_niveau).liste).donnee))
 1299:                                 .variable_statique, ((*s_etat_processus)
 1300:                                 .mode_execution_programme
 1301:                                  == 'Y') ? 'P' : 'E') == d_vrai)
 1302:                         {
 1303:                             (*s_etat_processus).s_liste_variables_statiques
 1304:                                     [(*s_etat_processus)
 1305:                                     .position_variable_statique_courante]
 1306:                                     .objet = (*((struct_variable *)
 1307:                                     (*(*(*s_etat_processus)
 1308:                                     .l_liste_variables_par_niveau).liste)
 1309:                                     .donnee)).objet;
 1310:                         }
 1311:                         else
 1312:                         {
 1313:                             (*s_etat_processus).erreur_systeme =
 1314:                                     d_es_variable_introuvable;
 1315:                         }
 1316: 
 1317:                         (*((struct_variable *) (*(*(*s_etat_processus)
 1318:                                 .l_liste_variables_par_niveau).liste).donnee))
 1319:                                 .objet = NULL;
 1320:                     }
 1321:                 }
 1322:                 else
 1323:                 {
 1324:                     if ((*((struct_variable *) (*(*(*s_etat_processus)
 1325:                             .l_liste_variables_par_niveau).liste).donnee))
 1326:                             .variable_statique.pointeur != NULL)
 1327:                     {
 1328:                         /*
 1329:                          * Gestion des variables statiques
 1330:                          */
 1331: 
 1332:                         if (recherche_variable_statique(s_etat_processus,
 1333:                                 (*((struct_variable *) (*(*(*s_etat_processus)
 1334:                                 .l_liste_variables_par_niveau).liste).donnee))
 1335:                                 .nom, (*((struct_variable *)
 1336:                                 (*(*(*s_etat_processus)
 1337:                                 .l_liste_variables_par_niveau).liste).donnee))
 1338:                                 .variable_statique, ((*s_etat_processus)
 1339:                                 .mode_execution_programme
 1340:                                  == 'Y') ? 'P' : 'E') == d_vrai)
 1341:                         {
 1342:                             (*s_etat_processus).s_liste_variables_statiques
 1343:                                     [(*s_etat_processus)
 1344:                                     .position_variable_statique_courante]
 1345:                                     .objet = (*((struct_variable *)
 1346:                                     (*(*(*s_etat_processus)
 1347:                                     .l_liste_variables_par_niveau).liste)
 1348:                                     .donnee)).objet;
 1349:                         }
 1350:                         else
 1351:                         {
 1352:                             (*s_etat_processus).erreur_systeme =
 1353:                                     d_es_variable_introuvable;
 1354:                             return(d_erreur);
 1355:                         }
 1356: 
 1357:                         (*((struct_variable *) (*(*(*s_etat_processus)
 1358:                                 .l_liste_variables_par_niveau).liste).donnee))
 1359:                                 .objet = NULL;
 1360:                     }
 1361:                 }
 1362: 
 1363:                 if (retrait_variable(s_etat_processus,
 1364:                         (*((struct_variable *) (*(*(*s_etat_processus)
 1365:                         .l_liste_variables_par_niveau).liste).donnee)).nom,
 1366:                         'L') == d_erreur)
 1367:                 {
 1368:                     return(d_erreur);
 1369:                 }
 1370:             }
 1371:         }
 1372: 
 1373:         // On retire l'élément de la liste doublement chaînée et circulaire.
 1374: 
 1375:         (*(*(*s_etat_processus).l_liste_variables_par_niveau).precedent).suivant
 1376:                 = (*(*s_etat_processus).l_liste_variables_par_niveau).suivant;
 1377:         (*(*(*s_etat_processus).l_liste_variables_par_niveau).suivant).precedent
 1378:                 = (*(*s_etat_processus).l_liste_variables_par_niveau).precedent;
 1379: 
 1380:         l_element_a_supprimer = (*s_etat_processus)
 1381:                 .l_liste_variables_par_niveau;
 1382:         (*s_etat_processus).l_liste_variables_par_niveau =
 1383:                 (*l_element_a_supprimer).suivant;
 1384:         free(l_element_a_supprimer);
 1385:     }
 1386: 
 1387:     return(d_absence_erreur);
 1388: }
 1389: 
 1390: 
 1391: /*
 1392: ================================================================================
 1393:   Procédure de retrait des toutes les variables locales et globales
 1394: ================================================================================
 1395:   Entrée : drapeau indiquant s'il faut retirer les définitions (variables
 1396:            de niveau 0)
 1397: --------------------------------------------------------------------------------
 1398:   Sortie :
 1399: --------------------------------------------------------------------------------
 1400:   Effets de bord : néant
 1401: ================================================================================
 1402: */
 1403: 
 1404: void
 1405: liberation_arbre_variables(struct_processus *s_etat_processus,
 1406:         struct_arbre_variables *arbre, logical1 retrait_definitions)
 1407: {
 1408:     int                     i;
 1409: 
 1410:     struct_liste_chainee    *l_element_courant_liste;
 1411:     struct_liste_chainee    *l_element_suivant_liste;
 1412: 
 1413:     struct_liste_variables  *l_element_courant;
 1414:     struct_liste_variables  *l_element_suivant;
 1415: 
 1416:     // Libération de l'arbre des variables. Le contenu des variables n'est
 1417:     // pas détruit par cette opération, il sera détruit lors de la libération
 1418:     // de la liste des variables par niveau.
 1419: 
 1420:     l_element_courant = (*arbre).feuille;
 1421: 
 1422:     if (l_element_courant != NULL)
 1423:     {
 1424:         do
 1425:         {
 1426:             l_element_suivant = (*l_element_courant).suivant;
 1427:             free(l_element_courant);
 1428:             l_element_courant = l_element_suivant;
 1429:         } while(l_element_courant != (*arbre).feuille);
 1430:     }
 1431: 
 1432:     for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
 1433:     {
 1434:         if ((*arbre).noeuds[i] != NULL)
 1435:         {
 1436:             liberation_arbre_variables(s_etat_processus, (*arbre).noeuds[i],
 1437:                     retrait_definitions);
 1438:         }
 1439:     }
 1440: 
 1441:     // Suppression de la liste des variables par niveau.
 1442: 
 1443:     if (arbre == (*s_etat_processus).s_arbre_variables)
 1444:     {
 1445:         l_element_courant = (*s_etat_processus).l_liste_variables_par_niveau;
 1446: 
 1447:         if (l_element_courant != NULL)
 1448:         {
 1449:             do
 1450:             {
 1451:                 l_element_courant_liste = (*l_element_courant).liste;
 1452: 
 1453:                 while(l_element_courant_liste != NULL)
 1454:                 {
 1455:                     if ((retrait_definitions == d_vrai) ||
 1456:                             ((*((struct_variable *) (*l_element_courant_liste)
 1457:                             .donnee)).niveau >= 1))
 1458:                     {
 1459:                         liberation(s_etat_processus, (*((struct_variable *)
 1460:                                 (*l_element_courant_liste).donnee)).objet);
 1461:                         free((*((struct_variable *) (*l_element_courant_liste)
 1462:                                 .donnee)).nom);
 1463:                         free((*l_element_courant_liste).donnee);
 1464:                     }
 1465: 
 1466:                     l_element_suivant_liste =
 1467:                             (*l_element_courant_liste).suivant;
 1468:                     free(l_element_courant_liste);
 1469:                     l_element_courant_liste = l_element_suivant_liste;
 1470:                 }
 1471: 
 1472:                 l_element_suivant = (*l_element_courant).suivant;
 1473:                 free(l_element_courant);
 1474:                 l_element_courant = l_element_suivant;
 1475:             } while(l_element_courant != (*s_etat_processus)
 1476:                     .l_liste_variables_par_niveau);
 1477:         }
 1478:     }
 1479: 
 1480:     free((*arbre).noeuds);
 1481:     free(arbre);
 1482: 
 1483:     return;
 1484: }
 1485: 
 1486: 
 1487: /*
 1488: ================================================================================
 1489:   Procédure renvoyant les variables dans un tableau
 1490: ================================================================================
 1491:   Entrée :
 1492: --------------------------------------------------------------------------------
 1493:   Sortie :
 1494: --------------------------------------------------------------------------------
 1495:   Effets de bord : néant
 1496: ================================================================================
 1497: */
 1498: 
 1499: int
 1500: nombre_variables(struct_processus *s_etat_processus,
 1501:         struct_arbre_variables *l_element_courant)
 1502: {
 1503:     int                     i;
 1504:     int                     n;
 1505: 
 1506:     struct_liste_variables  *l_variable;
 1507: 
 1508:     n = 0;
 1509: 
 1510:     if ((*l_element_courant).feuille != NULL)
 1511:     {
 1512:         l_variable = (*l_element_courant).feuille;
 1513: 
 1514:         do
 1515:         {
 1516:             n++;
 1517:             l_variable = (*l_variable).suivant;
 1518:         } while(l_variable != (*l_element_courant).feuille);
 1519:     }
 1520: 
 1521:     for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
 1522:     {
 1523:         if ((*l_element_courant).noeuds[i] != NULL)
 1524:         {
 1525:             n += nombre_variables(s_etat_processus,
 1526:                     (*l_element_courant).noeuds[i]);
 1527:         }
 1528:     }
 1529: 
 1530:     return(n);
 1531: }
 1532: 
 1533: int
 1534: liste_variables(struct_processus *s_etat_processus,
 1535:         struct_tableau_variables *tableau, int position,
 1536:         struct_arbre_variables *l_element_courant)
 1537: {
 1538:     int                     i;
 1539: 
 1540:     struct_liste_variables  *l_variable;
 1541: 
 1542:     if ((*l_element_courant).feuille != NULL)
 1543:     {
 1544:         l_variable = (*l_element_courant).feuille;
 1545: 
 1546:         do
 1547:         {
 1548:             tableau[position].origine = (*(*l_variable).variable).origine;
 1549:             tableau[position].nom = (*(*l_variable).variable).nom;
 1550:             tableau[position].niveau = (*(*l_variable).variable).niveau;
 1551:             tableau[position].objet = (*(*l_variable).variable).objet;
 1552:             tableau[position].variable_verrouillee =
 1553:                     (*(*l_variable).variable).variable_verrouillee;
 1554:             tableau[position].variable_statique =
 1555:                     (*(*l_variable).variable).variable_statique;
 1556:             tableau[position].variable_partagee =
 1557:                     (*(*l_variable).variable).variable_partagee;
 1558: 
 1559:             position++;
 1560:             l_variable = (*l_variable).suivant;
 1561:         } while(l_variable != (*l_element_courant).feuille);
 1562:     }
 1563: 
 1564:     for(i = 0; i < (*s_etat_processus).nombre_caracteres_variables; i++)
 1565:     {
 1566:         if ((*l_element_courant).noeuds[i] != NULL)
 1567:         {
 1568:             position = liste_variables(s_etat_processus,
 1569:                     tableau, position, (*l_element_courant).noeuds[i]);
 1570:         }
 1571:     }
 1572: 
 1573:     return(position);
 1574: }
 1575: 
 1576: /*
 1577: ================================================================================
 1578:   Procédure de copie de l'arbre des variables
 1579: ================================================================================
 1580:   Entrée :
 1581: --------------------------------------------------------------------------------
 1582:   Sortie :
 1583: --------------------------------------------------------------------------------
 1584:   Effets de bord : néant
 1585: ================================================================================
 1586: */
 1587: 
 1588: struct_arbre_variables *
 1589: copie_arbre_variables(struct_processus *s_etat_processus)
 1590: {
 1591:     // Les définitions sont partagées entre tous les threads et ne sont pas
 1592:     // copiées.
 1593:     //
 1594:     // NB : on ne copie que les variables de niveaux 0 et 1, les autres
 1595:     // variables locales étant masquées par le processus de création de thread
 1596:     // ou de processus, elles sont inaccessibles.
 1597: 
 1598:     BUG(1, uprintf("Oops !\n"));
 1599: 
 1600:     return(d_absence_erreur);
 1601: }
 1602: 
 1603: 
 1604: /*
 1605: ================================================================================
 1606:   Procédure d'initialisation de la table de correspondance des variables
 1607: ================================================================================
 1608:   Entrée :
 1609: --------------------------------------------------------------------------------
 1610:   Sortie :
 1611: --------------------------------------------------------------------------------
 1612:   Effets de bord : néant
 1613: ================================================================================
 1614: */
 1615: 
 1616: /*
 1617:  * Caractères autorisés dans les instructions
 1618:  *
 1619:  * A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
 1620:  * a b c d e f g h i j k l m n o p q r s t u v w x y z
 1621:  * _
 1622:  * 1 2 3 4 5 6 7 8 9 0
 1623:  */
 1624: 
 1625: void
 1626: initialisation_variables(struct_processus *s_etat_processus)
 1627: {
 1628:     int             decalage;
 1629:     int             i;
 1630:     int             longueur_tableau;
 1631: 
 1632:     unsigned char   caractere;
 1633: 
 1634:     // Récupération de la longueur d'un unsigned char
 1635: 
 1636:     longueur_tableau = 1;
 1637:     decalage = 0;
 1638:     caractere = 1;
 1639: 
 1640:     while((1L << decalage) == (long) ((unsigned char) (caractere << decalage)))
 1641:     {
 1642:         decalage++;
 1643:         longueur_tableau *= 2;
 1644:     }
 1645: 
 1646:     if (((*s_etat_processus).pointeurs_caracteres_variables =
 1647:             malloc(longueur_tableau * sizeof(int))) == NULL)
 1648:     {
 1649:         (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
 1650:         return;
 1651:     }
 1652: 
 1653:     for(i = 0; i < longueur_tableau; i++)
 1654:     {
 1655:         (*s_etat_processus).pointeurs_caracteres_variables[i] = -1;
 1656:     }
 1657: 
 1658:     (*s_etat_processus).nombre_caracteres_variables = 0;
 1659: 
 1660: #define DECLARATION_CARACTERE(c) \
 1661:         do { (*s_etat_processus).pointeurs_caracteres_variables[c] = \
 1662:         (*s_etat_processus).nombre_caracteres_variables++; } while(0)
 1663: 
 1664:     DECLARATION_CARACTERE('A');
 1665:     DECLARATION_CARACTERE('B');
 1666:     DECLARATION_CARACTERE('C');
 1667:     DECLARATION_CARACTERE('D');
 1668:     DECLARATION_CARACTERE('E');
 1669:     DECLARATION_CARACTERE('F');
 1670:     DECLARATION_CARACTERE('G');
 1671:     DECLARATION_CARACTERE('H');
 1672:     DECLARATION_CARACTERE('I');
 1673:     DECLARATION_CARACTERE('J');
 1674:     DECLARATION_CARACTERE('K');
 1675:     DECLARATION_CARACTERE('L');
 1676:     DECLARATION_CARACTERE('M');
 1677:     DECLARATION_CARACTERE('N');
 1678:     DECLARATION_CARACTERE('O');
 1679:     DECLARATION_CARACTERE('P');
 1680:     DECLARATION_CARACTERE('Q');
 1681:     DECLARATION_CARACTERE('R');
 1682:     DECLARATION_CARACTERE('S');
 1683:     DECLARATION_CARACTERE('T');
 1684:     DECLARATION_CARACTERE('U');
 1685:     DECLARATION_CARACTERE('V');
 1686:     DECLARATION_CARACTERE('W');
 1687:     DECLARATION_CARACTERE('X');
 1688:     DECLARATION_CARACTERE('Y');
 1689:     DECLARATION_CARACTERE('Z');
 1690: 
 1691:     DECLARATION_CARACTERE('a');
 1692:     DECLARATION_CARACTERE('b');
 1693:     DECLARATION_CARACTERE('c');
 1694:     DECLARATION_CARACTERE('d');
 1695:     DECLARATION_CARACTERE('e');
 1696:     DECLARATION_CARACTERE('f');
 1697:     DECLARATION_CARACTERE('g');
 1698:     DECLARATION_CARACTERE('h');
 1699:     DECLARATION_CARACTERE('i');
 1700:     DECLARATION_CARACTERE('j');
 1701:     DECLARATION_CARACTERE('k');
 1702:     DECLARATION_CARACTERE('l');
 1703:     DECLARATION_CARACTERE('m');
 1704:     DECLARATION_CARACTERE('n');
 1705:     DECLARATION_CARACTERE('o');
 1706:     DECLARATION_CARACTERE('p');
 1707:     DECLARATION_CARACTERE('q');
 1708:     DECLARATION_CARACTERE('r');
 1709:     DECLARATION_CARACTERE('s');
 1710:     DECLARATION_CARACTERE('t');
 1711:     DECLARATION_CARACTERE('u');
 1712:     DECLARATION_CARACTERE('v');
 1713:     DECLARATION_CARACTERE('w');
 1714:     DECLARATION_CARACTERE('x');
 1715:     DECLARATION_CARACTERE('y');
 1716:     DECLARATION_CARACTERE('z');
 1717: 
 1718:     DECLARATION_CARACTERE('_');
 1719: 
 1720:     DECLARATION_CARACTERE('1');
 1721:     DECLARATION_CARACTERE('2');
 1722:     DECLARATION_CARACTERE('3');
 1723:     DECLARATION_CARACTERE('4');
 1724:     DECLARATION_CARACTERE('5');
 1725:     DECLARATION_CARACTERE('6');
 1726:     DECLARATION_CARACTERE('7');
 1727:     DECLARATION_CARACTERE('8');
 1728:     DECLARATION_CARACTERE('9');
 1729:     DECLARATION_CARACTERE('0');
 1730: #undef DECLARATION_CARACTERE
 1731: 
 1732:     return;
 1733: }
 1734: 
 1735: // vim: ts=4

CVSweb interface <joel.bertrand@systella.fr>