File:  [local] / rpl / src / gestion_variables.c
Revision 1.34: download - view: text, annotated - select for diffs - revision graph
Mon Jun 20 17:34:10 2011 UTC (12 years, 10 months ago) by bertrand
Branches: MAIN
CVS tags: HEAD
La nouvelle gestion des variables fonctionne sur des programmes non
compilés utilisant des variables de tous niveaux. Les différentes techniques
de masquage des variables ont été testées ainsi que les portées des variables.

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

CVSweb interface <joel.bertrand@systella.fr>