File:  [local] / rpl / src / gestion_pile.c
Revision 1.24: download - view: text, annotated - select for diffs - revision graph
Tue Jun 21 15:26:29 2011 UTC (12 years, 10 months ago) by bertrand
Branches: MAIN
CVS tags: HEAD
Correction d'une réinitialisation sauvage de la pile des variables par niveau
dans la copie de la structure de description du processus. Cela corrige
la fonction SPAWN qui échouait sur un segmentation fault car la pile des
variables par niveau était vide alors même que l'arbre des variables contenait
bien les variables. Passage à la prerelease 2.

    1: /*
    2: ================================================================================
    3:   RPL/2 (R) version 4.1.0.prerelease.2
    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:   Procédure d'estimation de la longueur du tampon
   29: ================================================================================
   30:   Entrée :
   31: --------------------------------------------------------------------------------
   32:   Sortie :
   33: --------------------------------------------------------------------------------
   34:   Effets de bord : néant
   35: ================================================================================
   36: */
   37: 
   38: static inline void
   39: estimation_taille_pile(struct_processus *s_etat_processus)
   40: {
   41:     /*
   42:      * Cette fonction permet d'estimer un volant de structures de maillons
   43:      * de liste chaînée pour le programme courant et évite un certain nombre
   44:      * d'allocations de mémoire lors des manipulations de la pile. Cette taille
   45:      * est estimée au travers d'une chaîne de Markov.
   46:      */
   47: 
   48:     if ((*s_etat_processus).hauteur_pile_operationnelle >
   49:             (*s_etat_processus).estimation_taille_pile_tampon)
   50:     {
   51:         (*s_etat_processus).estimation_taille_pile_tampon =
   52:                 (*s_etat_processus).estimation_taille_pile_tampon;
   53:     }
   54:     else
   55:     {
   56:         (*s_etat_processus).estimation_taille_pile_tampon =
   57:                 ((*s_etat_processus).estimation_taille_pile_tampon *
   58:                 ((double) 0.95)) + ((*s_etat_processus)
   59:                 .hauteur_pile_operationnelle * ((double) 0.05));
   60:     }
   61: 
   62:     return;
   63: }
   64: 
   65: 
   66: /*
   67: ================================================================================
   68:   Procédure d'empilement d'un nouvel élément
   69: ================================================================================
   70:   Entrée :
   71: --------------------------------------------------------------------------------
   72:   Sortie :
   73: --------------------------------------------------------------------------------
   74:   Effets de bord : néant
   75: ================================================================================
   76: */
   77: 
   78: logical1
   79: empilement(struct_processus *s_etat_processus,
   80:         struct_liste_chainee **l_base_pile, struct_objet *s_objet)
   81: {
   82:     struct_liste_chainee        *l_ancienne_base_liste;
   83:     struct_liste_chainee        *l_nouvelle_base_liste;
   84: 
   85:     logical1                    erreur;
   86: 
   87:     l_ancienne_base_liste = *l_base_pile;
   88: 
   89:     if ((*s_etat_processus).pile_tampon == NULL)
   90:     {
   91:         // Tampon vide, on alloue un élément.
   92: 
   93:         if ((l_nouvelle_base_liste = malloc(sizeof(struct_liste_chainee)))
   94:                 == NULL)
   95:         {
   96:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
   97:             return(d_erreur);
   98:         }
   99:     }
  100:     else
  101:     {
  102:         // Tampon utilisable, on retire un élément du tampon.
  103: 
  104:         l_nouvelle_base_liste = (*s_etat_processus).pile_tampon;
  105:         (*s_etat_processus).pile_tampon = (*l_nouvelle_base_liste).suivant;
  106:         (*s_etat_processus).taille_pile_tampon--;
  107:     }
  108: 
  109:     *l_base_pile = l_nouvelle_base_liste;
  110:     (**l_base_pile).donnee = s_objet;
  111:     (**l_base_pile).suivant = l_ancienne_base_liste;
  112: 
  113:     erreur = d_absence_erreur;
  114: 
  115: /*
  116: -- Ne considère que la pile opérationnelle -------------------------------------
  117: */
  118: 
  119:     if ((*s_etat_processus).l_base_pile == *l_base_pile)
  120:     {
  121:         (*s_etat_processus).hauteur_pile_operationnelle++;
  122:         estimation_taille_pile(s_etat_processus);
  123: 
  124:         if ((*s_etat_processus).debug == d_vrai)
  125:             if (((*s_etat_processus).type_debug &
  126:                     d_debug_pile_utilisateur) != 0)
  127:         {
  128:             if ((*s_etat_processus).langue == 'F')
  129:             {
  130:                 printf("[%d] Empilement de type %d "
  131:                         "(profondeur %lu)\n", (int) getpid(),
  132:                         (*s_objet).type,
  133:                         (*s_etat_processus).hauteur_pile_operationnelle);
  134:             }
  135:             else
  136:             {
  137:                 printf("[%d] Pushing a type %d object "
  138:                         "(depth %lu)\n", (int) getpid(), (*s_objet).type,
  139:                         (*s_etat_processus).hauteur_pile_operationnelle);
  140:             }
  141: 
  142:             fflush(stdout);
  143:         }
  144:     }
  145: 
  146:     return erreur;
  147: }
  148: 
  149: 
  150: /*
  151: ================================================================================
  152:   Procédure de dépilement d'un élément. L'emplacement est libéré dans la pile.
  153: ================================================================================
  154:   Entrée :
  155: --------------------------------------------------------------------------------
  156:   Sortie :
  157: --------------------------------------------------------------------------------
  158:   Effets de bord : néant
  159: ================================================================================
  160: */
  161: 
  162: logical1
  163: depilement(struct_processus *s_etat_processus,
  164:         struct_liste_chainee **l_base_pile, struct_objet **s_objet)
  165: {
  166:     struct_liste_chainee        *l_ancienne_base_liste;
  167:     struct_liste_chainee        *l_nouvelle_base_liste;
  168: 
  169:     logical1                    erreur;
  170: 
  171:     if (*l_base_pile == NULL)
  172:     {
  173:         (*s_etat_processus).erreur_execution = d_ex_pile_vide;
  174:         erreur = d_erreur;
  175:     }
  176:     else
  177:     {
  178: 
  179: /*
  180: -- Ne considère que la pile opérationnelle -------------------------------------
  181: */
  182: 
  183:         l_ancienne_base_liste = *l_base_pile;
  184:         *s_objet = (*l_ancienne_base_liste).donnee;
  185: 
  186:         if ((*s_etat_processus).l_base_pile == *l_base_pile)
  187:         {
  188:             if ((*s_etat_processus).debug == d_vrai)
  189:                 if (((*s_etat_processus).type_debug &
  190:                         d_debug_pile_utilisateur) != 0)
  191:             {
  192:                 if ((*s_etat_processus).langue == 'F')
  193:                 {
  194:                     printf("[%d] Dépilement de type %d "
  195:                             "(profondeur %lu)\n", (int) getpid(),
  196:                             (*(*s_objet)).type,
  197:                             (*s_etat_processus).hauteur_pile_operationnelle);
  198:                 }
  199:                 else
  200:                 {
  201:                     printf("[%d] Pulling a type %d object "
  202:                             "(depth %lu)\n", (int) getpid(), (*(*s_objet)).type,
  203:                             (*s_etat_processus).hauteur_pile_operationnelle);
  204:                 }
  205: 
  206:                 fflush(stdout);
  207:             }
  208: 
  209:             (*s_etat_processus).hauteur_pile_operationnelle--;
  210:             estimation_taille_pile(s_etat_processus);
  211:         }
  212: 
  213:         l_nouvelle_base_liste = (*l_ancienne_base_liste).suivant;
  214: 
  215:         *l_base_pile = l_nouvelle_base_liste;
  216:         erreur = d_absence_erreur;
  217: 
  218:         if ((*s_etat_processus).taille_pile_tampon <= (10 * ((*s_etat_processus)
  219:                 .estimation_taille_pile_tampon + 1)))
  220:         {
  221:             // Enregistrement de la structure pour usage ultérieur.
  222: 
  223:             (*l_ancienne_base_liste).donnee = NULL;
  224:             (*l_ancienne_base_liste).suivant = (*s_etat_processus).pile_tampon;
  225:             (*s_etat_processus).pile_tampon = l_ancienne_base_liste;
  226:             (*s_etat_processus).taille_pile_tampon++;
  227:         }
  228:         else
  229:         {
  230:             // Libération car le tampon est plein.
  231: 
  232:             free(l_ancienne_base_liste);
  233:         }
  234:     }
  235: 
  236:     return erreur;
  237: }
  238: 
  239: 
  240: /*
  241: ================================================================================
  242:   Procédures affichant la pile opérationnelle
  243: ================================================================================
  244:   Entrée :
  245: --------------------------------------------------------------------------------
  246:   Sortie :
  247: --------------------------------------------------------------------------------
  248:   Effets de bord : néant
  249: ================================================================================
  250: */
  251: 
  252: void
  253: affichage_pile(struct_processus *s_etat_processus, struct_liste_chainee
  254:         *l_element_courant, unsigned long niveau_courant)
  255: {
  256:     unsigned char           registre;
  257: 
  258:     registre = (*s_etat_processus).autorisation_conversion_chaine;
  259:     (*s_etat_processus).autorisation_conversion_chaine = 'N';
  260: 
  261:     ecriture_pile(s_etat_processus, stdout, l_element_courant, niveau_courant);
  262: 
  263:     (*s_etat_processus).autorisation_conversion_chaine = registre;
  264:     return;
  265: }
  266: 
  267: void
  268: ecriture_pile(struct_processus *s_etat_processus, file *flux,
  269:         struct_liste_chainee *l_element_courant, unsigned long niveau_courant)
  270: {
  271:     unsigned char               *chaine;
  272:     unsigned char               *registre;
  273:     unsigned char               tampon[32 + 1];
  274: 
  275:     if (l_element_courant != NULL)
  276:     {
  277:         if (setjmp(contexte) == 0)
  278:         {
  279:             (*s_etat_processus).var_volatile_recursivite = -1;
  280:             ecriture_pile(s_etat_processus, flux,
  281:                     (*l_element_courant).suivant, niveau_courant + 1);
  282: 
  283:             if ((*s_etat_processus).var_volatile_recursivite > 0)
  284:             {
  285:                 (*s_etat_processus).var_volatile_recursivite--;
  286: 
  287:                 if ((*s_etat_processus).var_volatile_recursivite == 0)
  288:                 {
  289:                     if (fprintf(flux, "%lu: ...\n", niveau_courant) < 0)
  290:                     {
  291:                         (*s_etat_processus).erreur_systeme =
  292:                                 d_es_erreur_fichier;
  293:                         return;
  294:                     }
  295: 
  296:                     while(l_element_courant != NULL)
  297:                     {
  298:                         l_element_courant = (*l_element_courant).suivant;
  299:                     }
  300:                 }
  301: 
  302:                 return;
  303:             }
  304: 
  305:             (*s_etat_processus).var_volatile_recursivite = 0;
  306:         }
  307:         else
  308:         {
  309:             // Libération de n appels de la pile système qui permet de
  310:             // terminer la récursion sans autre dépassement de pile.
  311: 
  312:             (*s_etat_processus).var_volatile_recursivite = 64;
  313:             return;
  314:         }
  315: 
  316:         sprintf(tampon, "%lu: ", niveau_courant);
  317: 
  318:         if ((chaine = formateur(s_etat_processus, strlen(tampon),
  319:                 (*l_element_courant).donnee)) == NULL)
  320:         {
  321:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  322:             return;
  323:         }
  324: 
  325:         if ((*(*l_element_courant).donnee).type == CHN)
  326:         {
  327:             registre = chaine;
  328: 
  329:             if ((chaine = (unsigned char *) malloc((strlen(registre) + 3) *
  330:                     sizeof(unsigned char))) == NULL)
  331:             {
  332:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  333:                 return;
  334:             }
  335: 
  336:             sprintf(chaine, "\"%s\"", registre);
  337:             free(registre);
  338:         }
  339: 
  340:         if (fprintf(flux, "%lu: %s\n", niveau_courant, chaine) < 0)
  341:         {
  342:             (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;
  343:             return;
  344:         }
  345: 
  346:         free(chaine);
  347:     }
  348: 
  349:     return;
  350: }
  351: 
  352: 
  353: /*
  354: ================================================================================
  355:   Procédure imprimant la pile opérationnelle
  356: ================================================================================
  357:   Entrée : méthode 'C' = compacte, 'E' = étendue
  358: --------------------------------------------------------------------------------
  359:   Sortie :
  360: --------------------------------------------------------------------------------
  361:   Effets de bord : néant
  362: ================================================================================
  363: */
  364: 
  365: void
  366: impression_pile(struct_processus *s_etat_processus,
  367:         struct_liste_chainee *l_element_courant, unsigned char methode,
  368:         unsigned long niveau_courant)
  369: {
  370:     struct_objet                s_objet;
  371: 
  372:     unsigned char               *chaine;
  373:     unsigned char               *registre;
  374:     unsigned char               tampon[32 + 1];
  375: 
  376:     if (l_element_courant != NULL)
  377:     {
  378:         if (setjmp(contexte) == 0)
  379:         {
  380:             (*s_etat_processus).var_volatile_recursivite = -1;
  381:             impression_pile(s_etat_processus, (*l_element_courant).suivant,
  382:                     methode, niveau_courant + 1);
  383: 
  384:             if ((*s_etat_processus).var_volatile_recursivite > 0)
  385:             {
  386:                 (*s_etat_processus).var_volatile_recursivite--;
  387: 
  388:                 if ((*s_etat_processus).var_volatile_recursivite == 0)
  389:                 {
  390:                     while(l_element_courant != NULL)
  391:                     {
  392:                         l_element_courant = (*l_element_courant).suivant;
  393:                     }
  394:                 }
  395: 
  396:                 return;
  397:             }
  398: 
  399:             (*s_etat_processus).var_volatile_recursivite = 0;
  400:         }
  401:         else
  402:         {
  403:             (*s_etat_processus).var_volatile_recursivite = 16;
  404:             return;
  405:         }
  406: 
  407:         if (methode == 'C')
  408:         {
  409:             s_objet.type = CHN;
  410:             sprintf(tampon, "%lu: ", niveau_courant);
  411: 
  412:             if ((chaine = formateur(s_etat_processus, strlen(tampon),
  413:                     (*l_element_courant).donnee)) == NULL)
  414:             {
  415:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  416:                 return;
  417:             }
  418: 
  419:             if ((*(*l_element_courant).donnee).type == CHN)
  420:             {
  421:                 registre = chaine;
  422: 
  423:                 if ((chaine = (unsigned char *) malloc((strlen(registre) + 3) *
  424:                         sizeof(unsigned char))) == NULL)
  425:                 {
  426:                     (*s_etat_processus).erreur_systeme =
  427:                             d_es_allocation_memoire;
  428:                     return;
  429:                 }
  430: 
  431:                 sprintf(chaine, "\"%s\"", registre);
  432:                 free(registre);
  433:             }
  434: 
  435:             if ((s_objet.objet = malloc((strlen(chaine) + 64) *
  436:                     sizeof(unsigned char))) == NULL)
  437:             {
  438:                 (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  439:                 return;
  440:             }
  441: 
  442:             sprintf((unsigned char *) s_objet.objet,
  443:                     "\n\\noindent\\begin{verbatim}\n%lu: %s\n\\end{verbatim}",
  444:                     niveau_courant, chaine);
  445:             free(chaine);
  446: 
  447:             formateur_tex(s_etat_processus, &s_objet, 'V');
  448:             free(s_objet.objet);
  449:         }
  450:         else
  451:         {
  452:             formateur_tex(s_etat_processus, (*l_element_courant).donnee, 'N');
  453:         }
  454:     }
  455: 
  456:     return;
  457: }
  458: 
  459: // vim: ts=4

CVSweb interface <joel.bertrand@systella.fr>