Annotation of rpl/src/gestion_pile.c, revision 1.5

1.1       bertrand    1: /*
                      2: ================================================================================
1.5     ! bertrand    3:   RPL/2 (R) version 4.0.12
1.1       bertrand    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: {
1.3       bertrand  246:    unsigned char           registre;
                    247: 
                    248:    registre = (*s_etat_processus).autorisation_conversion_chaine;
                    249:    (*s_etat_processus).autorisation_conversion_chaine = 'N';
                    250: 
1.1       bertrand  251:    ecriture_pile(s_etat_processus, stdout, l_element_courant, niveau_courant);
1.3       bertrand  252: 
                    253:    (*s_etat_processus).autorisation_conversion_chaine = registre;
1.1       bertrand  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>