/* ================================================================================ RPL/2 (R) version 4.1.35 Copyright (C) 1989-2023 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" static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; /* ================================================================================ Procédure de chargement d'une bibliothèque dynamique ================================================================================ Entrée : -------------------------------------------------------------------------------- Sortie : -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ void * chargement_bibliotheque(struct_processus *s_etat_processus, unsigned char *bibliotheque) { char **(*fonction)(struct_rpl_arguments *, integer8 *, const char *); char *message; integer8 i; integer8 nombre_symboles; struct_rpl_arguments rpl_arguments; struct_liste_chainee *l_element_courant; struct_liste_chainee *l_nouvel_element; unsigned char *fleche; unsigned char **tableau; unsigned char *tampon; void *descripteur_bibliotheque; int (*onloading)(struct_rpl_arguments *, void *); /* * On vérifie que la bibliothèque n'est pas déjà chargée. */ l_element_courant = (*s_etat_processus).s_bibliotheques; while(l_element_courant != NULL) { if (strcmp((*((struct_bibliotheque *) (*l_element_courant).donnee)).nom, bibliotheque) == 0) { (*s_etat_processus).erreur_execution = d_ex_bibliotheque_chargee; return(NULL); } l_element_courant = (*l_element_courant).suivant; } /* * Ouverture de la bibliothèque */ if ((descripteur_bibliotheque = dlopen(bibliotheque, RTLD_NOW | RTLD_LOCAL)) == NULL) { if (pthread_mutex_lock(&mutex) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return(NULL); } printf("%s\n", dlerror()); if (pthread_mutex_unlock(&mutex) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return(NULL); } (*s_etat_processus).erreur_execution = d_ex_erreur_bibliotheque; return(NULL); } if (pthread_mutex_lock(&mutex) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return(NULL); } dlerror(); onloading = dlsym(descripteur_bibliotheque, "__runOnLoading"); if (((message = dlerror()) == NULL) && (onloading != NULL)) { if (pthread_mutex_unlock(&mutex) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return(NULL); } rpl_arguments.l_base_pile = (*s_etat_processus).l_base_pile; rpl_arguments.l_base_pile_last = (*s_etat_processus).l_base_pile_last; for(i = 0; i < 8; i++) { rpl_arguments.drapeaux_etat[i] = (*s_etat_processus).drapeaux_etat[i]; } rpl_arguments.message_erreur = NULL; rpl_arguments.type_erreur = 'E'; rpl_arguments.erreur = 0; rpl_arguments.aide = ((*s_etat_processus).affichage_arguments == 'N') ? d_faux : d_vrai; rpl_arguments.affichage_arguments = (*s_etat_processus) .affichage_arguments; rpl_arguments.test_instruction = (*s_etat_processus).test_instruction; rpl_arguments.constante_symbolique = (*s_etat_processus) .constante_symbolique; rpl_arguments.instruction_valide = 'N'; rpl_arguments.s_etat_processus = s_etat_processus; (*s_etat_processus).erreur_execution = d_ex; if ((*s_etat_processus).profilage == d_vrai) { if ((tampon = malloc((strlen(bibliotheque) + 14) * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } sprintf(tampon, "%s$runOnLoading", bibliotheque); profilage(s_etat_processus, tampon); free(tampon); if ((*s_etat_processus).erreur_systeme != d_es) { return(NULL); } } # ifndef SEMAPHORES_NOMMES if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0) # else if (sem_post((*s_etat_processus).semaphore_fork) != 0) # endif { (*s_etat_processus).erreur_systeme = d_es_processus; return(NULL); } (*onloading)(&rpl_arguments, descripteur_bibliotheque); # ifndef SEMAPHORES_NOMMES while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0) # else while(sem_wait((*s_etat_processus).semaphore_fork) != 0) # endif { if (errno != EINTR) { (*s_etat_processus).erreur_systeme = d_es_processus; return(NULL); } } if ((*s_etat_processus).profilage == d_vrai) { profilage(s_etat_processus, NULL); } (*s_etat_processus).nombre_arguments = rpl_arguments.nombre_arguments; (*s_etat_processus).constante_symbolique = rpl_arguments .constante_symbolique; (*s_etat_processus).instruction_valide = rpl_arguments .instruction_valide; if ((*s_etat_processus).test_instruction == 'Y') { if ((*s_etat_processus).nombre_arguments == 0) { (*s_etat_processus).nombre_arguments = -1; } } if (rpl_arguments.erreur != 0) { if (((*s_etat_processus).arret_si_exception == d_vrai) || (rpl_arguments.type_erreur == 'S')) { if (test_cfsf(s_etat_processus, 51) == d_faux) { printf("%s", ds_beep); } if (rpl_arguments.type_erreur == 'S') { (*s_etat_processus).derniere_erreur_execution = -1; if ((*s_etat_processus).langue == 'F') { printf("+++Système : Fonction dynamique %s " "(ligne %lld)\n", "onLoading", rpl_arguments.erreur); } else { printf("+++System : %s dynamic function (line %lld)\n", "onLoading", rpl_arguments.erreur); } } else { (*s_etat_processus).derniere_erreur_systeme = -1; if ((*s_etat_processus).langue == 'F') { printf("+++Erreur : Fonction dynamique %s " "(ligne %lld)\n", "onLoading" , rpl_arguments.erreur); } else { printf("+++Error : %s dynamic function (line %lld)\n", "onLoading", rpl_arguments.erreur); } } if (rpl_arguments.message_erreur != NULL) { printf("%s\n", rpl_arguments.message_erreur); } fflush(stdout); } if (rpl_arguments.type_erreur == 'S') { (*s_etat_processus).erreur_systeme = d_es_execution_bibliotheque; } else { (*s_etat_processus).erreur_execution = d_ex_execution_bibliotheque; } } (*s_etat_processus).l_base_pile = rpl_arguments.l_base_pile; (*s_etat_processus).l_base_pile_last = rpl_arguments.l_base_pile_last; for(i = 0; i < 8; i++) { (*s_etat_processus).drapeaux_etat[i] = rpl_arguments.drapeaux_etat[i]; } l_element_courant = (*s_etat_processus).l_base_pile; (*s_etat_processus).hauteur_pile_operationnelle = 0; while(l_element_courant != NULL) { (*s_etat_processus).hauteur_pile_operationnelle++; l_element_courant = (*l_element_courant).suivant; } } else { printf("%s\n", message); if (pthread_mutex_unlock(&mutex) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return(NULL); } } if (pthread_mutex_lock(&mutex) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return(NULL); } dlerror(); fonction = dlsym(descripteur_bibliotheque, "___external_symbols"); if (fonction == NULL) { if ((message = dlerror()) != NULL) { printf("%s\n", message); if (pthread_mutex_unlock(&mutex) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return(NULL); } (*s_etat_processus).erreur_execution = d_ex_erreur_bibliotheque; return(NULL); } } dlerror(); if (pthread_mutex_unlock(&mutex) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return(NULL); } /* * Ajout des symboles externes */ if ((tableau = (unsigned char **) (*fonction)(&rpl_arguments, (&nombre_symboles), d_version_rpl)) == NULL) { /* * Nombre symboles : * 0 : aucun symbole exporté * >0 : nombre de symboles exportés * -1 : version de bibliothèque incompatible */ if (nombre_symboles == 0) { (*s_etat_processus).erreur_execution = d_ex_aucun_symbole; } else if (nombre_symboles == -1) { (*s_etat_processus).erreur_execution = d_ex_version_bibliotheque; } else { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; } return(NULL); } if (((*s_etat_processus).s_instructions_externes = realloc( (*s_etat_processus).s_instructions_externes, ((size_t) ((*s_etat_processus).nombre_instructions_externes + nombre_symboles)) * sizeof(struct_instruction_externe))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } for(i = 0; i < nombre_symboles; i++) { if ((fleche = strstr(tableau[i], "->")) != NULL) { memcpy(fleche, "to", 2); (*s_etat_processus).s_instructions_externes[(*s_etat_processus) .nombre_instructions_externes].position_fleche = fleche - tableau[i]; } else { (*s_etat_processus).s_instructions_externes[(*s_etat_processus) .nombre_instructions_externes].position_fleche = -1; } (*s_etat_processus).s_instructions_externes[(*s_etat_processus) .nombre_instructions_externes].descripteur_bibliotheque = descripteur_bibliotheque; if (((*s_etat_processus).s_instructions_externes[(*s_etat_processus) .nombre_instructions_externes].nom = malloc((strlen(index(tableau[i], '$') + 1) + 1) * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } strcpy((*s_etat_processus).s_instructions_externes[(*s_etat_processus) .nombre_instructions_externes].nom, index(tableau[i], '$') + 1); *(index(tableau[i], '$')) = d_code_fin_chaine; if (((*s_etat_processus).s_instructions_externes[(*s_etat_processus) .nombre_instructions_externes].nom_bibliotheque = malloc( (strlen(tableau[i]) + 1) * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } strcpy((*s_etat_processus).s_instructions_externes[(*s_etat_processus) .nombre_instructions_externes].nom_bibliotheque, tableau[i]); (*s_etat_processus).nombre_instructions_externes++; free(tableau[i]); } /* * Ajout de la nouvelle bibliothèque */ if ((l_nouvel_element = (struct_liste_chainee *) malloc(sizeof(struct_liste_chainee))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } if (((*l_nouvel_element).donnee = malloc(sizeof(struct_bibliotheque))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } (*((struct_bibliotheque *) (*l_nouvel_element).donnee)).descripteur = descripteur_bibliotheque; (*((struct_bibliotheque *) (*l_nouvel_element).donnee)).pid = getpid(); (*((struct_bibliotheque *) (*l_nouvel_element).donnee)).tid = pthread_self(); if (((*((struct_bibliotheque *) (*l_nouvel_element).donnee)).nom = malloc((strlen((*s_etat_processus).s_instructions_externes [(*s_etat_processus).nombre_instructions_externes - 1] .nom_bibliotheque) + 1) * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } strcpy((*((struct_bibliotheque *) (*l_nouvel_element).donnee)).nom, (*s_etat_processus).s_instructions_externes [(*s_etat_processus).nombre_instructions_externes - 1] .nom_bibliotheque); // La nouvelle bibliothèque est mise en tête de la liste pour que // les bibliothèques soient implicitement déchargées dans l'ordre // inverse de leur chargement. (*l_nouvel_element).suivant = (*s_etat_processus).s_bibliotheques; (*s_etat_processus).s_bibliotheques = l_nouvel_element; tri_base_symboles_externes(s_etat_processus); free(tableau); return(descripteur_bibliotheque); } /* ================================================================================ Procédure de retrait d'une bibliothèque dynamique ================================================================================ Entrée : -------------------------------------------------------------------------------- Sortie : -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ logical1 retrait_bibliotheque(struct_processus *s_etat_processus, struct_bibliotheque *descripteur) { char *message; logical1 presence_bibliotheque; struct_instruction_externe *registre; struct_liste_chainee *l_element_courant; struct_liste_chainee *l_element_precedent; struct_rpl_arguments rpl_arguments; unsigned char *tampon; integer8 i; integer8 j; integer8 nombre_symboles_residuels; int (*onclosing)(struct_rpl_arguments *, void *); l_element_courant = (*s_etat_processus).s_bibliotheques; presence_bibliotheque = d_faux; l_element_precedent = NULL; /* * Recherche de la bibliothèque à supprimer */ while(l_element_courant != NULL) { if (((*((struct_bibliotheque *) (*l_element_courant).donnee)) .descripteur == (*descripteur).descripteur) && ((*((struct_bibliotheque *) (*l_element_courant).donnee)).pid == getpid()) && (pthread_equal((*((struct_bibliotheque *) (*l_element_courant).donnee)).tid, pthread_self()) != 0)) { presence_bibliotheque = d_vrai; break; } l_element_precedent = l_element_courant; l_element_courant = (*l_element_courant).suivant; } if (presence_bibliotheque == d_vrai) { if (pthread_mutex_lock(&mutex) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return(d_erreur); } dlerror(); onclosing = dlsym((*descripteur).descripteur, "__runOnClosing"); if (((message = dlerror()) == NULL) && (onclosing != NULL)) { if (pthread_mutex_unlock(&mutex) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return(d_erreur); } rpl_arguments.l_base_pile = (*s_etat_processus).l_base_pile; rpl_arguments.l_base_pile_last = (*s_etat_processus).l_base_pile_last; for(i = 0; i < 8; i++) { rpl_arguments.drapeaux_etat[i] = (*s_etat_processus).drapeaux_etat[i]; } rpl_arguments.message_erreur = NULL; rpl_arguments.type_erreur = 'E'; rpl_arguments.erreur = 0; rpl_arguments.aide = ((*s_etat_processus).affichage_arguments == 'N') ? d_faux : d_vrai; rpl_arguments.affichage_arguments = (*s_etat_processus) .affichage_arguments; rpl_arguments.test_instruction = (*s_etat_processus).test_instruction; rpl_arguments.constante_symbolique = (*s_etat_processus) .constante_symbolique; rpl_arguments.instruction_valide = 'N'; rpl_arguments.s_etat_processus = s_etat_processus; (*s_etat_processus).erreur_execution = d_ex; if ((*s_etat_processus).profilage == d_vrai) { if ((tampon = malloc((strlen((*descripteur).nom) + 14) * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(d_erreur); } sprintf(tampon, "%s$runOnClosing", (*descripteur).nom); profilage(s_etat_processus, tampon); free(tampon); if ((*s_etat_processus).erreur_systeme != d_es) { return(d_erreur); } } # ifndef SEMAPHORES_NOMMES if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0) # else if (sem_post((*s_etat_processus).semaphore_fork) != 0) # endif { (*s_etat_processus).erreur_systeme = d_es_processus; return(d_erreur); } (*onclosing)(&rpl_arguments, (*descripteur).descripteur); # ifndef SEMAPHORES_NOMMES while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0) # else while(sem_wait((*s_etat_processus).semaphore_fork) != 0) # endif { if (errno != EINTR) { (*s_etat_processus).erreur_systeme = d_es_processus; return(d_erreur); } } if ((*s_etat_processus).profilage == d_vrai) { profilage(s_etat_processus, NULL); } (*s_etat_processus).nombre_arguments = rpl_arguments.nombre_arguments; (*s_etat_processus).constante_symbolique = rpl_arguments .constante_symbolique; (*s_etat_processus).instruction_valide = rpl_arguments .instruction_valide; if ((*s_etat_processus).test_instruction == 'Y') { if ((*s_etat_processus).nombre_arguments == 0) { (*s_etat_processus).nombre_arguments = -1; } } if (rpl_arguments.erreur != 0) { if (((*s_etat_processus).arret_si_exception == d_vrai) || (rpl_arguments.type_erreur == 'S')) { if (test_cfsf(s_etat_processus, 51) == d_faux) { printf("%s", ds_beep); } if (rpl_arguments.type_erreur == 'S') { (*s_etat_processus).derniere_erreur_execution = -1; if ((*s_etat_processus).langue == 'F') { printf("+++Système : Fonction dynamique " "%s (ligne %lld)\n", "onClosing" , rpl_arguments.erreur); } else { printf("+++System : %s dynamic function " "(line %lld)\n", "onClosing", rpl_arguments.erreur); } } else { (*s_etat_processus).derniere_erreur_systeme = -1; if ((*s_etat_processus).langue == 'F') { printf("+++Erreur : Fonction dynamique %s " "(ligne %lld)\n", "onClosing", rpl_arguments.erreur); } else { printf("+++Error : %s dynamic function " "(line %lld)\n", "onClosing", rpl_arguments.erreur); } } if (rpl_arguments.message_erreur != NULL) { printf("%s\n", rpl_arguments.message_erreur); } fflush(stdout); } if (rpl_arguments.type_erreur == 'S') { (*s_etat_processus).erreur_systeme = d_es_execution_bibliotheque; } else { (*s_etat_processus).erreur_execution = d_ex_execution_bibliotheque; } } (*s_etat_processus).l_base_pile = rpl_arguments.l_base_pile; (*s_etat_processus).l_base_pile_last = rpl_arguments.l_base_pile_last; for(i = 0; i < 8; i++) { (*s_etat_processus).drapeaux_etat[i] = rpl_arguments.drapeaux_etat[i]; } l_element_courant = (*s_etat_processus).l_base_pile; (*s_etat_processus).hauteur_pile_operationnelle = 0; while(l_element_courant != NULL) { (*s_etat_processus).hauteur_pile_operationnelle++; l_element_courant = (*l_element_courant).suivant; } } else { printf("%s\n", message); if (pthread_mutex_unlock(&mutex) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return(d_erreur); } } /* * Retrait de la bibliothèque de la pile */ dlclose((*descripteur).descripteur); l_element_courant = (*s_etat_processus).s_bibliotheques; while(l_element_courant != NULL) { if ((*((struct_bibliotheque *) (*l_element_courant).donnee)) .descripteur == (*descripteur).descripteur) { break; } l_element_precedent = l_element_courant; l_element_courant = (*l_element_courant).suivant; } if (l_element_precedent == NULL) { (*s_etat_processus).s_bibliotheques = (*l_element_courant).suivant; } else { (*l_element_precedent).suivant = (*l_element_courant).suivant; } free((*((struct_bibliotheque *) (*l_element_courant).donnee)).nom); free((*l_element_courant).donnee); free(l_element_courant); /* * Retrait des symboles associés à la bibliothèque */ nombre_symboles_residuels = 0; for(i = 0; i < (*s_etat_processus).nombre_instructions_externes; i++) { if ((*s_etat_processus).s_instructions_externes[i] .descripteur_bibliotheque != (*descripteur).descripteur) { nombre_symboles_residuels++; } } if (nombre_symboles_residuels == 0) { for(i = 0; i < (*s_etat_processus).nombre_instructions_externes; i++) { free((*s_etat_processus).s_instructions_externes[i].nom); free((*s_etat_processus).s_instructions_externes[i] .nom_bibliotheque); } free((*s_etat_processus).s_instructions_externes); (*s_etat_processus).s_instructions_externes = NULL; } else { registre = (*s_etat_processus).s_instructions_externes; if (((*s_etat_processus).s_instructions_externes = malloc(((size_t) nombre_symboles_residuels) * sizeof(struct_instruction_externe))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(d_erreur); } for(i = j = 0; i < (*s_etat_processus).nombre_instructions_externes; i++) { if (registre[i].descripteur_bibliotheque != (*descripteur).descripteur) { (*s_etat_processus).s_instructions_externes[j].nom = registre[i].nom; (*s_etat_processus).s_instructions_externes[j] .nom_bibliotheque = registre[i].nom_bibliotheque; (*s_etat_processus).s_instructions_externes[j] .descripteur_bibliotheque = registre[i] .descripteur_bibliotheque; j++; } else { free(registre[i].nom); free(registre[i].nom_bibliotheque); } } free(registre); } (*s_etat_processus).nombre_instructions_externes = nombre_symboles_residuels; return(d_absence_erreur); } else { (*s_etat_processus).erreur_execution = d_ex_erreur_bibliotheque; return(d_erreur); } } /* ================================================================================ Procédure d'exécution d'une fonction d'une bibliothèque ================================================================================ Entrée : -------------------------------------------------------------------------------- Sortie : -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ logical1 execution_fonction_de_bibliotheque(struct_processus *s_etat_processus, unsigned char *nom_fonction, unsigned char *bibliotheque) { logical1 presence_bibliotheque; logical1 unicite_symbole; int difference; int difference_inferieure; int difference_superieure; struct_liste_chainee *l_element_courant; struct_rpl_arguments rpl_arguments; unsigned char *fleche; unsigned char *nom_fonction_externe; unsigned char *tampon; integer8 borne_inferieure; integer8 borne_superieure; integer8 i; integer8 moyenne; integer8 nombre_iterations_maximal; integer8 ordre_iteration; int (*fonction)(struct_rpl_arguments *); /* * Recherche dichotomique de la définition externe */ if ((*s_etat_processus).nombre_instructions_externes == 0) { return(d_faux); } if (bibliotheque != NULL) { presence_bibliotheque = d_faux; l_element_courant = (*s_etat_processus).s_bibliotheques; while(l_element_courant != NULL) { if (strcmp((*((struct_bibliotheque *) (*l_element_courant).donnee)) .nom, bibliotheque) == 0) { presence_bibliotheque = d_vrai; break; } l_element_courant = (*l_element_courant).suivant; } if (presence_bibliotheque == d_faux) { return(d_faux); } } if ((fleche = strstr(nom_fonction, "->")) != NULL) { memcpy(fleche, "to", 2); } ordre_iteration = 0; nombre_iterations_maximal = ((integer8) (log((real8) (*s_etat_processus).nombre_instructions_externes) / log(2))) + 2; borne_inferieure = 0; borne_superieure = (*s_etat_processus).nombre_instructions_externes - 1; do { moyenne = (borne_inferieure + borne_superieure) / 2; ordre_iteration++; if ((2 * ((integer8) ((borne_inferieure + borne_superieure) / 2))) == (borne_inferieure + borne_superieure)) { difference = strcmp(nom_fonction, (*s_etat_processus) .s_instructions_externes[moyenne].nom); if (difference != 0) { if (difference > 0) { borne_inferieure = moyenne; } else { borne_superieure = moyenne; } } } else { difference_inferieure = strcmp(nom_fonction, (*s_etat_processus).s_instructions_externes[moyenne].nom); difference_superieure = strcmp(nom_fonction, (*s_etat_processus).s_instructions_externes[moyenne + 1] .nom); if (difference_inferieure == 0) { difference = 0; } else if (difference_superieure == 0) { difference = 0; moyenne++; } else { difference = difference_inferieure; if (difference > 0) { borne_inferieure = moyenne; } else { borne_superieure = moyenne; } } } } while((difference != 0) && (ordre_iteration <= nombre_iterations_maximal)); if (ordre_iteration > nombre_iterations_maximal) { return(d_faux); } if (bibliotheque != NULL) { // Nom de la bibliothèque spécifié if (strcmp((*s_etat_processus).s_instructions_externes[moyenne] .nom_bibliotheque, bibliotheque) > 0) { i = moyenne; while(i >= 0) { if (strcmp((*s_etat_processus).s_instructions_externes[i] .nom, nom_fonction) != 0) { break; } else if (strcmp((*s_etat_processus).s_instructions_externes[i] .nom_bibliotheque, bibliotheque) == 0) { break; } i--; } moyenne = i; } else if (strcmp((*s_etat_processus).s_instructions_externes[moyenne] .nom_bibliotheque, bibliotheque) < 0) { i = moyenne; while(i < (*s_etat_processus).nombre_instructions_externes) { if (strcmp((*s_etat_processus).s_instructions_externes[i] .nom, nom_fonction) != 0) { break; } else if (strcmp((*s_etat_processus).s_instructions_externes[i] .nom_bibliotheque, bibliotheque) == 0) { break; } i++; } moyenne = i; } } else { // Nom de la bibliothèque non spécifié /* * Vérification de l'unicité du symbole */ unicite_symbole = d_vrai; if (moyenne > 0) { if (strcmp((*s_etat_processus).s_instructions_externes [moyenne - 1].nom, nom_fonction) == 0) { unicite_symbole = d_faux; } } if ((moyenne + 1) < (*s_etat_processus) .nombre_instructions_externes) { if (strcmp((*s_etat_processus).s_instructions_externes [moyenne + 1].nom, nom_fonction) == 0) { unicite_symbole = d_faux; } } if (unicite_symbole == d_faux) { (*s_etat_processus).erreur_execution = d_ex_definition_ambigue; return(d_faux); } } if ((nom_fonction_externe = malloc((strlen(nom_fonction) + 12) * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(d_faux); } sprintf(nom_fonction_externe, "__external_%s", nom_fonction); if (pthread_mutex_lock(&mutex) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return(d_faux); } dlerror(); fonction = dlsym((*s_etat_processus).s_instructions_externes [moyenne].descripteur_bibliotheque, nom_fonction_externe); free(nom_fonction_externe); /* * Vérification de la présence du symbole */ if (fonction == NULL) { if (dlerror() != NULL) { if (pthread_mutex_unlock(&mutex) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return(d_faux); } return(d_faux); } } dlerror(); if (pthread_mutex_unlock(&mutex) != 0) { (*s_etat_processus).erreur_systeme = d_es_processus; return(d_faux); } /* * Exécution de la fonction externe */ rpl_arguments.l_base_pile = (*s_etat_processus).l_base_pile; rpl_arguments.l_base_pile_last = (*s_etat_processus).l_base_pile_last; for(i = 0; i < 8; i++) { rpl_arguments.drapeaux_etat[i] = (*s_etat_processus).drapeaux_etat[i]; } rpl_arguments.message_erreur = NULL; rpl_arguments.type_erreur = 'E'; rpl_arguments.erreur = 0; rpl_arguments.aide = ((*s_etat_processus).affichage_arguments == 'N') ? d_faux : d_vrai; rpl_arguments.affichage_arguments = (*s_etat_processus) .affichage_arguments; rpl_arguments.test_instruction = (*s_etat_processus).test_instruction; rpl_arguments.constante_symbolique = (*s_etat_processus) .constante_symbolique; rpl_arguments.instruction_valide = 'N'; rpl_arguments.s_etat_processus = s_etat_processus; (*s_etat_processus).erreur_execution = d_ex; if ((*s_etat_processus).profilage == d_vrai) { if ((tampon = malloc(strlen((*s_etat_processus) .s_instructions_externes[moyenne].nom_bibliotheque) + strlen(nom_fonction) + 2)) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(d_faux); } sprintf(tampon, "%s$%s", (*s_etat_processus).s_instructions_externes [moyenne].nom_bibliotheque, nom_fonction); profilage(s_etat_processus, tampon); free(tampon); if ((*s_etat_processus).erreur_systeme != d_es) { return(d_faux); } } # ifndef SEMAPHORES_NOMMES if (sem_post(&((*s_etat_processus).semaphore_fork)) != 0) # else if (sem_post((*s_etat_processus).semaphore_fork) != 0) # endif { (*s_etat_processus).erreur_systeme = d_es_processus; return(d_faux); } (*fonction)(&rpl_arguments); # ifndef SEMAPHORES_NOMMES while(sem_wait(&((*s_etat_processus).semaphore_fork)) != 0) # else while(sem_wait((*s_etat_processus).semaphore_fork) != 0) # endif { if (errno != EINTR) { (*s_etat_processus).erreur_systeme = d_es_processus; return(d_faux); } } if ((*s_etat_processus).profilage == d_vrai) { profilage(s_etat_processus, NULL); } (*s_etat_processus).nombre_arguments = rpl_arguments.nombre_arguments; (*s_etat_processus).constante_symbolique = rpl_arguments .constante_symbolique; (*s_etat_processus).instruction_valide = rpl_arguments .instruction_valide; if ((*s_etat_processus).test_instruction == 'Y') { if ((*s_etat_processus).nombre_arguments == 0) { (*s_etat_processus).nombre_arguments = -1; } } if (rpl_arguments.erreur != 0) { if (((*s_etat_processus).arret_si_exception == d_vrai) || (rpl_arguments.type_erreur == 'S')) { if (test_cfsf(s_etat_processus, 51) == d_faux) { printf("%s", ds_beep); } if (rpl_arguments.type_erreur == 'S') { (*s_etat_processus).derniere_erreur_execution = -1; if ((*s_etat_processus).langue == 'F') { printf("+++Système : Fonction dynamique %s (ligne %lld)\n", nom_fonction, rpl_arguments.erreur); } else { printf("+++System : %s dynamic function (line %lld)\n", nom_fonction, rpl_arguments.erreur); } } else { (*s_etat_processus).derniere_erreur_systeme = -1; if ((*s_etat_processus).langue == 'F') { printf("+++Erreur : Fonction dynamique %s (ligne %lld)\n", nom_fonction, rpl_arguments.erreur); } else { printf("+++Error : %s dynamic function (line %lld)\n", nom_fonction, rpl_arguments.erreur); } } if (rpl_arguments.message_erreur != NULL) { printf("%s\n", rpl_arguments.message_erreur); } fflush(stdout); } if (rpl_arguments.type_erreur == 'S') { (*s_etat_processus).erreur_systeme = d_es_execution_bibliotheque; } else { (*s_etat_processus).erreur_execution = d_ex_execution_bibliotheque; } } (*s_etat_processus).l_base_pile = rpl_arguments.l_base_pile; (*s_etat_processus).l_base_pile_last = rpl_arguments.l_base_pile_last; for(i = 0; i < 8; i++) { (*s_etat_processus).drapeaux_etat[i] = rpl_arguments.drapeaux_etat[i]; } l_element_courant = (*s_etat_processus).l_base_pile; (*s_etat_processus).hauteur_pile_operationnelle = 0; while(l_element_courant != NULL) { (*s_etat_processus).hauteur_pile_operationnelle++; l_element_courant = (*l_element_courant).suivant; } #undef return return(d_vrai); } /* ================================================================================ Wrapper vers une fonction intrinsèque ================================================================================ Entrée : -------------------------------------------------------------------------------- Sortie : -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ int wrapper_instruction_intrinseque(void (*fonction)(), struct_rpl_arguments *rpl_arguments) { int i; logical1 registre31; struct_liste_chainee *l_element_courant; struct_processus *s_etat_processus; s_etat_processus = (*rpl_arguments).s_etat_processus; (*s_etat_processus).nombre_arguments = (*rpl_arguments).nombre_arguments; (*s_etat_processus).constante_symbolique = (*rpl_arguments) .constante_symbolique; (*s_etat_processus).instruction_valide = (*rpl_arguments) .instruction_valide; (*s_etat_processus).l_base_pile = (*rpl_arguments).l_base_pile; (*s_etat_processus).l_base_pile_last = (*rpl_arguments).l_base_pile_last; for(i = 0; i < 8; i++) { (*s_etat_processus).drapeaux_etat[i] = (*rpl_arguments).drapeaux_etat[i]; } l_element_courant = (*s_etat_processus).l_base_pile; (*s_etat_processus).hauteur_pile_operationnelle = 0; while(l_element_courant != NULL) { (*s_etat_processus).hauteur_pile_operationnelle++; l_element_courant = (*l_element_courant).suivant; } registre31 = test_cfsf(s_etat_processus, 31); cf(s_etat_processus, 31); (*fonction)(s_etat_processus); if (registre31 == d_vrai) { sf(s_etat_processus, 31); } else { cf(s_etat_processus, 31); } (*rpl_arguments).l_base_pile = (*s_etat_processus).l_base_pile; (*rpl_arguments).l_base_pile_last = (*s_etat_processus).l_base_pile_last; for(i = 0; i < 8; i++) { (*rpl_arguments).drapeaux_etat[i] = (*s_etat_processus).drapeaux_etat[i]; } (*rpl_arguments).message_erreur = NULL; (*rpl_arguments).type_erreur = 'E'; (*rpl_arguments).erreur = 0; (*rpl_arguments).aide = ((*s_etat_processus).affichage_arguments == 'N') ? d_faux : d_vrai; (*rpl_arguments).affichage_arguments = (*s_etat_processus) .affichage_arguments; (*rpl_arguments).test_instruction = (*s_etat_processus).test_instruction; (*rpl_arguments).constante_symbolique = (*s_etat_processus) .constante_symbolique; (*rpl_arguments).instruction_valide = 'Y'; (*rpl_arguments).s_etat_processus = s_etat_processus; if (((*s_etat_processus).erreur_execution != d_ex) || ((*s_etat_processus).exception != d_ep)) { return(1); } if ((*s_etat_processus).erreur_systeme != d_es) { return(2); } (*s_etat_processus).erreur_execution = d_ex; (*s_etat_processus).erreur_systeme = d_es; (*s_etat_processus).exception = d_ep; return(0); } /* ================================================================================ Procédure d'empilement d'un nouvel élément ================================================================================ Entrée : -------------------------------------------------------------------------------- Sortie : -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ struct_liste_chainee * empilement_pile_operationnelle(struct_rpl_arguments *s_rpl_arguments, struct_objet *s_objet) { # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wunused-but-set-variable" struct_liste_chainee *l_ancienne_base_liste; struct_liste_chainee *l_nouvelle_base_liste; struct_processus *s_etat_processus; l_ancienne_base_liste = (*s_rpl_arguments).l_base_pile; s_etat_processus = (*s_rpl_arguments).s_etat_processus; l_nouvelle_base_liste = (struct_liste_chainee *) malloc( sizeof(struct_liste_chainee)); if (l_nouvelle_base_liste != NULL) { (*l_nouvelle_base_liste).donnee = s_objet; (*l_nouvelle_base_liste).suivant = l_ancienne_base_liste; } (*s_rpl_arguments).l_base_pile = l_nouvelle_base_liste; return l_nouvelle_base_liste; # pragma GCC diagnostic pop } /* ================================================================================ 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 ================================================================================ */ struct_liste_chainee * depilement_pile_operationnelle(struct_rpl_arguments *s_rpl_arguments, struct_objet **s_objet) { # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wunused-but-set-variable" struct_liste_chainee *l_ancienne_base_liste; struct_liste_chainee *l_nouvelle_base_liste; struct_processus *s_etat_processus; if ((*s_rpl_arguments).l_base_pile == NULL) { *s_objet = NULL; return NULL ; } else { l_ancienne_base_liste = (*s_rpl_arguments).l_base_pile; l_nouvelle_base_liste = (*l_ancienne_base_liste).suivant; s_etat_processus = (*s_rpl_arguments).s_etat_processus; *s_objet = (*l_ancienne_base_liste).donnee; free(l_ancienne_base_liste); (*s_rpl_arguments).l_base_pile = l_nouvelle_base_liste; return l_nouvelle_base_liste ; } # pragma GCC diagnostic pop } /* ================================================================================ Procédure de sauvegarde des arguments dans la pile last ================================================================================ Entrée : structure processus et nombre d'aguments à empiler -------------------------------------------------------------------------------- Sortie : drapeau d'erreur de la structure rpl_arguments -------------------------------------------------------------------------------- Effets de bord : efface le précédent contenu de la pile LAST ================================================================================ */ struct_liste_chainee * sauvegarde_arguments(struct_rpl_arguments *s_rpl_arguments, integer8 nombre_arguments) { struct_liste_chainee *l_ancienne_base_liste; struct_liste_chainee *l_element_courant; struct_liste_chainee *l_element_suivant; struct_liste_chainee *l_nouvelle_base_liste; struct_objet *s_objet; logical1 erreur; t_8_bits masque; unsigned char indice_bit; unsigned char indice_bloc; unsigned char indice_drapeau; unsigned char taille_bloc; integer8 i; struct_processus *s_etat_processus; (*s_rpl_arguments).erreur = 0; s_etat_processus = (*s_rpl_arguments).s_etat_processus; indice_drapeau = 31; indice_drapeau--; taille_bloc = sizeof(t_8_bits) * 8; indice_bloc = indice_drapeau / taille_bloc; indice_bit = indice_drapeau % taille_bloc; masque = (t_8_bits) ((1 << (taille_bloc - indice_bit - 1)) & 0xFF); if (((*s_rpl_arguments).drapeaux_etat[indice_bloc] & masque) == 0) { return (*s_rpl_arguments).l_base_pile_last; } erreur = d_absence_erreur; l_element_courant = (*s_rpl_arguments).l_base_pile_last; while(l_element_courant != NULL) { liberation(s_etat_processus, (*l_element_courant).donnee); l_element_suivant = (*l_element_courant).suivant; free(l_element_courant); l_element_courant = l_element_suivant; } (*s_rpl_arguments).l_base_pile_last = NULL; l_element_courant = (*s_rpl_arguments).l_base_pile; l_nouvelle_base_liste = (*s_rpl_arguments).l_base_pile_last; for(i = 0; ((i < nombre_arguments) && (erreur == d_absence_erreur) && (l_element_courant != NULL)); i++) { s_objet = copie_objet(s_etat_processus, (*l_element_courant).donnee, 'P'); if (s_objet != NULL) { l_ancienne_base_liste = l_nouvelle_base_liste; l_nouvelle_base_liste = (struct_liste_chainee *) malloc( sizeof(struct_liste_chainee)); if (l_nouvelle_base_liste != NULL) { (*l_nouvelle_base_liste).donnee = s_objet; (*l_nouvelle_base_liste).suivant = l_ancienne_base_liste; } else { erreur = d_erreur; } l_element_courant = (*l_element_courant).suivant; } else { erreur = d_erreur; } } if (i != nombre_arguments) { /* * Erreur système : la pile est vidée et la routine renvoie NULL. */ l_element_courant = l_nouvelle_base_liste; while(l_element_courant != NULL) { liberation(s_etat_processus, (*l_element_courant).donnee); l_element_suivant = (*l_element_courant).suivant; free(l_element_courant); l_element_courant = l_element_suivant; } l_nouvelle_base_liste = NULL; (*s_rpl_arguments).erreur = i; } return(l_nouvelle_base_liste); } /* ================================================================================ Procédure de tri des symboles externes Principe du tri dit de Shell-Metzner ================================================================================ Entrée : -------------------------------------------------------------------------------- Sortie : -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ void tri_base_symboles_externes(struct_processus *s_etat_processus) { logical1 terminaison_boucle; logical1 terminaison_boucle_1; logical1 terminaison_boucle_2; logical1 terminaison_boucle_3; integer8 borne_inferieure; integer8 borne_superieure; integer8 ecartement; integer8 indice; integer8 indice_i; integer8 indice_j; integer8 indice_k; integer8 indice_l; ecartement = (*s_etat_processus).nombre_instructions_externes; terminaison_boucle_1 = d_faux; do { ecartement = ecartement / 2; if (ecartement >= 1) { indice_j = 0; indice_k = (*s_etat_processus).nombre_instructions_externes - ecartement; terminaison_boucle_2 = d_faux; do { indice_i = indice_j; terminaison_boucle_3 = d_faux; do { indice_l = indice_i + ecartement; if ((indice_i > 0) && (indice_l > 0)) { if (strcmp(((*s_etat_processus).s_instructions_externes [indice_i - 1]).nom, ((*s_etat_processus) .s_instructions_externes[indice_l - 1]).nom) > 0) { swap((void *) &((*s_etat_processus) .s_instructions_externes [indice_i - 1]), (void *) &((*s_etat_processus) .s_instructions_externes[indice_l - 1]), sizeof(struct_instruction_externe)); indice_i -= ecartement; if (indice_i < 1) { terminaison_boucle_3 = d_vrai; } } else { terminaison_boucle_3 = d_vrai; } } else { terminaison_boucle_3 = d_vrai; } } while(terminaison_boucle_3 == d_faux); indice_j++; if (indice_j > indice_k) { terminaison_boucle_2 = d_vrai; } } while(terminaison_boucle_2 == d_faux); } else { terminaison_boucle_1 = d_vrai; } } while(terminaison_boucle_1 == d_faux); indice_i = 0; do { indice_j = indice_i; while(((indice_i + 1) < (*s_etat_processus) .nombre_instructions_externes) && (strcmp(((*s_etat_processus) .s_instructions_externes[indice_i]).nom, ((*s_etat_processus) .s_instructions_externes[indice_i + 1]).nom) == 0)) { indice_i++; } borne_inferieure = indice_j; borne_superieure = indice_i; do { terminaison_boucle = d_vrai; for(indice = borne_inferieure + 1; indice <= borne_superieure; indice++) { if (strcmp((*s_etat_processus).s_instructions_externes[indice] .nom_bibliotheque, (*s_etat_processus) .s_instructions_externes[indice - 1].nom_bibliotheque) < 0) { swap((void *) &((*s_etat_processus).s_instructions_externes [indice - 1]), (void *) &((*s_etat_processus) .s_instructions_externes[indice]), sizeof(struct_instruction_externe)); terminaison_boucle = d_faux; } } } while(terminaison_boucle == d_faux); indice_i++; } while((indice_i + 1) < (*s_etat_processus).nombre_instructions_externes); return; } // vim: ts=4