/*************************************************************************************************************************************/
/* */
/* O P E R A T I O N S A R I T H M E T I Q U E S S U R D E S F I C H I E R S : */
/* */
/* */
/* Author of '$xrv/ARITHMET.1g$I' : */
/* */
/* Jean-Francois COLONNA (LACTAMME, 20060215103111). */
/* */
/*************************************************************************************************************************************/
/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/* */
/* R E C U P E R A T I O N D ' U N F I C H I E R " L I S T E " : */
/* */
/*************************************************************************************************************************************/
#define PREMIER_ELEMENT_D_UNE_LISTE_VERSION_PREMIER_ELEMENT_D_UN_FICHIER_0 \
/* Afin de faire la difference entre les programmes dont les premiers elements sont */ \
/* numerotes 'PREMIER_POINT_DES_LISTES' ('v $xrv/particule.10$K') et ceux dont les premiers */ \
/* elements sont numerotes 'PREMIER_ELEMENT_D_UN_FICHIER' ('v $xrv/distance.02$K'). */
/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/* */
/* V A L E U R S I M P L I C I T E S D E S P A R A M E T R E S : */
/* */
/*************************************************************************************************************************************/
#nodefine NOMBRE_D_ELEMENTS \
TRI_DIMENSIONNEL
#define NOMBRE_D_ELEMENTS \
ZERO
/* Nombre d'elements attendus a priori dans les fichiers. Le passage de 'TRI_DIMENSIONNEL' */
/* a 'ZERO' a eu lieu le 19991217121738 afin de permettre la determination automatique de */
/* 'nombre_d_elements'... */
#define UTILISER_LE_FORMAT_EXPONENTIEL \
VRAI \
/* Faut-il sortir en format "%g" ('VRAI') ou en format "%f" ('FAUX'). Ceci a ete introduit */ \
/* afin de permettre d'extraire la partie entiere d'un nombre en supprimant simplement tout */ \
/* ce qui suit le point decimal avec '$SE'... */
/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/* */
/* D E F I N I T I O N D E S F I C H I E R S : */
/* */
/*************************************************************************************************************************************/
#define EN_TETE_DANS_LE_FICHIER \
ZERO
#define SAUT_DANS_LE_FICHIER \
ZERO
DEFV(Local,DEFV(Positive,INIT(en_tete_dans_le_fichier_des_valeurs,EN_TETE_DANS_LE_FICHIER)));
DEFV(Local,DEFV(Positive,INIT(saut_dans_le_fichier_des_valeurs,SAUT_DANS_LE_FICHIER)));
/* Definition du nombre de valeurs a sauter entre deux valeurs recuperees du fichier de */
/* coordonnees et de valeurs. L'amplitude du saut sur le debut du fichier ("en_tete") a */
/* ete introduite le 20021104171432 par symetrie avec '$xrv/particule.11$I 20021104161517'. */
#define PROCESS_ARGUMENTS_DE_DEFINITION_DES_FICHIERS_01 \
/* La partie "_01" du nom 'PROCESS_ARGUMENTS_DE_DEFINITION_DES_FICHIERS_01' est choisie */ \
/* en harmonie avec le nom de la procedure 'lTRANSFORMAT_01(...)' qui lui est associee... */ \
Bblock \
\
DEBUT_D_IMBRICATION_DES_____gPROCESS_PARAMETRE_____SECONDAIRES; \
/* Introduit le 20060208111712 ('v $xig/fonct$vv$DEF _IMBRICATION_DES__gPROCESS_PARAMETRE'). */ \
\
PROCESS_ARGUMENT_I("en_tete=",en_tete_dans_le_fichier_des_valeurs \
,BLOC(VIDE;) \
,BLOC(PRINT_AVERTISSEMENT("'saut=' doit etre defini avant toute entree de fichiers");) \
); \
/* ATTENTION : la recuperation de 'en_tete_dans_le_fichier_des_valeurs' doit */ \
/* preceder les 'PROCESS_ARGUMENT_C(...)' qui suivent car ils l'utilisent. */ \
PROCESS_ARGUMENT_I("saut=",saut_dans_le_fichier_des_valeurs \
,BLOC(VIDE;) \
,BLOC(PRINT_AVERTISSEMENT("'saut=' doit etre defini avant toute entree de fichiers");) \
); \
/* ATTENTION : la recuperation de 'saut_dans_le_fichier_des_valeurs' doit preceder */ \
/* les 'PROCESS_ARGUMENT_C(...)' qui suivent car ils l'utilisent. */ \
\
FIN___D_IMBRICATION_DES_____gPROCESS_PARAMETRE_____SECONDAIRES; \
/* Introduit le 20060208111712 ('v $xig/fonct$vv$DEF _IMBRICATION_DES__gPROCESS_PARAMETRE'). */ \
\
Eblock \
/* Introduit le 20021104173637 pour faciliter la mise a jour de differents '$K' suite */ \
/* a l'introduction du nouveau parametre 'en_tete_dans_le_fichier_des_valeurs'... */
#TestADef NOMBRE_MAXIMAL_D_ELEMENTS_DANS_LE_FICHIER \
GRO2(MILLION) \
/* Nombre maximal d'elements dans les fichiers (valeur tres arbitraire...). */ \
/* */ \
/* Le 20060210172552, ce nombre est passe de 'MILLION' a 'GRO2(MILLION)' a cause de */ \
/* 'v $xiird/.PEA3.3.11.$U'... */
DEFV(Local,DEFV(Positive,INIT(nombre_maximal_d_elements_dans_le_fichier,NOMBRE_MAXIMAL_D_ELEMENTS_DANS_LE_FICHIER)));
#define gGENERATION_D_UN_FICHIER_nom(fichier_des_valeurs) \
DEFV(Local,DEFV(CHAR,INIT(POINTERc(fichier_des_valeurs),NOM_PIPE_Local)));
#define gGENERATION_D_UN_FICHIER_liste(liste_des_valeurs) \
DEFV(Local,DEFV(Positive,INIT(liste_des_valeurs`____nombre_d_elements,NOMBRE_D_ELEMENTS))); \
/* Il est plus logique de definir 'nombre_d_elements' a partir de 'liste_des_valeurs' qu'a */ \
/* l'aide de 'fichier_des_valeurs' car, en effet, ainsi cette variable specifique a chaque */ \
/* fichier pourra etre utilisee dans 'gELEMENT_DU_FICHIER(...)' si besoin est... */ \
DEFV(Local,DEFV(Float,DdTb1(POINTERf \
,liste_des_valeurs \
,nombre_maximal_d_elements_dans_le_fichier \
,ADRESSE_NON_ENCORE_DEFINIE \
) \
) \
);
#define gGENERATION_D_UN_FICHIER(fichier_des_valeurs,liste_des_valeurs) \
gGENERATION_D_UN_FICHIER_nom(fichier_des_valeurs); \
gGENERATION_D_UN_FICHIER_liste(liste_des_valeurs);
/* Generation en memoire d'un fichier sous la forme {nom,liste}. */
/* */
/* L'allocation dynamique de 'liste_des_valeurs' a ete introduite le 20060213182327... */
/* */
/* Le nombre specifique d'elements de chauqe fichier a ete introduit le 20240930155301... */
#define gELEMENT_DU_FICHIER(liste_des_valeurs,index) \
IdTb1(liste_des_valeurs \
,INDX(index,PREMIER_ELEMENT_D_UN_FICHIER) \
,nombre_maximal_d_elements_dans_le_fichier \
) \
/* Acces a un element courant des fichiers. */ \
/* */ \
/* ATTENTION a ne pas confondre : */ \
/* */ \
/* 1-'ACCES_LISTE(...)', pour lequel le premier element vaut : */ \
/* */ \
/* PREMIER_POINT_DES_LISTES=PREMIER_POINT=PREMIERE_ITERATION_D_UN_Komp=UN */ \
/* */ \
/* qui est donc adapte a une gestion de type 'Komp(...)' ou le premier element est defini */ \
/* implicitement (et vaut donc 'UN'), et */ \
/* */ \
/* 2-'gELEMENT_DU_FICHIER(...)', pour lequel le premier element vaut : */ \
/* */ \
/* PREMIER_ELEMENT_D_UN_FICHIER=INDEX0=ZERO */ \
/* */ \
/* qui ne peut utiliser 'Komp(...)' et demande donc une gestion de type 'DoIn(...)' en */ \
/* precisant le premier element en tant qu'argument du 'DoIn(...)' (et valant donc 'ZERO'). */
#define glTRANSFORMAT_01__nombre_d_elements(nombre_effectif_d_elements,editer_les_messages_d_erreur_des_fichiers) \
Bblock \
DEFV(Int,INIT(taille_du_fichier_des_valeurs_effectif,UNDEF)); \
EGAL(Fsize_fichier_____compter_les_lignes,COMPTER_LES_LIGNES_DANS_Fsize_fichier); \
CALS(Fsize_fichier(fichier_des_valeurs_effectif \
,ADRESSE(taille_du_fichier_des_valeurs_effectif) \
,editer_les_messages_d_erreur_des_fichiers \
) \
); \
EGAL(nombre_effectif_d_elements \
,DIVI(SOUS(Fsize_fichier_____nombre_de_lignes,en_tete_dans_le_fichier_des_valeurs) \
,TRPU(saut_dans_le_fichier_des_valeurs) \
) \
); \
Eblock \
/* Introduit le 20240930155301... */
#define glTRANSFORMAT_01(fichier_des_valeurs,liste_des_valeurs,valeur_par_defaut,sequence_allocation_eventuelle) \
Bblock \
DEFV(CHAR,INIC(POINTERc(fichier_des_valeurs_effectif),NOM_UNDEF)); \
/* Nom du fichier a lire (soit un "vrai" fichier, soit un "pipe"). */ \
\
Test(I3OU(IFEQ_chaine(fichier_des_valeurs,C_VIDE) \
,IFEQ_chaine(fichier_des_valeurs,NOM_PIPE) \
,IFEQ_chaine(fichier_des_valeurs,NOM_PIPE_Local) \
) \
) \
/* ATTENTION, j'ai decouvert le 20000207110651 qu'il n'etait pas equivalent de laisser */ \
/* a un argument 'fichier_des_valeurs' sa valeur implicite ('NOM_PIPE_Local'), et de lui */ \
/* donner cette valeur, par exemple a l'aide de : */ \
/* */ \
/* fichier="=" */ \
/* */ \
/* (en supposant que l'argument s'appelle "fichier="). En effet, dans le premier cas */ \
/* (valeur implicite conservee), la procedure 'lTRANSFORMAT_01(...)' n'est pas appelee */ \
/* par 'PROCESF_ARGUMENT_C(...)' puisque l'argument courant n'est pas rencontre. Alors, */ \
/* dans ce cas, la gestion du "pipe" qui suit n'est pas effectuee. Donc, moralite, pour */ \
/* acceder proprement au "pipe", il faut que cela soit demande explicitement... */ \
/* */ \
/* Cela est vrai aussi, malheureusement, de l'evaluation automatique de 'nombre_d_elements'. */ \
/* */ \
/* Cela a donc conduit a l'introduction de 'v $xig/fonct$vv$DEF gPROCESS_PARAMETRE' et de */ \
/* 'v $xig/fonct$vv$DEF PROCESF_ARGUMENT_C'. Malheureusement, le 20000207173145 j'ai */ \
/* decouvert que cela etait insuffisant ('v $xig/fonct$vv$DEF 20000207173145'). Donc, pour */ \
/* "connecter" un fichier au "pipe", il faudra malheureusement ecrire quelque chose du */ \
/* type : */ \
/* */ \
/* fichier="=" */ \
/* */ \
/* si l'on veut que les arguments du meme type et qui sont absents, correspondent a leur */ \
/* valeur par defaut. On etait donc en presence de deux desirs contradictoires : */ \
/* */ \
/* 1-initialiser un fichier avec la valeur par defaut lorsqu'il est */ \
/* absent en tant qu'argument, */ \
/* */ \
/* 1-"connecter" un fichier au "pipe" (valeur par defaut de son nom) */ \
/* lorsqu'il est absent en tant qu'argument. */ \
/* */ \
/* Ainsi, malgre les initialisations (dans 'gGENERATION_D_UN_FICHIER(...)'), l'absence d'un */ \
/* fichier (en tant qu'argument) impliquera l'initialisation de tous ses elements avec sa */ \
/* valeur par defaut, meme si donc son nom vaut 'NOM_PIPE_Local'... */ \
Bblock \
EGAL(fichier_des_valeurs_effectif,generation_d_un_nom_absolu_dans_xT_temporaire(C_VIDE)); \
/* Generation du nom du fichier temporaire correspondant au "pipe". */ \
\
EXECUTION_D_UNE_SUITE_DE_COMMANDES_SOUS_SH(chain_Aconcaten3(Gvar("CA") \
,C_SH__REDIRECTION_FICHIER \
,fichier_des_valeurs_effectif \
) \
); \
/* Transfert du "pipe" dans le fichier temporaire... */ \
/* */ \
/* Passage de 'C_REDIRECTION_FICHIER' a 'C_SH__REDIRECTION_FICHIER' le 20111117082138... */ \
Eblock \
ATes \
Bblock \
EGAL(fichier_des_valeurs_effectif,chain_Acopie(fichier_des_valeurs)); \
/* Le fichier utilise est le fichier argument... */ \
Eblock \
ETes \
\
Test(IZEQ(nombre_d_elements)) \
/* Dispositif introduit le 19991217121738 pour permettre la determination automatique */ \
/* de 'nombre_d_elements' lorsque la valeur qui lui est donnee est nulle... */ \
Bblock \
glTRANSFORMAT_01__nombre_d_elements(nombre_d_elements \
,EDITER_LES_MESSAGES_D_ERREUR_DES_FICHIERS \
); \
/* Determination automatique de 'nombre_d_elements' que le fichier soit un "vrai" fichier */ \
/* ou bien un "pipe"... */ \
/* */ \
/* ATTENTION, cela ne fonctionne pas evidemment dans le cas ou le nom du fichier est en fait */ \
/* une valeur numerique ('LE_NOM_DU_FICHIER_EST_CONVERTISSABLE_EN_UNE_VALEUR_NUMERIQUE'). */ \
/* Dans ce cas et lorsque le programme correspondant recoit comme Arguments plusieurs noms */ \
/* de fichier, la solution consiste a mettre en premier les "vrais" fichiers, puis derriere */ \
/* les "faux" fichiers (dont les noms sont des valeurs numeriques). Ainsi : */ \
/* */ \
/* COMMANDE ne=0 fichier1=1234 fichier2=NOM */ \
/* */ \
/* ne fonctionnera pas car 'Fsize_fichier(...)' va vouloir ouvrir le fichier dont le nom */ \
/* est '1234', alors que : */ \
/* */ \
/* COMMANDE ne=0 fichier1=NOM fichier2=1234 */ \
/* */ \
/* ou encore : */ \
/* */ \
/* COMMANDE ne=0 fichier1="=" fichier2=1234 */ \
/* */ \
/* fonctionneront car la determination de 'nombre_d_elements' aura lieu sur 'fichier1' et */ \
/* donc sur un vrai fichier (de nom 'NOM' ou le "pipe"). */ \
/* */ \
/* Le 20110324100311 (c'est-a-dire un peu tardivement !) ont ete pris en compte dans le */ \
/* calcul de 'nombre_d_elements' des variables 'en_tete_dans_le_fichier_des_valeurs' et */ \
/* 'saut_dans_le_fichier_des_valeurs'... */ \
Eblock \
ATes \
Bblock \
Eblock \
ETes \
\
glTRANSFORMAT_01__nombre_d_elements(liste_des_valeurs`____nombre_d_elements \
,NE_PAS_EDITER_LES_MESSAGES_D_ERREUR_DES_FICHIERS \
); \
/* Mise a jour specifique et systematique introduite le 20240930155301... */ \
/* */ \
/* Je note le 20241005203934 que cette instruction rend impossible la conversion d'un */ \
/* nom de fichier en valeur numerique. On a alors : */ \
/* */ \
/* liste_des_valeurs`____nombre_d_elements == 0 */ \
/* */ \
/* En fait, il apparait que tout se passe bien, sauf le message d'erreur, d'ou sa */ \
/* suppression... */ \
\
BLOC(sequence_allocation_eventuelle); \
/* Allocation memoire ou validation de la taille... */ \
\
CALS(Fload_fichier_formatte_Float(fichier_des_valeurs_effectif \
,liste_des_valeurs \
,nombre_d_elements \
,en_tete_dans_le_fichier_des_valeurs \
,saut_dans_le_fichier_des_valeurs \
,VRAI \
,valeur_par_defaut \
,LE_NOM_DU_FICHIER_EST_CONVERTISSABLE_EN_UNE_VALEUR_NUMERIQUE \
) \
); \
/* Et enfin, lecture du fichier... */ \
\
&define __ParaVal liste_des_valeurs&&& \
&define __ParaInd PREMIER_ELEMENT_D_UN_FICHIER&&& \
&define __ParaLon nombre_d_elements&&& \
&define __ParaTyp TYPE_FORMAT_FLOT&&& \
&define __ParaFor FORMAT_FLOT_EDITION&&& \
\
Test(IFEQ_chaine(fichier_des_valeurs_effectif,fichier_des_valeurs)) \
Bblock \
/* Cas ou il s'agissait d'un "vrai" fichier... */ \
Eblock \
ATes \
Bblock \
/* Cas ou il s'agissait d'un "pipe"... */ \
CALS(Idelete_fichier(fichier_des_valeurs_effectif)); \
/* Destruction du fichier temporaire. */ \
Eblock \
ETes \
\
CALZ_FreCC(fichier_des_valeurs_effectif); \
/* Liberation de l'espace contenant le nom du fichier effectif. */ \
Eblock \
/* Recuperation d'un fichier contenant une liste. ATTENTION, le 19980317091800, le */ \
/* parametre : */ \
/* */ \
/* LE_NOM_DU_FICHIER_N_EST_PAS_CONVERTISSABLE_EN_UNE_VALEUR_NUMERIQUE */ \
/* */ \
/* est devenu : */ \
/* */ \
/* LE_NOM_DU_FICHIER_EST_CONVERTISSABLE_EN_UNE_VALEUR_NUMERIQUE */ \
/* */ \
/* car cela permet, par exemple, d'incrementer tous les elements d'un fichier d'une valeur */ \
/* constante... */ \
/* */ \
/* Je rappelle le 20170111102646 que si le nom du fichier est une "bonne" valeur numerique, */ \
/* c'est elle qui l'emporte, meme si il existe un fichier portant ce nom. Cela ne peut */ \
/* evidemment se produire que si ce dernier fichier est designe de facon relative (et donc */ \
/* dans '$CWD'). Pour forcer l'acces a ce fichier (et donc ne pas utiliser la valeur */ \
/* numerique correspondant a son nom), il suffit d'absolutiser ce nom, qui alors ne */ \
/* ressemblera plus a une "bonne" valeur numerique... */