1 /*============================================================================
2  *  Définitions des fonctions de base
3  *   associées à une liste chaînée de structures `ecs_descr_t' décrivant
4  *   un descripteur de table
5  *============================================================================*/
6 
7 /*
8   This file is part of Code_Saturne, a general-purpose CFD tool.
9 
10   Copyright (C) 1998-2021 EDF S.A.
11 
12   This program is free software; you can redistribute it and/or modify it under
13   the terms of the GNU General Public License as published by the Free Software
14   Foundation; either version 2 of the License, or (at your option) any later
15   version.
16 
17   This program is distributed in the hope that it will be useful, but WITHOUT
18   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19   FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
20   details.
21 
22   You should have received a copy of the GNU General Public License along with
23   this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
24   Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 */
26 
27 /*----------------------------------------------------------------------------*/
28 
29 
30 /*============================================================================
31  *                                 Visibilité
32  *============================================================================*/
33 
34 /*----------------------------------------------------------------------------
35  *  Fichiers `include' librairie standard C
36  *----------------------------------------------------------------------------*/
37 
38 #include <assert.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 
43 
44 /*----------------------------------------------------------------------------
45  *  Fichiers `include' visibles du  paquetage global "Utilitaire"
46  *----------------------------------------------------------------------------*/
47 
48 #include "ecs_def.h"
49 #include "ecs_fic.h"
50 #include "ecs_mem.h"
51 #include "ecs_tab.h"
52 
53 
54 /*----------------------------------------------------------------------------
55  *  Fichiers `include' visibles des paquetages visibles
56  *----------------------------------------------------------------------------*/
57 
58 
59 /*----------------------------------------------------------------------------
60  *  Fichiers `include' visibles du  paquetage courant
61  *----------------------------------------------------------------------------*/
62 
63 #include "ecs_descr.h"
64 
65 
66 /*----------------------------------------------------------------------------
67  *  Fichier  `include' du  paquetage courant associe au fichier courant
68  *----------------------------------------------------------------------------*/
69 
70 #include "ecs_descr_chaine.h"
71 
72 
73 /*----------------------------------------------------------------------------
74  *  Fichiers `include' prives   du  paquetage courant
75  *----------------------------------------------------------------------------*/
76 
77 #include "ecs_descr_priv.h"
78 
79 
80 /*============================================================================
81  *                              Fonctions privées
82  *============================================================================*/
83 
84 /*----------------------------------------------------------------------------
85  *  Fonction qui supprime un noeud donné
86  *   dans une liste chaînée de descripteurs dont la tête est donnée
87  *
88  *  La tête de la liste qui n'est pas modifiée
89  *   sauf si le noeud à supprimer est aussi la tête de la liste !
90  *----------------------------------------------------------------------------*/
91 
92 static int
_ecs_descr_chaine_compare(const void * descr1,const void * descr2)93 _ecs_descr_chaine_compare(const void  *descr1,
94                           const void  *descr2)
95 {
96   const ecs_descr_t *d1 = descr1;
97   const ecs_descr_t *d2 = descr2;
98 
99   /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
100 
101   if (d1->nom != NULL && d2->nom != NULL)
102     return strcmp(d1->nom, d2->nom);
103 
104   else if (d1->nom != NULL && d2->nom == NULL)
105     return 1;
106 
107   else if (d1->nom == NULL && d2->nom != NULL)
108     return -1;
109 
110   return 0;
111 }
112 
113 /*----------------------------------------------------------------------------
114  *  Fonction qui supprime un noeud donné
115  *   dans une liste chaînée de descripteurs dont la tête est donnée
116  *
117  *  La tête de la liste qui n'est pas modifiée
118  *   sauf si le noeud à supprimer est aussi la tête de la liste !
119  *----------------------------------------------------------------------------*/
120 
121 static void
ecs_loc_descr_chaine__supprime(ecs_descr_t ** descr_noeud,ecs_descr_t ** descr_tete)122 ecs_loc_descr_chaine__supprime(ecs_descr_t  **descr_noeud,
123                                ecs_descr_t  **descr_tete)
124 {
125   ecs_descr_t *loc_descr_sui;
126   ecs_descr_t *ptr_descr;
127 
128   /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
129 
130   assert(*descr_tete != NULL);
131   assert(*descr_noeud != NULL);
132 
133   if ((*descr_noeud) == *descr_tete) {
134 
135     /* Le descripteur noeud à supprimer est la tête de liste des descripteurs */
136     /* Le descripteur suivant est la nouvelle tête                            */
137 
138     *descr_tete = (*descr_tete)->l_descr_sui;
139 
140   }
141   else {
142 
143     /* On recherche le noeud qui précède le noeud à supprimer */
144 
145     loc_descr_sui = (*descr_noeud)->l_descr_sui;
146 
147     for (ptr_descr = *descr_tete;
148          ptr_descr != NULL && ptr_descr->l_descr_sui != (*descr_noeud);
149          ptr_descr = ptr_descr->l_descr_sui);
150 
151     /* Le noeud à supprimer doit être contenu dans la liste */
152     /* `*descr_tete' est la tête                            */
153     assert(ptr_descr != NULL);
154 
155     ptr_descr->l_descr_sui = loc_descr_sui;
156 
157   } /* Fin else : le descripteur à supprimer n'est pas le descripteur de tête */
158 
159   /* Libération du descripteur correspondant au noeud à supprimer */
160 
161   *descr_noeud = ecs_descr__detruit(*descr_noeud);
162 }
163 
164 /*============================================================================
165  *                             Fonctions publiques
166  *============================================================================*/
167 
168 /*----------------------------------------------------------------------------
169  *  Fonction libérant la portion d'une liste chaînée de descripteurs
170  *   à partir d'un noeud dont le pointeur est donné en argument.
171  *  Le noeud est à NULL au retour de la fonction
172  *----------------------------------------------------------------------------*/
173 
174 void
ecs_descr_chaine__detruit(ecs_descr_t ** descr_noeud)175 ecs_descr_chaine__detruit(ecs_descr_t  **descr_noeud)
176 {
177   if (*descr_noeud != NULL) {
178 
179     ecs_descr_chaine__detruit(&(*descr_noeud)->l_descr_sui);
180 
181     *descr_noeud = ecs_descr__detruit(*descr_noeud);
182 
183   }
184 }
185 
186 /*----------------------------------------------------------------------------
187  *  Fonction imprimant à partir d'un noeud `ecs_descr_t' donné
188  *   une liste chaînée de tables
189  *   sur le flux décrit par la structure `ecs_file_t'
190  *----------------------------------------------------------------------------*/
191 
ecs_descr_chaine__imprime(const ecs_descr_t * descr_noeud,int imp_col,FILE * fic_imp)192 void ecs_descr_chaine__imprime(const ecs_descr_t  *descr_noeud,
193                                int                 imp_col,
194                                FILE               *fic_imp)
195 {
196 #define ECS_FCT_IMP_DESCR_NOEUD       "descr"
197 
198   /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
199 
200   if (descr_noeud != NULL) {
201 
202     ecs_descr_chaine__imprime(descr_noeud->l_descr_sui,
203                               imp_col,
204                               fic_imp);
205 
206     ecs_fic__imprime_ptr(fic_imp, imp_col, ECS_FCT_IMP_DESCR_NOEUD,
207                          (const void *)descr_noeud);
208 
209     ecs_descr__imprime(descr_noeud,
210                        imp_col,
211                        fic_imp);
212 
213   }
214 }
215 
216 /*----------------------------------------------------------------------------
217  *  Fonction qui renvoie la taille en octets
218  *   d'une chaîné de structures `ecs_descr_t'
219  *----------------------------------------------------------------------------*/
220 
221 float
ecs_descr_chaine__ret_taille(const ecs_descr_t * descr_noeud)222 ecs_descr_chaine__ret_taille(const ecs_descr_t  *descr_noeud)
223 {
224 
225   float         taille;
226 
227   /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
228 
229   taille = 0.;
230 
231   if (descr_noeud != NULL) {
232 
233     taille +=
234       ecs_descr_chaine__ret_taille(descr_noeud->l_descr_sui);
235 
236     taille += ecs_descr__ret_taille(descr_noeud);
237 
238   }
239 
240   return taille;
241 }
242 
243 /*----------------------------------------------------------------------------
244  *  Fonction qui ajoute à la fin d'une liste chaînée de descripteurs
245  *   réceptrice dont la tête est donnée, une liste chaînée de descripteurs
246  *   à concaténer dont la tête est donnée
247  *
248  *  Les numéros des descripteurs de la liste à concaténer sont incrementés
249  *   à partir du nombre de descripteur de la liste réceptrice
250  *
251  *  Remarque: cette fonction se contente d'ajouter des descripteurs sans
252  *            vérifier si le descripteur ajoute a le même contenu qu'un autre
253  *            descripteur déjà présent dans la liste.
254  *            Pour une vérification, utiliser `ecs_descr_chaine__concatene()'
255  *----------------------------------------------------------------------------*/
256 
257 void
ecs_descr_chaine__ajoute(ecs_descr_t ** descr_tete,ecs_descr_t * descr_concat_tete)258 ecs_descr_chaine__ajoute(ecs_descr_t  **descr_tete,
259                          ecs_descr_t   *descr_concat_tete)
260 {
261   ecs_int_t   inum;
262 
263   ecs_descr_t  *loc_descr_prec;
264   ecs_descr_t  *ptr_descr;
265 
266   /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
267 
268   assert(descr_tete   != NULL);
269 
270   if (*descr_tete != NULL) {
271 
272     /* On va à la fin de la chaîne réceptrice */
273 
274     for (ptr_descr = *descr_tete;
275          ptr_descr != NULL;
276          ptr_descr = ptr_descr->l_descr_sui  )
277       loc_descr_prec = ptr_descr;
278 
279     /* On ajoute le lien avec le début de la chaîne à concaténer */
280 
281     loc_descr_prec->l_descr_sui = descr_concat_tete;
282 
283     /* Les numéros des descripteurs de la liste à concaténer sont incrémentés */
284     /*  à partir du nombre de descripteur de la liste réceptrice              */
285 
286     for (ptr_descr = descr_concat_tete, inum = 1;
287          ptr_descr != NULL;
288          ptr_descr = ptr_descr->l_descr_sui, inum++    )
289       ptr_descr->num = loc_descr_prec->num + inum;
290 
291   }
292   else {
293 
294     *descr_tete = descr_concat_tete;
295 
296   }
297 }
298 
299 /*----------------------------------------------------------------------------
300  *  Fonction qui renvoie le nombre de descripteurs
301  *   de la liste chaînée des descripteurs dont la tête est donnée
302  *----------------------------------------------------------------------------*/
303 
304 int
ecs_descr_chaine__ret_nbr(const ecs_descr_t * descr_tete)305 ecs_descr_chaine__ret_nbr(const ecs_descr_t  *descr_tete)
306 {
307   const ecs_descr_t  *ptr_descr;
308   ecs_int_t           nbr_descr;
309 
310   /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
311 
312   assert(descr_tete != NULL);
313 
314   nbr_descr = 0;
315 
316   for (ptr_descr = descr_tete;
317        ptr_descr != NULL;
318        ptr_descr = ptr_descr->l_descr_sui) {
319 
320     nbr_descr++;
321 
322   }
323 
324   return nbr_descr;
325 }
326 
327 /*----------------------------------------------------------------------------
328  *  Fonction qui copie une liste chaînée de descripteurs
329  *   dont la tête est donnée
330  *----------------------------------------------------------------------------*/
331 
332 ecs_descr_t *
ecs_descr_chaine__copie(ecs_descr_t * descr_tete)333 ecs_descr_chaine__copie(ecs_descr_t  *descr_tete)
334 {
335   ecs_descr_t  *descr_copie;
336   ecs_descr_t  *descr_tete_copie;
337   ecs_descr_t  *ptr_descr;
338 
339   /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
340 
341   descr_tete_copie = NULL;
342 
343   for (ptr_descr  = descr_tete;
344        ptr_descr != NULL;
345        ptr_descr  = ptr_descr->l_descr_sui  ) {
346 
347     descr_copie = ecs_descr__copie(ptr_descr);
348 
349     ecs_descr_chaine__ajoute(&descr_tete_copie,
350                              descr_copie);
351 
352   }
353 
354   return descr_tete_copie;
355 }
356 
357 /*----------------------------------------------------------------------------
358  *  Fonction qui concatène,
359  *   à la fin d'une liste chaînée de descripteurs dont la tête est donnée,
360  *   une autre liste chaînée de descripteurs dont la tête est donnée,
361  *   en supprimant les descripteurs déjà présents dans la 1ère liste
362  *   et en décalant la renumérotation des descripteurs de la 2nde liste
363  *
364  *  La fonction renvoie la renumérotation des descripteurs de la 2nde liste
365  *----------------------------------------------------------------------------*/
366 
367 ecs_tab_int_t
ecs_descr_chaine__concatene(ecs_descr_t ** descr_recept_tete,ecs_descr_t ** descr_concat_tete)368 ecs_descr_chaine__concatene(ecs_descr_t  **descr_recept_tete,
369                             ecs_descr_t  **descr_concat_tete)
370 {
371   ecs_int_t     cpt_descr;
372 
373   ecs_descr_t    *ptr_descr_concat;
374   ecs_descr_t    *ptr_descr_recept;
375 
376   ecs_tab_int_t   tab_renum_descr_concat;
377 
378   /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
379 
380   assert(*descr_concat_tete != NULL);
381 
382   /* On repère le plus grand numéro de descripteur de la chaîne à concaténer */
383 
384   for (ptr_descr_concat = *descr_concat_tete, cpt_descr = 0;
385        ptr_descr_concat != NULL;
386        ptr_descr_concat = ptr_descr_concat->l_descr_sui, cpt_descr++);
387 
388   ECS_MALLOC(tab_renum_descr_concat.val, cpt_descr, ecs_int_t);
389   tab_renum_descr_concat.nbr = cpt_descr;
390 
391   /* On repère le plus grand numéro de descripteur de la chaîne réceptrice */
392 
393   for (ptr_descr_recept = *descr_recept_tete, cpt_descr = 0;
394        ptr_descr_recept != NULL;
395        ptr_descr_recept = ptr_descr_recept->l_descr_sui, cpt_descr++);
396 
397   /* On parcourt les descripteurs de la chaîne réceptrice   :               */
398   /* on parcourt les descripteurs de la chaîne à concaténer :               */
399   /*  - si un descripteur n'a pas un descripteur identique                  */
400   /*     dans la chaîne à concaténer                                        */
401   /*     -> le descripteur de la liste à concaténer prend un nouveau numéro */
402   /*  - sinon                                                               */
403   /*     -> il est supprime de la chaîne à concaténer                       */
404 
405   for (ptr_descr_recept = *descr_recept_tete;
406        ptr_descr_recept != NULL;
407        ptr_descr_recept = ptr_descr_recept->l_descr_sui  ) {
408 
409     ptr_descr_concat = *descr_concat_tete;
410     while (ptr_descr_concat != NULL                          &&
411            ecs_descr__compare(ptr_descr_recept,
412                               ptr_descr_concat) == false    )
413       ptr_descr_concat = ptr_descr_concat->l_descr_sui;
414 
415     if (ptr_descr_concat != NULL) {
416 
417       /* Il y a un descripteur identique dans la chaîne à concaténer */
418 
419       tab_renum_descr_concat.val[ptr_descr_concat->num - 1]
420         = ptr_descr_recept->num - 1;
421 
422       ecs_loc_descr_chaine__supprime(&ptr_descr_concat,
423                                  descr_concat_tete);
424     }
425   }
426 
427   if (*descr_concat_tete != NULL) {
428 
429     /* Les numéros des descripteurs restants de la chaîne à concaténer */
430     /*  sont modifies                                                  */
431 
432     for (ptr_descr_concat = *descr_concat_tete;
433          ptr_descr_concat != NULL;
434          ptr_descr_concat = ptr_descr_concat->l_descr_sui) {
435 
436       tab_renum_descr_concat.val[ptr_descr_concat->num - 1] = cpt_descr;
437       cpt_descr++;
438     }
439 
440     /* On ajoute à la fin de la chaîne réceptrice,          */
441     /*  les descripteurs restants de la chaîne à concaténer */
442 
443     ecs_descr_chaine__ajoute(descr_recept_tete,
444                              *descr_concat_tete);
445   }
446 
447   return tab_renum_descr_concat;
448 }
449 
450 /*----------------------------------------------------------------------------
451  *  Fonction qui affiche les contenus des descripteurs
452  *   de la liste chaînée des descripteurs dont la tête est donnée
453  *----------------------------------------------------------------------------*/
454 
455 void
ecs_descr_chaine__affiche(ecs_descr_t * descr_tete,int decal)456 ecs_descr_chaine__affiche(ecs_descr_t  *descr_tete,
457                           int           decal)
458 {
459   ecs_descr_t  *ptr_descr;
460 
461   /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
462 
463   for (ptr_descr  = descr_tete;
464        ptr_descr != NULL;
465        ptr_descr  = ptr_descr->l_descr_sui) {
466 
467     ecs_descr__affiche(ptr_descr,
468                        decal);
469   }
470 }
471 
472 /*----------------------------------------------------------------------------
473  *  Fonction qui recherche dans une liste chaînée de descripteurs
474  *   dont la tête est donnée,
475  *   un numéro de descripteur donné
476  *
477  *  La fonction renvoie :
478  *  -    le pointeur du descripteur si le numéro de descripteur a été trouve
479  *  - ou NULL                       sinon
480  *----------------------------------------------------------------------------*/
481 
482 ecs_descr_t *
ecs_descr_chaine__cherche_num(ecs_descr_t * descr_tete,int num)483 ecs_descr_chaine__cherche_num(ecs_descr_t  *descr_tete,
484                               int           num)
485 {
486   ecs_descr_t  *ptr_descr;
487 
488   /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
489 
490   assert(descr_tete != NULL);
491 
492   ptr_descr = descr_tete;
493 
494   while (ptr_descr != NULL && ptr_descr->num != num)
495     ptr_descr = ptr_descr->l_descr_sui;
496 
497   return ptr_descr;
498 }
499 
500 /*----------------------------------------------------------------------------
501  *  Fonction qui recherche dans une liste chaînée de descripteurs
502  *   dont la tête est donnée,
503  *   un descripteur ayant les mêmes type, identificateur et nom
504  *   que le descripteur donné
505  *
506  *  La fonction renvoie :
507  *  -    le numéro du descripteur si le descripteur   a     été trouve
508  *  - ou ECS_DESCR_NUM_NUL        si le descripteur n'a pas été trouve
509  *----------------------------------------------------------------------------*/
510 
511 int
ecs_descr_chaine__trouve_num(ecs_descr_t * descr_tete,const ecs_descr_t * descr_rech)512 ecs_descr_chaine__trouve_num(ecs_descr_t        *descr_tete,
513                              const ecs_descr_t  *descr_rech)
514 {
515   ecs_descr_t  *ptr_descr;
516 
517   /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
518 
519   assert(descr_tete != NULL && descr_rech != NULL);
520 
521   ptr_descr = descr_tete;
522 
523   while (   ptr_descr != NULL
524          && ecs_descr__compare(ptr_descr, descr_rech ) == false)
525     ptr_descr = ptr_descr->l_descr_sui;
526 
527   if (ptr_descr != NULL) {
528 
529     return ptr_descr->num;
530 
531   }
532   else {
533 
534     return ECS_DESCR_NUM_NUL;
535 
536   }
537 }
538 
539 /*----------------------------------------------------------------------------
540  *  Fonction qui crée une nouvelle chaîne de descripteurs
541  *   à partir d'une chaîne de descripteurs dont la tête est donnée
542  *  Un descripteur est copié dans la nouvelle chaîne si son numéro
543  *   ne se transforme pas par le vecteur de transformation donné
544  *   en `ECS_DESCR_NUM_NUL'
545  *  Les membres du descripteur sont copies dans le nouveau sans modification
546  *   sauf le numéro qui devient celui transformé par le vecteur
547  *----------------------------------------------------------------------------*/
548 
549 ecs_descr_t *
ecs_descr_chaine__renumerote(ecs_descr_t * descr_tete,const ecs_tab_int_t vect_transf)550 ecs_descr_chaine__renumerote(ecs_descr_t          *descr_tete ,
551                              const ecs_tab_int_t   vect_transf)
552 {
553   size_t        inum;
554 
555   ecs_descr_t  *descr_new;
556   ecs_descr_t  *descr_tete_new;
557   ecs_descr_t  *ptr_descr;        /* Pointeur de boucle sur les descripteurs */
558 
559   /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
560 
561   descr_tete_new = NULL;
562 
563   for (inum = 0; inum < vect_transf.nbr; inum++) {
564 
565     ptr_descr = descr_tete;
566     while (ptr_descr != NULL && vect_transf.val[inum] != (ptr_descr->num - 1))
567       ptr_descr = ptr_descr->l_descr_sui;
568 
569     assert(ptr_descr != NULL);
570 
571     descr_new = ecs_descr__cree(ECS_DESCR_IDE_NUL,
572                                 ptr_descr->nom);
573 
574     ecs_descr_chaine__ajoute(&descr_tete_new,
575                              descr_new);
576 
577   }
578 
579   return descr_tete_new;
580 }
581 
582 /*----------------------------------------------------------------------------
583  *  Fonction qui renvoie le nombre et la liste des pointeurs sur les noms
584  *   des descripteurs de type groupe d'une liste chaînée dont la tête est
585  *   donnée en argument
586  *----------------------------------------------------------------------------*/
587 
588 ecs_tab_char_t
ecs_descr_chaine__ret_nom(ecs_descr_t * descr_tete)589 ecs_descr_chaine__ret_nom(ecs_descr_t   *descr_tete)
590 {
591   ecs_int_t       cpt_descr;
592   ecs_descr_t    *ptr_descr;
593 
594   ecs_tab_char_t  tab_nom_descr_chaine;
595 
596   /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
597 
598   assert(descr_tete != NULL);
599 
600   /* Comptage des descripteurs de type groupe */
601 
602   cpt_descr = 0;
603 
604   for (ptr_descr  = descr_tete;
605        ptr_descr != NULL;
606        ptr_descr  = ptr_descr->l_descr_sui) {
607     assert(ptr_descr->nom != NULL);
608     cpt_descr += 1;
609   }
610 
611   ECS_MALLOC(tab_nom_descr_chaine.val, cpt_descr, char *);
612   tab_nom_descr_chaine.nbr = cpt_descr;
613 
614   /* Construction de la liste des descripteurs de type groupe */
615 
616   cpt_descr = 0;
617 
618   for (ptr_descr  = descr_tete;
619        ptr_descr != NULL;
620        ptr_descr  = ptr_descr->l_descr_sui) {
621     tab_nom_descr_chaine.val[cpt_descr] = ptr_descr->nom;
622     cpt_descr += 1;
623   }
624 
625   return tab_nom_descr_chaine;
626 }
627 
628 /*----------------------------------------------------------------------------
629  *  Fonction qui renvoie la liste des références des descripteurs
630  *   de la liste chaînée des descripteurs dont la tête est donnée
631  *----------------------------------------------------------------------------*/
632 
633 ecs_descr_t **
ecs_descr_chaine__ret_ref(ecs_descr_t * descr_tete,int * nbr_descr)634 ecs_descr_chaine__ret_ref(ecs_descr_t  *descr_tete,
635                           int          *nbr_descr)
636 {
637   ecs_int_t     idescr;
638 
639   ecs_descr_t * * liste_ref_descr;
640   ecs_descr_t   * ptr_descr;
641 
642   /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
643 
644   /* Détermination du nombre de descripteurs de la liste chaînée */
645   /*-------------------------------------------------------------*/
646 
647   *nbr_descr = ecs_descr_chaine__ret_nbr(descr_tete);
648 
649   ECS_MALLOC(liste_ref_descr, *nbr_descr, ecs_descr_t *);
650 
651   idescr = 0;
652 
653   for (ptr_descr  = descr_tete;
654        ptr_descr != NULL;
655        ptr_descr  = ptr_descr->l_descr_sui) {
656 
657     liste_ref_descr[idescr++] = ptr_descr;
658 
659   }
660 
661   return liste_ref_descr;
662 }
663 
664 /*----------------------------------------------------------------------------
665  *  Fonction qui crée une nouvelle chaîne de descripteurs
666  *   à partir d'une chaîne de descripteurs dont la tête est donnée
667  *  Un descripteur est copié dans la nouvelle chaîne si son numéro
668  *   ne se transforme pas par le vecteur de transformation donné
669  *   en `ECS_DESCR_NUM_NUL'
670  *  Les membres du descripteur sont copies dans le nouveau sans modification
671  *   sauf le numéro qui devient celui transformé par le vecteur
672  *----------------------------------------------------------------------------*/
673 
674 ecs_tab_int_t
ecs_descr_chaine__trie(ecs_descr_t * descr_tete)675 ecs_descr_chaine__trie(ecs_descr_t  *descr_tete)
676 {
677   size_t        nbr_descr;
678   size_t        i, j;
679 
680   ecs_descr_t  *ptr_descr;
681   ecs_descr_t  *tab_descr;
682 
683   ecs_tab_int_t  tab_renum;
684 
685   /*xxxxxxxxxxxxxxxxxxxxxxxxxxx Instructions xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
686 
687   nbr_descr = ecs_descr_chaine__ret_nbr(descr_tete);
688 
689   ECS_MALLOC(tab_descr, nbr_descr, ecs_descr_t);
690 
691   for (ptr_descr = descr_tete, i = 0;
692        ptr_descr != NULL;
693        ptr_descr = ptr_descr->l_descr_sui, i++)
694     tab_descr[i] = *ptr_descr;
695 
696   /* Sort descriptors */
697 
698   qsort(tab_descr,
699         nbr_descr,
700         sizeof(ecs_descr_t),
701         _ecs_descr_chaine_compare);
702 
703   tab_renum.nbr = nbr_descr;
704   ECS_MALLOC(tab_renum.val, tab_renum.nbr, ecs_int_t);
705 
706   for (ptr_descr = descr_tete, i = 0;
707        ptr_descr != NULL;
708        ptr_descr = ptr_descr->l_descr_sui, i++) {
709     for (j = 0;
710          j < nbr_descr && ptr_descr->num != tab_descr[j].num;
711          j++);
712     assert(j < nbr_descr);
713     assert(ptr_descr->num <= (int)nbr_descr);
714     tab_renum.val[tab_descr[j].num - 1] = j + 1;
715     ptr_descr->num = j + 1;
716     ptr_descr->nom = tab_descr[j].nom;
717   }
718 
719   ECS_FREE(tab_descr);
720 
721   return tab_renum;
722 }
723 
724 /*----------------------------------------------------------------------------*/
725 
726