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