File:  [local] / rpl / src / gestion_pile.c
Revision 1.4: download - view: text, annotated - select for diffs - revision graph
Wed Feb 10 10:14:20 2010 UTC (14 years, 2 months ago) by bertrand
Branches: MAIN
CVS tags: rpl-4_0_11, HEAD
Branchement vers 4.0.11

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

CVSweb interface <joel.bertrand@systella.fr>