/* ================================================================================ RPL/2 (R) version 4.0.20 Copyright (C) 1989-2010 Dr. BERTRAND Joël This file is part of RPL/2. RPL/2 is free software; you can redistribute it and/or modify it under the terms of the CeCILL V2 License as published by the french CEA, CNRS and INRIA. RPL/2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL V2 License for more details. You should have received a copy of the CeCILL License along with RPL/2. If not, write to info@cecill.info. ================================================================================ */ #include "rpl-conv.h" /* ================================================================================ Procédure d'estimation de la longueur du tampon ================================================================================ Entrée : -------------------------------------------------------------------------------- Sortie : -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ static inline void estimation_taille_pile(struct_processus *s_etat_processus) { /* * Cette fonction permet d'estimer un volant de structures de maillons * de liste chaînée pour le programme courant et évite un certain nombre * d'allocations de mémoire lors des manipulations de la pile. Cette taille * est estimée au travers d'une chaîne de Markov. */ if ((*s_etat_processus).hauteur_pile_operationnelle > (*s_etat_processus).estimation_taille_pile_tampon) { (*s_etat_processus).estimation_taille_pile_tampon = (*s_etat_processus).estimation_taille_pile_tampon; } else { (*s_etat_processus).estimation_taille_pile_tampon = ((*s_etat_processus).estimation_taille_pile_tampon * ((double) 0.95)) + ((*s_etat_processus) .hauteur_pile_operationnelle * ((double) 0.05)); } return; } /* ================================================================================ Procédure d'empilement d'un nouvel élément ================================================================================ Entrée : -------------------------------------------------------------------------------- Sortie : -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ logical1 empilement(struct_processus *s_etat_processus, struct_liste_chainee **l_base_pile, struct_objet *s_objet) { struct_liste_chainee *l_ancienne_base_liste; struct_liste_chainee *l_nouvelle_base_liste; logical1 erreur; l_ancienne_base_liste = *l_base_pile; if ((*s_etat_processus).pile_tampon == NULL) { // Tampon vide, on alloue un élément. if ((l_nouvelle_base_liste = malloc(sizeof(struct_liste_chainee))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(d_erreur); } } else { // Tampon utilisable, on retire un élément du tampon. l_nouvelle_base_liste = (*s_etat_processus).pile_tampon; (*s_etat_processus).pile_tampon = (*l_nouvelle_base_liste).suivant; (*s_etat_processus).taille_pile_tampon--; } *l_base_pile = l_nouvelle_base_liste; (**l_base_pile).donnee = s_objet; (**l_base_pile).suivant = l_ancienne_base_liste; erreur = d_absence_erreur; /* -- Ne considère que la pile opérationnelle ------------------------------------- */ if ((*s_etat_processus).l_base_pile == *l_base_pile) { (*s_etat_processus).hauteur_pile_operationnelle++; estimation_taille_pile(s_etat_processus); if ((*s_etat_processus).debug == d_vrai) if (((*s_etat_processus).type_debug & d_debug_pile_utilisateur) != 0) { if ((*s_etat_processus).langue == 'F') { printf("[%d] Empilement de type %d " "(profondeur %lu)\n", (int) getpid(), (*s_objet).type, (*s_etat_processus).hauteur_pile_operationnelle); } else { printf("[%d] Pushing a type %d object " "(depth %lu)\n", (int) getpid(), (*s_objet).type, (*s_etat_processus).hauteur_pile_operationnelle); } fflush(stdout); } } return erreur; } /* ================================================================================ Procédure de dépilement d'un élément. L'emplacement est libéré dans la pile. ================================================================================ Entrée : -------------------------------------------------------------------------------- Sortie : -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ logical1 depilement(struct_processus *s_etat_processus, struct_liste_chainee **l_base_pile, struct_objet **s_objet) { struct_liste_chainee *l_ancienne_base_liste; struct_liste_chainee *l_nouvelle_base_liste; logical1 erreur; if (*l_base_pile == NULL) { (*s_etat_processus).erreur_execution = d_ex_pile_vide; erreur = d_erreur; } else { /* -- Ne considère que la pile opérationnelle ------------------------------------- */ l_ancienne_base_liste = *l_base_pile; *s_objet = (*l_ancienne_base_liste).donnee; if ((*s_etat_processus).l_base_pile == *l_base_pile) { if ((*s_etat_processus).debug == d_vrai) if (((*s_etat_processus).type_debug & d_debug_pile_utilisateur) != 0) { if ((*s_etat_processus).langue == 'F') { printf("[%d] Dépilement de type %d " "(profondeur %lu)\n", (int) getpid(), (*(*s_objet)).type, (*s_etat_processus).hauteur_pile_operationnelle); } else { printf("[%d] Pulling a type %d object " "(depth %lu)\n", (int) getpid(), (*(*s_objet)).type, (*s_etat_processus).hauteur_pile_operationnelle); } fflush(stdout); } (*s_etat_processus).hauteur_pile_operationnelle--; estimation_taille_pile(s_etat_processus); } l_nouvelle_base_liste = (*l_ancienne_base_liste).suivant; *l_base_pile = l_nouvelle_base_liste; erreur = d_absence_erreur; if ((*s_etat_processus).taille_pile_tampon <= (10 * ((*s_etat_processus) .estimation_taille_pile_tampon + 1))) { // Enregistrement de la structure pour usage ultérieur. (*l_ancienne_base_liste).donnee = NULL; (*l_ancienne_base_liste).suivant = (*s_etat_processus).pile_tampon; (*s_etat_processus).pile_tampon = l_ancienne_base_liste; (*s_etat_processus).taille_pile_tampon++; } else { // Libération car le tampon est plein. free(l_ancienne_base_liste); } } return erreur; } /* ================================================================================ Procédures affichant la pile opérationnelle ================================================================================ Entrée : -------------------------------------------------------------------------------- Sortie : -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ void affichage_pile(struct_processus *s_etat_processus, struct_liste_chainee *l_element_courant, unsigned long niveau_courant) { unsigned char registre; registre = (*s_etat_processus).autorisation_conversion_chaine; (*s_etat_processus).autorisation_conversion_chaine = 'N'; ecriture_pile(s_etat_processus, stdout, l_element_courant, niveau_courant); (*s_etat_processus).autorisation_conversion_chaine = registre; return; } void ecriture_pile(struct_processus *s_etat_processus, file *flux, struct_liste_chainee *l_element_courant, unsigned long niveau_courant) { unsigned char *chaine; unsigned char *registre; unsigned char tampon[32 + 1]; if (l_element_courant != NULL) { if (setjmp(contexte) == 0) { (*s_etat_processus).var_volatile_recursivite = -1; ecriture_pile(s_etat_processus, flux, (*l_element_courant).suivant, niveau_courant + 1); if ((*s_etat_processus).var_volatile_recursivite > 0) { (*s_etat_processus).var_volatile_recursivite--; if ((*s_etat_processus).var_volatile_recursivite == 0) { if (fprintf(flux, "%lu: ...\n", niveau_courant) < 0) { (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; return; } while(l_element_courant != NULL) { l_element_courant = (*l_element_courant).suivant; } } return; } (*s_etat_processus).var_volatile_recursivite = 0; } else { // Libération de n appels de la pile système qui permet de // terminer la récursion sans autre dépassement de pile. (*s_etat_processus).var_volatile_recursivite = 64; return; } sprintf(tampon, "%lu: ", niveau_courant); if ((chaine = formateur(s_etat_processus, strlen(tampon), (*l_element_courant).donnee)) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } if ((*(*l_element_courant).donnee).type == CHN) { registre = chaine; if ((chaine = (unsigned char *) malloc((strlen(registre) + 3) * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } sprintf(chaine, "\"%s\"", registre); free(registre); } if (fprintf(flux, "%lu: %s\n", niveau_courant, chaine) < 0) { (*s_etat_processus).erreur_systeme = d_es_erreur_fichier; return; } free(chaine); } return; } /* ================================================================================ Procédure imprimant la pile opérationnelle ================================================================================ Entrée : méthode 'C' = compacte, 'E' = étendue -------------------------------------------------------------------------------- Sortie : -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ void impression_pile(struct_processus *s_etat_processus, struct_liste_chainee *l_element_courant, unsigned char methode, unsigned long niveau_courant) { struct_objet s_objet; unsigned char *chaine; unsigned char *registre; unsigned char tampon[32 + 1]; if (l_element_courant != NULL) { if (setjmp(contexte) == 0) { (*s_etat_processus).var_volatile_recursivite = -1; impression_pile(s_etat_processus, (*l_element_courant).suivant, methode, niveau_courant + 1); if ((*s_etat_processus).var_volatile_recursivite > 0) { (*s_etat_processus).var_volatile_recursivite--; if ((*s_etat_processus).var_volatile_recursivite == 0) { while(l_element_courant != NULL) { l_element_courant = (*l_element_courant).suivant; } } return; } (*s_etat_processus).var_volatile_recursivite = 0; } else { (*s_etat_processus).var_volatile_recursivite = 16; return; } if (methode == 'C') { s_objet.type = CHN; sprintf(tampon, "%lu: ", niveau_courant); if ((chaine = formateur(s_etat_processus, strlen(tampon), (*l_element_courant).donnee)) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } if ((*(*l_element_courant).donnee).type == CHN) { registre = chaine; if ((chaine = (unsigned char *) malloc((strlen(registre) + 3) * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } sprintf(chaine, "\"%s\"", registre); free(registre); } if ((s_objet.objet = malloc((strlen(chaine) + 64) * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return; } sprintf((unsigned char *) s_objet.objet, "\n\\noindent\\begin{verbatim}\n%lu: %s\n\\end{verbatim}", niveau_courant, chaine); free(chaine); formateur_tex(s_etat_processus, &s_objet, 'V'); free(s_objet.objet); } else { formateur_tex(s_etat_processus, (*l_element_courant).donnee, 'N'); } } return; } // vim: ts=4