--- rpl/src/rpl.h 2015/04/14 11:26:47 1.269 +++ rpl/src/rpl.h 2019/02/07 21:44:15 1.328 @@ -1,7 +1,7 @@ /* ================================================================================ - RPL/2 (R) version 4.1.21 - Copyright (C) 1989-2015 Dr. BERTRAND Joël + RPL/2 (R) version 4.1.31 + Copyright (C) 1989-2019 Dr. BERTRAND Joël This file is part of RPL/2. @@ -18,7 +18,8 @@ along with RPL/2. If not, write to info@cecill.info. ================================================================================ */ - +#define DEBUG_ERREURS +#define DEBUG_SEMAPHORES #ifndef INCLUSION_RPL #define INCLUSION_RPL @@ -64,6 +65,16 @@ # define SA_ONSTACK 0 #endif +#ifdef BROKEN_SIGSEGV +# undef HAVE_STACK_OVERFLOW_RECOVERY +# undef HAVE_SIGSEGV_RECOVERY +#endif + +#define DEBUG_TRACE uprintf("[%d/%X] %s(%d)\n", \ + getpid(), pthread_self(), __FILE__, __LINE__); +#define TEST_ABSENCE_FICHIER(nom) \ + { int ios; struct stat *buf; ios = stat(nom, buf); \ + if (ios == 0) BUG(1, uprintf("File %s found!\n", nom)); } /* ================================================================================ @@ -82,10 +93,10 @@ #include #include #include +#include #ifndef RPLARGS # include -# include # include # include # include @@ -94,6 +105,7 @@ # include # include # include +# include # include # include @@ -210,7 +222,11 @@ # endif # include "sqlite3.h" -# include "sigsegv.h" + +# ifndef BROKEN_SIGSEGV +# include "sigsegv.h" +# endif + # ifdef OS2 // Bug de libsigsegv # undef HAVE_STACK_OVERFLOW_RECOVERY @@ -267,6 +283,7 @@ # define __STATIC_MUTEX_INITIALIZATION__ #endif + /* ================================================================================ Bugs spécifiques @@ -326,6 +343,7 @@ typedef struct queue_signaux volatile logical1 requete_arret; pthread_t thread_signaux; + pid_t controle; volatile struct { @@ -380,20 +398,30 @@ union semun # define sem_wait(a) ({ int value; sem_getvalue(a, &value); \ uprintf("[%d-%llu] Semaphore %s (%p) "\ "waiting at %s() " \ - "line #%d\n", (int) getpid(), (unsigned long long) i\ + "line #%d <%d>\n", (int) getpid(), (unsigned long long) i\ pthread_self(), \ - #a, a, __FUNCTION__, __LINE__), fflush(stdout); \ - if (value > 1) BUG(1, uprintf("Value %d\n", value)); \ + #a, a, __FUNCTION__, __LINE__, value), fflush(stdout); \ sem_wait_SysV(a); }) -# define sem_post(a) ({ int value; sem_getvalue(a, &value); \ +# define sem_trywait(a) ({ int value; sem_getvalue(a, &value); \ + uprintf("[%d-%llu] Semaphore %s (%p) "\ + "trywaiting at %s() " \ + "line #%d <%d>\n", (int) getpid(), (unsigned long long) i\ + pthread_self(), \ + #a, a, __FUNCTION__, __LINE__, value), fflush(stdout); \ + sem_trywait_SysV(a); }) +# define sem_post(a) ({ int value; sem_getvalue(a, &value); \ uprintf("[%d-%llu] Semaphore %s (%p) "\ "posting at %s() " \ - "line #%d\n", (int) getpid(), (unsigned long long) \ + "line #%d <%d>\n", (int) getpid(), (unsigned long long) \ pthread_self(), \ - #a, a, __FUNCTION__, __LINE__), fflush(stdout); \ - if (value > 0) BUG(1, uprintf("Value %d\n", value)); \ + #a, a, __FUNCTION__, __LINE__, value), fflush(stdout); \ sem_post_SysV(a); }) -# define sem_destroy(a) ({ int value; sem_getvalue(a, &value); \ +# define sem_destroy(a) ({ int value; sem_getvalue(a, &value); \ + uprintf("[%d-%llu] Semaphore %s (%p) "\ + "destroying at %s() " \ + "line #%d <%d>\n", (int) getpid(), (unsigned long long) \ + pthread_self(), \ + #a, a, __FUNCTION__, __LINE__, value), fflush(stdout); \ if (value == 0) BUG(1, uprintf("Value %d\n", value)); \ sem_destroy_SysV(a); }) # else @@ -414,18 +442,30 @@ union semun # define sem_wait(a) ({ int value; sem_getvalue(a, &value); \ uprintf("[%d-%llu] Semaphore %s (%p) "\ "waiting at %s() " \ - "line #%d\n", (int) getpid(), (unsigned long long) \ + "line #%d <%d>\n", (int) getpid(), (unsigned long long) \ + pthread_self(), \ + #a, a, __FUNCTION__, __LINE__, value), fflush(stdout); \ + sem_wait(a); }) +# define sem_trywait(a) ({ int value; sem_getvalue(a, &value); \ + uprintf("[%d-%llu] Semaphore %s (%p) "\ + "trywaiting at %s() " \ + "line #%d <%d>\n", (int) getpid(), (unsigned long long) \ pthread_self(), \ - #a, a, __FUNCTION__, __LINE__), fflush(stdout); \ - if (value > 1) BUG(1, uprintf("Value %d\n", value)); sem_wait(a); }) + #a, a, __FUNCTION__, __LINE__, value), fflush(stdout); \ + sem_trywait(a); }) # define sem_post(a) ({ int value; sem_getvalue(a, &value); \ uprintf("[%d-%llu] Semaphore %s (%p) "\ "posting at %s() " \ - "line #%d\n", (int) getpid(), (unsigned long long) \ + "line #%d <%d>\n", (int) getpid(), (unsigned long long) \ pthread_self(), \ - #a, a, __FUNCTION__, __LINE__), fflush(stdout); \ - if (value > 0) BUG(1, uprintf("Value %d\n", value)); sem_post(a); }) + #a, a, __FUNCTION__, __LINE__, value), fflush(stdout); \ + sem_post(a); }) # define sem_destroy(a) ({ int value; sem_getvalue(a, &value); \ + uprintf("[%d-%llu] Semaphore %s (%p) "\ + "destroying at %s() " \ + "line #%d <%d>\n", (int) getpid(), (unsigned long long) \ + pthread_self(), \ + #a, a, __FUNCTION__, __LINE__, value), fflush(stdout); \ if (value == 0) BUG(1, uprintf("Value %d\n", value)); \ sem_destroy(a); }) # endif @@ -514,8 +554,7 @@ union semun __EXTERN__ pid_t pid_processus_pere; - __EXTERN__ pthread_mutex_t mutex_liste_threads - __STATIC_MUTEX_INITIALIZATION__; + __EXTERN__ pthread_mutex_t mutex_liste_threads; __EXTERN__ pthread_mutex_t mutex_creation_variable_partagee __STATIC_MUTEX_INITIALIZATION__; __EXTERN__ pthread_mutex_t mutex_sections_critiques; @@ -523,6 +562,7 @@ union semun __EXTERN__ pthread_mutex_t mutex_sem __STATIC_MUTEX_INITIALIZATION__; __EXTERN__ volatile int routine_recursive; + __EXTERN__ volatile int nombre_thread_surveillance_processus; # define SEM_FORK 0 # define SEM_QUEUE 1 @@ -590,26 +630,6 @@ union semun # define fflush(flux) fflush((flux == stdout) ? stderr : flux) #endif -// Ajout d'un timeout sur les fonctions pipe() pour éviter une erreur -// système dans le cas où l'on a atteint le nombre maximale de fichiers -// ouverts. - -#define pipe(descripteurs) \ - ({ \ - struct timespec temporisation; \ - int erreur, nombre_echecs; \ - nombre_echecs = 0; \ - do \ - { \ - if ((erreur = pipe(descripteurs)) == 0) break; \ - nombre_echecs++; \ - temporisation.tv_sec = 0; \ - temporisation.tv_nsec = ((long) 1000000000) * rand(); \ - nanosleep(&temporisation, NULL); \ - } while(nombre_echecs < 100); \ - erreur; \ - }) - // Redéfinition de abs pour un fonctionnement en entier de type long long int #ifdef __GNUC__ @@ -632,9 +652,9 @@ union semun } while(0) #ifdef __GLIBC__ -#include -#define __BACKTRACE -#define BACKTRACE(n) \ +# include +# define __BACKTRACE +# define BACKTRACE(n) \ do \ { \ void *buffer[n]; \ @@ -659,7 +679,7 @@ union semun pthread_mutex_unlock(&mutex); \ } while(0) #else -#define BACKTRACE(n) NOTICE("BACKTRACE only defined in glibc") +# define BACKTRACE(n) NOTICE("BACKTRACE only defined in glibc") #endif #ifdef __BACKTRACE @@ -705,23 +725,29 @@ pid_t debug_fork(); #endif #ifdef DEBUG_RETURN -#define return uprintf("[%d] Return from <%s()> at line #%d " \ +# define return uprintf("[%d] Return from <%s()> at line #%d " \ "(%s [%d])\n", (int) getpid(), __FUNCTION__, \ __LINE__, strerror(errno), errno); fflush(stdout); errno = 0; return #endif #ifdef DEBUG_MUTEX -#define pthread_mutex_lock(mutex) uprintf("[%d-%llu] Mutex %s (%p) " \ +# define pthread_mutex_lock(mutex) uprintf("[%d-%llu] Mutex %s (%p) " \ "locking at %s() " \ "line #%d\n", (int) getpid(), (unsigned long long) pthread_self(), \ #mutex, mutex, __FUNCTION__, __LINE__), fflush(stdout), \ pthread_mutex_lock(mutex) -#define pthread_mutex_unlock(mutex) uprintf("[%d-%llu] Mutex %s (%p) " \ +# define pthread_mutex_unlock(mutex) uprintf("[%d-%llu] Mutex %s (%p) " \ "unlocking at " \ "%s() line #%d\n", (int) getpid(), (unsigned long long) \ pthread_self(), #mutex, mutex, __FUNCTION__, __LINE__), \ fflush(stdout), \ pthread_mutex_unlock(mutex) +# define pthread_mutex_trylock(mutex) uprintf("[%d-%llu] Mutex %s (%p) " \ + "trylocking at " \ + "%s() line #%d\n", (int) getpid(), (unsigned long long) \ + pthread_self(), #mutex, mutex, __FUNCTION__, __LINE__), \ + fflush(stdout), \ + pthread_mutex_trylock(mutex) #endif @@ -772,6 +798,7 @@ pid_t debug_fork(); #define d_SPH "Semaphore $n 'name'" #define d_TAB "<[ table ]>" #define d_MTX "Mutex $n" +#define d_REC "|[ record ]|" /* -------------------------------------------------------------------------------- @@ -809,16 +836,48 @@ pid_t debug_fork(); # else # define __erreur_(i) i # endif -# define __erreur(i) ({ if (strstr(__FUNCTION__, "recherche_variable") \ - == NULL) ufprintf(stderr, \ - "ERROR %d AT %s() FROM %s LINE %d\n", \ - i, __FUNCTION__, __FILE__, __LINE__); i; }) +# define __erreur(i) ({ int ios; ios = errno; \ + if (strstr(__FUNCTION__, "recherche_variable") \ + == NULL) { if(ios != 0) \ + ufprintf(stderr, "LAST ERROR: %s\n", strerror(ios)); \ + ufprintf(stderr, "ERROR %d AT %s() FROM %s LINE %d\n", \ + i, __FUNCTION__, __FILE__, __LINE__); BACKTRACE(16); } i; }) # endif #else # define __erreur(i) i # define __erreur_(i) i #endif +#ifdef DEBUG_FICHIERS +# define open(a, ...) \ + ({ ufprintf(stderr, "[%d] OPEN %s AT %s() FROM %s LINE %d\n", \ + getpid(), a, \ + __FUNCTION__, __FILE__, __LINE__); open(a, __VA_ARGS__); }) +# define pipe(a) \ + ({ ufprintf(stderr, "[%d] PIPE %s AT %s() FROM %s LINE %d\n", \ + getpid(), a, \ + __FUNCTION__, __FILE__, __LINE__); pipe(a); }) +# define shm_open(a, ...) \ + ({ ufprintf(stderr, "[%d] SHM_OPEN %s AT %s() FROM %s LINE %d\n", \ + getpid(), a, \ + __FUNCTION__, __FILE__, __LINE__); shm_open(a, __VA_ARGS__); }) +# define shm_unlink(a) \ + ({ ufprintf(stderr, "[%d] SHM_UNLINK %s AT %s() FROM %s LINE %d\n", \ + getpid(), a, \ + __FUNCTION__, __FILE__, __LINE__); shm_unlink(a); }) +# define sem_open(a, ...) \ + ({ ufprintf(stderr, "[%d] SEM_OPEN %s AT %s() FROM %s LINE %d\n", \ + getpid(), a, \ + __FUNCTION__, __FILE__, __LINE__); sem_open(a, __VA_ARGS__); }) +# define sem_unlink(a) \ + ({ ufprintf(stderr, "[%d] SEM_UNLINK %s AT %s() FROM %s LINE %d\n", \ + getpid(), a, \ + __FUNCTION__, __FILE__, __LINE__); sem_unlink(a); }) +# define close(a) \ + ({ ufprintf(stderr, "[%d] CLOSE %s AT %s() FROM %s LINE %d\n", \ + getpid(), a, \ + __FUNCTION__, __FILE__, __LINE__); close(a); }) +#endif // -1 : erreur provoquée par une bibliothèque externe #ifndef RPLARGS @@ -985,6 +1044,8 @@ pid_t debug_fork(); # define d_ex_chiffrement_indisponible __erreur(90) # define d_ex_longueur_clef_chiffrement __erreur(91) # define d_ex_taille_message __erreur(92) +# define d_ex_type_externe_dup __erreur(93) +# define d_ex_type_externe_drop __erreur(94) #endif @@ -1013,6 +1074,7 @@ pid_t debug_fork(); #define BIN __RPL_BIN #define CHN __RPL_CHN #define CPL __RPL_CPL +#define EXT __RPL_EXT #define FCH __RPL_FCH #define FCT __RPL_FCT #define INT __RPL_INT @@ -1024,6 +1086,7 @@ pid_t debug_fork(); #define NOM __RPL_NOM #define NON __RPL_NON #define PRC __RPL_PRC +#define REC __RPL_REC #define REL __RPL_REL #define RPN __RPL_RPN #define SCK __RPL_SCK @@ -1037,8 +1100,8 @@ pid_t debug_fork(); enum t_rplcas_commandes { RPLCAS_INTEGRATION = 0, RPLCAS_LIMITE }; -enum t_type { ADR = 0, ALG, BIN, CHN, CPL, FCH, FCT, INT, LST, - MCX, MIN, MRL, MTX, NOM, NON, PRC, REL, RPN, SCK, +enum t_type { ADR = 0, ALG, BIN, CHN, CPL, EXT, FCH, FCT, INT, LST, + MCX, MIN, MRL, MTX, NOM, NON, PRC, REC, REL, RPN, SCK, SLB, SPH, SQL, TBL, VCX, VIN, VRL }; /* @@ -1061,6 +1124,8 @@ enum t_type { ADR = 0, ALG, BIN, CHN, C Sans objet. Type C/Fortran : complex16 + EXT : type géré dans une bibliothèque externe. + FCH : descripteur de fichier (struct_fichier *). FCT : déclaration d'une fonction et de son nombre d'arguments @@ -1095,6 +1160,8 @@ enum t_type { ADR = 0, ALG, BIN, CHN, C PRC : processus (struct_processus_fils *) Sans objet. + REC : enregistrement (struct_record *) + REL : reel sur 64 bits (real*8, real8 *) Sans objet. @@ -1126,6 +1193,8 @@ enum t_type { ADR = 0, ALG, BIN, CHN, C typedef struct objet { enum t_type type; + integer8 extension_type; + void *descripteur_bibliotheque; volatile long nombre_occurrences; @@ -1312,6 +1381,20 @@ typedef struct connecteur_sql */ #ifndef RPLARGS + +# define d_BIND_TO_DEVICE 0 +# define d_BROADCAST 1 +# define d_DONT_ROUTE 2 +# define d_KEEP_ALIVE 3 +# define d_PRIORITY 4 +# define d_RECEIVE_BUFFER 5 +# define d_FORCE_RECEIVE_BUFFER 6 +# define d_SEND_BUFFER 7 +# define d_FORCE_SEND_BUFFER 8 +# define d_RECEIVING_TIMEOUT 9 +# define d_SENDING_TIMEOUT 10 +# define d_REUSE_ADDRESS 11 + typedef struct socket { int domaine; @@ -1330,6 +1413,13 @@ typedef struct socket unsigned char protection; unsigned char type[19 + 1]; + integer8 options; + int priorite; + int buffer_reception; + int buffer_emission; + int timeout_emission; + int timeout_reception; + struct_objet *format; } struct_socket; #endif @@ -1517,6 +1607,7 @@ typedef struct liste_pile_systeme logical1 creation_variables_statiques; logical1 creation_variables_partagees; logical1 evaluation_expression; + logical1 debug_programme; unsigned char clause; @@ -1697,6 +1788,19 @@ typedef struct tableau /* -------------------------------------------------------------------------------- + Structure enregistrement +-------------------------------------------------------------------------------- +*/ + +typedef struct record +{ + struct_objet *noms; + struct_objet *donnees; +} struct_record; + + +/* +-------------------------------------------------------------------------------- Structure arbre -------------------------------------------------------------------------------- */ @@ -1721,6 +1825,7 @@ typedef struct instruction_externe unsigned char *nom; unsigned char *nom_bibliotheque; void *descripteur_bibliotheque; + integer8 position_fleche; } struct_instruction_externe; @@ -1762,7 +1867,10 @@ typedef struct rpl_arguments unsigned char test_instruction; integer8 nombre_arguments; - // Nombre d'arguments de la fonction, positif ou nul. + // Nombre d'arguments de la fonction + // 0 : instruction infixe + // positif : nombre d'arguments (notation algébrique possible) + // -1 : notation algrébrique non autorisée void *s_etat_processus; } struct_rpl_arguments; @@ -1951,6 +2059,7 @@ typedef struct processus unsigned char evaluation_forcee; /*Y/N*/ unsigned char instruction_valide; /*Y/N*/ unsigned char instruction_intrinseque; /*Y/I/N*/ + unsigned char instruction_sensible; /*Y/N*/ unsigned char test_instruction; /*Y/N*/ unsigned char affichage_arguments; /*Y/N*/ unsigned char constante_symbolique; /*Y/N*/ @@ -2411,6 +2520,7 @@ typedef struct processus CACHE(integer8, int) CACHE(struct_matrice, mat) CACHE(struct_nom, nom) + CACHE(struct_record, rec) CACHE(real8, rel) CACHE(struct_tableau, tab) CACHE(struct_vecteur, vec) @@ -2425,8 +2535,8 @@ typedef struct processus variables_tableau_noeuds_partages) CACHE2(struct_buffer, enveloppes_buffers) - unsigned char ***cache_buffer; - int *pointeur_cache_buffer; + unsigned char ***cache_buffer; + int *pointeur_cache_buffer; } struct_processus; #endif @@ -2446,6 +2556,7 @@ void *rpl_malloc(struct_processus *s_eta void *rpl_realloc(struct_processus *s_etat_processus, void *ptr, size_t s); void rpl_free(struct_processus *s_etat_processus, void *ptr); void *sys_malloc(size_t s); +void *sys_realloc(void *ptr, size_t s); void sys_free(void *ptr); /* @@ -2735,6 +2846,7 @@ void instruction_mtxtrylock(struct_proce void instruction_mtxunlock(struct_processus *s_etat_processus); void instruction_multiplication(struct_processus *s_etat_processus); +void instruction_nbrcpus(struct_processus *s_etat_prorcessus); void instruction_ne(struct_processus *s_etat_processus); void instruction_neg(struct_processus *s_etat_processus); void instruction_next(struct_processus *s_etat_processus); @@ -2824,6 +2936,7 @@ void instruction_rdz(struct_processus *s void instruction_re(struct_processus *s_etat_processus); void instruction_read(struct_processus *s_etat_processus); void instruction_recode(struct_processus *s_etat_processus); +void instruction_record(struct_processus *s_etat_processus); void instruction_recv(struct_processus *s_etat_processus); void instruction_redraw(struct_processus *s_etat_processus); void instruction_regex(struct_processus *s_etat_processus); @@ -3105,7 +3218,10 @@ void interruption3(int signal); void interruption4(int signal); void interruption5(int signal); void interruption6(int signal); -void interruption_depassement_pile(int urgence, stackoverflow_context_t scp); +#ifdef HAVE_SIGSEGV_RECOVERY + void interruption_depassement_pile(int urgence, + stackoverflow_context_t scp); +#endif void inversion_matrice(struct_processus *s_etat_processus, struct_matrice *s_matrice); void lancement_daemon(struct_processus *s_etat_processus); @@ -3189,7 +3305,8 @@ void liberation_queue_signaux(struct_pro void destruction_queue_signaux(struct_processus *s_etat_processus); int envoi_signal_contexte(struct_processus *s_etat_processus, enum signaux_rpl signal); -int envoi_signal_processus(pid_t pid, enum signaux_rpl signal); +int envoi_signal_processus(pid_t pid, enum signaux_rpl signal, + logical1 test_ouverture); int envoi_signal_thread(pthread_t tid, enum signaux_rpl signal); #endif @@ -3274,8 +3391,10 @@ struct_liste_chainee *sauvegarde_argumen #ifndef RPLARGS unsigned char *analyse_algebrique(struct_processus *s_etat_processus, unsigned char *chaine_algebrique, struct_liste_chainee **l_base_liste); +#endif unsigned char *analyse_flux(struct_processus *s_etat_processus, unsigned char *flux, integer8 longueur); +#ifndef RPLARGS unsigned char *chiffrement(struct_processus *s_etat_processus, const EVP_CIPHER *type_chiffrement, logical1 encodage, unsigned char *message, integer8 longueur_message, @@ -3298,8 +3417,10 @@ unsigned char *formateur_fichier(struct_ integer8 longueur, integer8 longueur_champ, unsigned char format, unsigned char type, integer8 *longueur_effective, integer8 *recursivite, logical1 export_fichier); +#endif unsigned char *formateur_flux(struct_processus *s_etat_processus, unsigned char *donnees, integer8 *longueur); +#ifndef RPLARGS unsigned char *formateur_fichier_nombre(struct_processus *s_etat_processus, void *valeur_numerique, unsigned char type, integer8 longueur, integer8 longueur_champ, unsigned char format); @@ -3383,7 +3504,8 @@ logical1 retrait_variable_statique(struc logical1 retrait_variables_statiques_locales( struct_processus *s_etat_processus); logical1 sequenceur(struct_processus *s_etat_processus); -logical1 sequenceur_optimise(struct_processus *s_etat_processus); +logical1 sequenceur_optimise(struct_processus *s_etat_processus, + struct_liste_chainee *l_bibliotheques); #endif /*