Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Search msg.h at the right location
[simgrid.git] / src / gras / DataDesc / ddt_create.c
1 /* $Id$ */
2
3 /* ddt_new - creation/deletion of datatypes structs (private to this module)*/
4
5 /* Copyright (c) 2003 Olivier Aumage.                                       */
6 /* Copyright (c) 2003, 2004 Martin Quinson.                                 */
7 /* All rights reserved.                                                     */
8
9 /* This program is free software; you can redistribute it and/or modify it
10  * under the terms of the license (GNU LGPL) which comes with this package. */
11
12 #include "xbt/misc.h" /* min()/max() */
13 #include "gras/DataDesc/datadesc_private.h"
14
15 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(ddt_create,datadesc,"Creating new datadescriptions");
16
17 /**
18  * gras_ddt_freev:
19  *
20  * gime that memory back, dude. I mean it.
21  */
22 void gras_ddt_freev(void *ddt) {
23   gras_datadesc_type_t type= (gras_datadesc_type_t)ddt;
24   
25   if (type) {
26     gras_datadesc_free(&type);
27   }
28 }
29
30 static gras_datadesc_type_t gras_ddt_new(const char *name) {
31   gras_datadesc_type_t res;
32
33   XBT_IN1("(%s)",name);
34   res=xbt_new0(s_gras_datadesc_type_t,1);
35
36   res->name = (char*)strdup(name);
37   res->name_len = strlen(name);
38   res->cycle = 0;
39       
40   xbt_set_add(gras_datadesc_set_local,
41                (xbt_set_elm_t)res,&gras_ddt_freev);
42   XBT_OUT;
43   return res;
44 }
45
46 /**
47  * gras_datadesc_by_name:
48  *
49  * Retrieve a type from its name
50  */
51 gras_datadesc_type_t gras_datadesc_by_name(const char *name) {
52
53   gras_datadesc_type_t type;
54
55   XBT_IN1("(%s)",name);
56   if (xbt_set_get_by_name(gras_datadesc_set_local,
57                            name,(xbt_set_elm_t*)&type) == no_error) {
58     XBT_OUT;
59     return type;
60   } else { 
61     XBT_OUT;
62     return NULL;
63   }
64 }
65
66 /**
67  * gras_datadesc_by_id:
68  *
69  * Retrieve a type from its code
70  */
71 xbt_error_t gras_datadesc_by_id(long int              code,
72                                  gras_datadesc_type_t *type) {
73   XBT_IN;
74   return xbt_set_get_by_id(gras_datadesc_set_local,
75                             code,(xbt_set_elm_t*)type);
76 }
77
78 /**
79  * gras_datadesc_scalar:
80  *
81  * Create a new scalar and give a pointer to it 
82  */
83 gras_datadesc_type_t 
84   gras_datadesc_scalar(const char                      *name,
85                        gras_ddt_scalar_type_t           type,
86                        enum e_gras_dd_scalar_encoding   encoding) {
87
88   gras_datadesc_type_t res;
89   long int arch;
90
91   XBT_IN;
92   res = gras_datadesc_by_name(name);
93   if (res) {
94     xbt_assert1(res->category_code == e_gras_datadesc_type_cat_scalar,
95                  "Redefinition of type %s does not match", name);
96     xbt_assert1(res->category.scalar_data.encoding == encoding,
97                  "Redefinition of type %s does not match", name);
98     xbt_assert1(res->category.scalar_data.type == type,
99                  "Redefinition of type %s does not match", name);
100     VERB1("Discarding redefinition of %s",name);
101     return res;
102   }
103   res = gras_ddt_new(name);
104
105   for (arch = 0; arch < gras_arch_count; arch ++) {
106     res->size[arch]         = gras_arches[arch].sizeofs[type];
107     res->alignment[arch]    = gras_arches[arch].boundaries[type];
108     res->aligned_size[arch] = aligned(res->size[arch], res->alignment[arch]);
109   }
110
111   res->category_code                 = e_gras_datadesc_type_cat_scalar;
112   res->category.scalar_data.encoding = encoding;
113   res->category.scalar_data.type     = type;
114   XBT_OUT;
115   
116   return res;
117 }
118
119
120 /**
121  * gras_dd_cat_field_free:
122  *
123  * Frees one struct or union field
124  */
125 void gras_dd_cat_field_free(void *f) {
126   gras_dd_cat_field_t field = *(gras_dd_cat_field_t *)f;
127   XBT_IN;
128   if (field) {
129     if (field->name) 
130       xbt_free(field->name);
131     xbt_free(field);
132   }
133   XBT_OUT;
134 }
135
136 /**
137  * gras_datadesc_struct:
138  *
139  * Create a new struct and give a pointer to it 
140  */
141 gras_datadesc_type_t 
142   gras_datadesc_struct(const char            *name) {
143
144   gras_datadesc_type_t res;
145   long int arch;
146   
147   XBT_IN1("(%s)",name);
148   res = gras_datadesc_by_name(name);
149   if (res) {
150     /* FIXME: Check that field redefinition matches */
151     xbt_assert1(res->category_code == e_gras_datadesc_type_cat_struct,
152                  "Redefinition of type %s does not match", name);
153     VERB1("Discarding redefinition of %s",name);
154     return res;
155   }
156   res = gras_ddt_new(name);
157
158   for (arch=0; arch<gras_arch_count; arch ++) {
159     res->size[arch] = 0;
160     res->alignment[arch] = 0;
161     res->aligned_size[arch] = 0;
162   }
163   res->category_code = e_gras_datadesc_type_cat_struct;
164   res->category.struct_data.fields = 
165        xbt_dynar_new(sizeof(gras_dd_cat_field_t),
166                       &gras_dd_cat_field_free);
167
168   XBT_OUT;
169   return res;
170 }
171
172 /**
173  * gras_datadesc_struct_append:
174  *
175  * Append a field to the struct
176  */
177 void
178 gras_datadesc_struct_append(gras_datadesc_type_t struct_type,
179                             const char          *name,
180                             gras_datadesc_type_t field_type) {
181
182   gras_dd_cat_field_t field;
183   int arch;
184
185   xbt_assert2(field_type,
186                "Cannot add the field '%s' into struct '%s': its type is NULL. Typo in get_by_name?",
187                name,struct_type->name);
188   XBT_IN3("(%s %s.%s;)",field_type->name,struct_type->name,name);
189   if (struct_type->category.struct_data.closed) {
190     VERB1("Ignoring request to add field to struct %s (closed. Redefinition?)",
191           struct_type->name);
192     return;
193   }
194
195   xbt_assert1(field_type->size != 0,
196                "Cannot add a dynamically sized field in structure %s",
197                struct_type->name);
198     
199   field=xbt_new(s_gras_dd_cat_field_t,1);
200   field->name   = (char*)strdup(name);
201
202   DEBUG0("----------------");
203   DEBUG3("PRE s={size=%ld,align=%ld,asize=%ld}",
204          struct_type->size[GRAS_THISARCH], 
205          struct_type->alignment[GRAS_THISARCH], 
206          struct_type->aligned_size[GRAS_THISARCH]);
207      
208      
209   for (arch=0; arch<gras_arch_count; arch ++) {
210     field->offset[arch] = aligned(struct_type->size[arch],
211                                   field_type->alignment[arch]);
212
213     struct_type->size[arch] = field->offset[arch] + field_type->size[arch];
214     struct_type->alignment[arch] = max(struct_type->alignment[arch],
215                                        field_type->alignment[arch]);
216     struct_type->aligned_size[arch] = aligned(struct_type->size[arch],
217                                               struct_type->alignment[arch]);
218   }
219   field->type   = field_type;
220   field->pre    = NULL;
221   field->post   = NULL;
222   
223   xbt_dynar_push(struct_type->category.struct_data.fields, &field);
224
225   DEBUG3("Push a %s into %s at offset %ld.",
226          field_type->name, struct_type->name,field->offset[GRAS_THISARCH]);
227   DEBUG3("  f={size=%ld,align=%ld,asize=%ld}",
228          field_type->size[GRAS_THISARCH], 
229          field_type->alignment[GRAS_THISARCH], 
230          field_type->aligned_size[GRAS_THISARCH]);
231   DEBUG3("  s={size=%ld,align=%ld,asize=%ld}",
232          struct_type->size[GRAS_THISARCH], 
233          struct_type->alignment[GRAS_THISARCH], 
234          struct_type->aligned_size[GRAS_THISARCH]);
235   XBT_OUT;
236 }
237
238 void
239 gras_datadesc_struct_close(gras_datadesc_type_t struct_type) {
240   XBT_IN;
241   struct_type->category.struct_data.closed = 1;
242   DEBUG4("structure %s closed. size=%ld,align=%ld,asize=%ld",
243          struct_type->name,
244          struct_type->size[GRAS_THISARCH], 
245          struct_type->alignment[GRAS_THISARCH], 
246          struct_type->aligned_size[GRAS_THISARCH]);
247 }
248
249 /**
250  * gras_datadesc_cycle_set:
251  * 
252  * Tell GRAS that the pointers of the type described by @ddt may present
253  * some loop, and that the cycle detection mecanism is needed.
254  *
255  * Note that setting this option when not needed have a rather bad effect 
256  * on the performance (several times slower on big data).
257  */
258 void
259 gras_datadesc_cycle_set(gras_datadesc_type_t ddt) {
260   ddt->cycle = 1;
261 }
262 /**
263  * gras_datadesc_cycle_unset:
264  * 
265  * Tell GRAS that the pointers of the type described by @ddt do not present
266  * any loop and that cycle detection mecanism are not needed.
267  * (default)
268  */
269 void
270 gras_datadesc_cycle_unset(gras_datadesc_type_t ddt) {
271   ddt->cycle = 0;
272 }
273
274 /**
275  * gras_datadesc_union:
276  *
277  * Create a new union and give a pointer to it 
278  */
279 gras_datadesc_type_t 
280 gras_datadesc_union(const char                   *name,
281                     gras_datadesc_type_cb_int_t   selector) {
282
283   gras_datadesc_type_t res;
284   int arch;
285
286   XBT_IN1("(%s)",name);
287   xbt_assert0(selector,
288                "Attempt to creat an union without field_count function");
289
290   res = gras_datadesc_by_name(name);
291   if (res) {
292     /* FIXME: Check that field redefinition matches */
293     xbt_assert1(res->category_code == e_gras_datadesc_type_cat_union,
294                  "Redefinition of type %s does not match", name);
295     xbt_assert1(res->category.union_data.selector == selector,
296                  "Redefinition of type %s does not match", name);
297     VERB1("Discarding redefinition of %s",name);
298     return res;
299   }
300
301   res = gras_ddt_new(name);
302
303   for (arch=0; arch<gras_arch_count; arch ++) {
304      res->size[arch] = 0;
305      res->alignment[arch] = 0;
306      res->aligned_size[arch] = 0;
307   }
308
309   res->category_code            = e_gras_datadesc_type_cat_union;
310   res->category.union_data.fields =
311      xbt_dynar_new(sizeof(gras_dd_cat_field_t*),
312                     &gras_dd_cat_field_free);
313   res->category.union_data.selector = selector;
314
315   return res;
316 }
317
318 /**
319  * gras_datadesc_union_append:
320  *
321  * Append a field to the union
322  */
323 void
324 gras_datadesc_union_append(gras_datadesc_type_t  union_type,
325                            const char           *name,
326                            gras_datadesc_type_t  field_type) {
327
328   gras_dd_cat_field_t field;
329   int arch;
330
331   XBT_IN3("(%s %s.%s;)",field_type->name,union_type->name,name);
332   xbt_assert1(field_type->size != 0,
333                "Cannot add a dynamically sized field in union %s",
334                union_type->name);
335
336   if (union_type->category.union_data.closed) {
337     VERB1("Ignoring request to add field to union %s (closed)",
338            union_type->name);
339     return;
340   }
341     
342   field=xbt_new0(s_gras_dd_cat_field_t,1);
343
344   field->name   = (char*)strdup(name);
345   field->type   = field_type;
346   /* All offset are left to 0 in an union */
347   
348   xbt_dynar_push(union_type->category.union_data.fields, &field);
349
350   for (arch=0; arch<gras_arch_count; arch ++) {
351     union_type->size[arch] = max(union_type->size[arch],
352                                  field_type->size[arch]);
353     union_type->alignment[arch] = max(union_type->alignment[arch],
354                                       field_type->alignment[arch]);
355     union_type->aligned_size[arch] = aligned(union_type->size[arch],
356                                              union_type->alignment[arch]);
357   }
358 }
359
360 void
361 gras_datadesc_union_close(gras_datadesc_type_t union_type) {
362    union_type->category.union_data.closed = 1;
363 }
364 /**
365  * gras_datadesc_ref:
366  *
367  * Create a new ref to a fixed type and give a pointer to it 
368  */
369 gras_datadesc_type_t 
370   gras_datadesc_ref(const char           *name,
371                     gras_datadesc_type_t  referenced_type) {
372
373   gras_datadesc_type_t res;
374   gras_datadesc_type_t pointer_type = gras_datadesc_by_name("data pointer");
375   int arch;
376
377   XBT_IN1("(%s)",name);
378   res = gras_datadesc_by_name(name);
379   if (res) {
380     xbt_assert1(res->category_code == e_gras_datadesc_type_cat_ref,
381                  "Redefinition of %s does not match",name);
382     xbt_assert1(res->category.ref_data.type == referenced_type,
383                  "Redefinition of %s does not match",name);
384     xbt_assert1(res->category.ref_data.selector == NULL,
385                  "Redefinition of %s does not match",name);
386     VERB1("Discarding redefinition of %s",name);
387     return res;
388   }
389
390   res = gras_ddt_new(name);
391
392   xbt_assert0(pointer_type, "Cannot get the description of data pointer");
393       
394   for (arch=0; arch<gras_arch_count; arch ++){
395     res->size[arch] = pointer_type->size[arch];
396     res->alignment[arch] = pointer_type->alignment[arch];
397     res->aligned_size[arch] = pointer_type->aligned_size[arch];
398   }
399   
400   res->category_code              = e_gras_datadesc_type_cat_ref;
401   res->category.ref_data.type     = referenced_type;
402   res->category.ref_data.selector = NULL;
403
404   return res;
405 }
406 /**
407  * gras_datadesc_ref_generic:
408  *
409  * Create a new ref to a type given at use time, and give a pointer to it 
410  */
411 gras_datadesc_type_t 
412   gras_datadesc_ref_generic(const char                *name,
413                             gras_datadesc_selector_t   selector) {
414
415   gras_datadesc_type_t res;
416   gras_datadesc_type_t pointer_type = gras_datadesc_by_name("data pointer");
417   int arch;
418
419   XBT_IN1("(%s)",name);
420   res = gras_datadesc_by_name(name);
421   if (res) {
422     xbt_assert1(res->category_code == e_gras_datadesc_type_cat_ref,
423                  "Redefinition of type %s does not match", name);
424     xbt_assert1(res->category.ref_data.type == NULL,
425                  "Redefinition of type %s does not match", name);
426     xbt_assert1(res->category.ref_data.selector == selector,
427                  "Redefinition of type %s does not match", name);
428     VERB1("Discarding redefinition of %s",name);
429     return res;
430   }
431   res = gras_ddt_new(name);
432
433   xbt_assert0(pointer_type, "Cannot get the description of data pointer");
434       
435   for (arch=0; arch<gras_arch_count; arch ++) {
436     res->size[arch] = pointer_type->size[arch];
437     res->alignment[arch] = pointer_type->alignment[arch];
438     res->aligned_size[arch] = pointer_type->aligned_size[arch];
439   }
440
441   res->category_code            = e_gras_datadesc_type_cat_ref;
442
443   res->category.ref_data.type     = NULL;
444   res->category.ref_data.selector = selector;
445
446   return res;
447 }
448
449 /**
450  * gras_datadesc_array_fixed:
451  *
452  * Create a new array and give a pointer to it 
453  */
454 gras_datadesc_type_t 
455   gras_datadesc_array_fixed(const char           *name,
456                             gras_datadesc_type_t  element_type,
457                             long int              fixed_size) {
458
459   gras_datadesc_type_t res;
460   int arch;
461
462   XBT_IN1("(%s)",name);
463   res = gras_datadesc_by_name(name);
464   if (res) {
465     xbt_assert1(res->category_code == e_gras_datadesc_type_cat_array,
466                  "Redefinition of type %s does not match", name);
467     xbt_assert1(res->category.array_data.type == element_type,
468                  "Redefinition of type %s does not match", name);
469     xbt_assert1(res->category.array_data.fixed_size == fixed_size,
470                  "Redefinition of type %s does not match", name);
471     xbt_assert1(res->category.array_data.dynamic_size == NULL,
472                  "Redefinition of type %s does not match", name);
473     VERB1("Discarding redefinition of %s",name);
474
475     return res;
476   }
477   res = gras_ddt_new(name);
478
479   xbt_assert1(fixed_size > 0, "'%s' is a array of null fixed size",name);
480   for (arch=0; arch<gras_arch_count; arch ++) {
481     res->size[arch] = fixed_size * element_type->aligned_size[arch];
482     res->alignment[arch] = element_type->alignment[arch];
483     res->aligned_size[arch] = res->size[arch];
484   }  
485
486   res->category_code            = e_gras_datadesc_type_cat_array;
487
488   res->category.array_data.type         = element_type;
489   res->category.array_data.fixed_size   = fixed_size;
490   res->category.array_data.dynamic_size = NULL;
491
492   return res;
493 }
494 /**
495  * gras_datadesc_array_dyn:
496  *
497  * Create a new array and give a pointer to it 
498  */
499 gras_datadesc_type_t 
500   gras_datadesc_array_dyn(const char                  *name,
501                           gras_datadesc_type_t         element_type,
502                           gras_datadesc_type_cb_int_t  dynamic_size) {
503
504   gras_datadesc_type_t res;
505   int arch;
506
507   XBT_IN1("(%s)",name);
508   xbt_assert1(dynamic_size,
509                "'%s' is a dynamic array without size discriminant",
510                name);
511
512   res = gras_datadesc_by_name(name);
513   if (res) {
514     xbt_assert1(res->category_code == e_gras_datadesc_type_cat_array,
515                  "Redefinition of type %s does not match", name);
516     xbt_assert1(res->category.array_data.type == element_type,
517                  "Redefinition of type %s does not match", name);
518     xbt_assert1(res->category.array_data.fixed_size == 0,
519                  "Redefinition of type %s does not match", name);
520     xbt_assert1(res->category.array_data.dynamic_size == dynamic_size,
521                  "Redefinition of type %s does not match", name);
522     VERB1("Discarding redefinition of %s",name);
523
524     return res;
525   }
526
527   res = gras_ddt_new(name);
528
529   for (arch=0; arch<gras_arch_count; arch ++) {
530     res->size[arch] = 0; /* make sure it indicates "dynamic" */
531     res->alignment[arch] = element_type->alignment[arch];
532     res->aligned_size[arch] = 0; /*FIXME: That was so in GS, but looks stupid*/
533   }
534
535   res->category_code            = e_gras_datadesc_type_cat_array;
536
537   res->category.array_data.type         = element_type;
538   res->category.array_data.fixed_size   = 0;
539   res->category.array_data.dynamic_size = dynamic_size;
540
541   return res;
542 }
543
544 /**
545  * gras_datadesc_ref_pop_arr:
546  *
547  * Most of the time, you want to include a reference in your structure which
548  * is a pointer to a dynamic array whose size is fixed by another field of 
549  * your structure.
550  *
551  * This case pops up so often that this function was created to take care of
552  * this case. It creates a dynamic array type whose size is poped from the 
553  * current cbps, and then create a reference to it.
554  *
555  * The name of the created datatype will be the name of the element type, with
556  * '[]*' appended to it.
557  *
558  * Then to use it, you just have to make sure that your structure pre-callback
559  * does push the size of the array in the cbps (using #gras_cbps_i_push), and 
560  * you are set. 
561  *
562  * But be remember that this is a stack. If you have two different pop_arr, you
563  * should push the second one first, so that the first one is on the top of the 
564  * list when the first field gets transfered.
565  *
566  */
567 gras_datadesc_type_t 
568   gras_datadesc_ref_pop_arr(gras_datadesc_type_t element_type) {
569
570   gras_datadesc_type_t res;
571   char *name=(char*)xbt_malloc(strlen(element_type->name) + 4);
572
573   sprintf(name,"%s[]",element_type->name);
574
575   res = gras_datadesc_array_dyn(name,element_type,
576                                 gras_datadesc_cb_pop);
577
578   sprintf(name,"%s[]*",element_type->name);
579   res = gras_datadesc_ref(name,res);
580
581   xbt_free(name);
582
583   return res;
584 }
585 xbt_error_t
586 gras_datadesc_import_nws(const char           *name,
587                          const DataDescriptor *desc,
588                          unsigned long         howmany,
589                /* OUT */ gras_datadesc_type_t *dst) {
590   RAISE_UNIMPLEMENTED;
591 }
592
593 /**
594  * gras_datadesc_cb_send:
595  *
596  * Add a pre-send callback to this datadesc.
597  * (useful to push the sizes of the upcoming arrays, for example)
598  */
599 void gras_datadesc_cb_send (gras_datadesc_type_t          type,
600                             gras_datadesc_type_cb_void_t  send) {
601   type->send = send;
602 }
603 /**
604  * gras_datadesc_cb_recv:
605  *
606  * Add a post-receive callback to this datadesc.
607  * (useful to put the function pointers to the rigth value, for example)
608  */
609 void gras_datadesc_cb_recv(gras_datadesc_type_t          type,
610                            gras_datadesc_type_cb_void_t  recv) {
611   type->recv = recv;
612 }
613 /**
614  * gras_dd_find_field:
615  * 
616  * Returns the type descriptor of the given field. Abort on error.
617  */
618 static gras_datadesc_type_t 
619   gras_dd_find_field(gras_datadesc_type_t  type,
620                      const char           *field_name) {
621    xbt_dynar_t         field_array;
622    
623    gras_dd_cat_field_t  field=NULL;
624    int                  field_num;
625    
626    if (type->category_code == e_gras_datadesc_type_cat_union) {
627       field_array = type->category.union_data.fields;
628    } else if (type->category_code == e_gras_datadesc_type_cat_struct) {
629       field_array = type->category.struct_data.fields;
630    } else {
631       ERROR2("%s (%p) is not a struct nor an union. There is no field.", type->name,(void*)type);
632       xbt_abort();
633    }
634    xbt_dynar_foreach(field_array,field_num,field) {
635       if (!strcmp(field_name,field->name)) {
636          return field->type;
637       }
638    }
639    ERROR2("No field nammed %s in %s",field_name,type->name);
640    xbt_abort();
641
642 }
643                                   
644 /**
645  * gras_datadesc_cb_field_send:
646  *
647  * Add a pre-send callback to the given field of the datadesc (which must be a struct or union).
648  * (useful to push the sizes of the upcoming arrays, for example)
649  */
650 void gras_datadesc_cb_field_send (gras_datadesc_type_t          type,
651                                   const char                   *field_name,
652                                   gras_datadesc_type_cb_void_t  send) {
653    
654    gras_datadesc_type_t sub_type=gras_dd_find_field(type,field_name);   
655    sub_type->send = send;
656 }
657
658 /**
659  * gras_datadesc_cb_field_push:
660  *
661  * Add a pre-send callback to the given field resulting in its value to be pushed to
662  * the stack of sizes. It must be a int, unsigned int, long int or unsigned long int.
663  */
664 void gras_datadesc_cb_field_push (gras_datadesc_type_t  type,
665                                   const char           *field_name) {
666    
667    gras_datadesc_type_t sub_type=gras_dd_find_field(type,field_name);
668    if (!strcmp("int",sub_type->name)) {
669       sub_type->send = gras_datadesc_cb_push_int;
670    } else if (!strcmp("unsigned int",sub_type->name)) {
671       sub_type->send = gras_datadesc_cb_push_uint;
672    } else if (!strcmp("long int",sub_type->name)) {
673       sub_type->send = gras_datadesc_cb_push_lint;
674    } else if (!strcmp("unsigned long int",sub_type->name)) {
675       sub_type->send = gras_datadesc_cb_push_ulint;
676    } else {
677       ERROR1("Field %s is not an int, unsigned int, long int neither unsigned long int",
678              sub_type->name);
679       xbt_abort();
680    }
681 }
682 /**
683  * gras_datadesc_cb_field_recv:
684  *
685  * Add a post-receive callback to the given field of the datadesc (which must be a struct or union).
686  * (useful to put the function pointers to the right value, for example)
687  */
688 void gras_datadesc_cb_field_recv(gras_datadesc_type_t          type,
689                                  const char                   *field_name,
690                                  gras_datadesc_type_cb_void_t  recv) {
691    
692    gras_datadesc_type_t sub_type=gras_dd_find_field(type,field_name);   
693    sub_type->recv = recv;
694 }
695
696 /**
697  * gras_datadesc_free:
698  *
699  * Free a datadesc. Should only be called at xbt_exit. 
700  */
701 void gras_datadesc_free(gras_datadesc_type_t *type) {
702
703   DEBUG1("Let's free ddt %s",(*type)->name);
704   
705   switch ((*type)->category_code) {
706   case e_gras_datadesc_type_cat_scalar:
707   case e_gras_datadesc_type_cat_ref:
708   case e_gras_datadesc_type_cat_array:
709     /* nothing to free in there */
710     break;
711     
712   case e_gras_datadesc_type_cat_ignored:
713     if ((*type)->category.ignored_data.free_func) {
714       (*type)->category.ignored_data.free_func
715         ((*type)->category.ignored_data.default_value);
716     }
717     break;
718     
719   case e_gras_datadesc_type_cat_struct:
720     xbt_dynar_free(&( (*type)->category.struct_data.fields ));
721     break;
722     
723   case e_gras_datadesc_type_cat_union:
724     xbt_dynar_free(&( (*type)->category.union_data.fields ));
725     break;
726     
727   default:
728     /* datadesc was invalid. Killing it is like euthanasy, I guess */
729     break;
730   }
731   xbt_free((*type)->name);
732   xbt_free(*type);
733   type=NULL;
734 }
735
736 /**
737  * gras_datadesc_type_cmp:
738  *
739  * Compares two datadesc types with the same semantic than strcmp.
740  *
741  * This comparison does not take the set headers into account (name and ID), 
742  * but only the payload (actual type description).
743  */
744 int gras_datadesc_type_cmp(const gras_datadesc_type_t d1,
745                            const gras_datadesc_type_t d2) {
746   int ret,cpt;
747   gras_dd_cat_field_t field1,field2;
748   gras_datadesc_type_t field_desc_1,field_desc_2;
749
750   if (d1 == d2) return 0; /* easy optimization */
751
752   if (!d1 && d2) {
753     DEBUG0("ddt_cmp: !d1 && d2 => 1");
754     return 1;
755   }
756   if (!d1 && !d2) {
757     DEBUG0("ddt_cmp: !d1 && !d2 => 0");
758     return 0;
759   }
760   if ( d1 && !d2) {
761     DEBUG0("ddt_cmp: d1 && !d2 => -1");
762     return -1;
763   }
764
765   for (cpt=0; cpt<gras_arch_count; cpt++) {
766     if (d1->size[cpt] != d2->size[cpt]) {
767       DEBUG5("ddt_cmp: %s->size=%ld  !=  %s->size=%ld (on %s)",
768              d1->name,d1->size[cpt],d2->name,d2->size[cpt],
769              gras_arches[cpt].name);
770       return d1->size[cpt] >  d2->size[cpt] ? 1 : -1;
771     }
772
773     if (d1->alignment[cpt] != d2->alignment[cpt]) {
774       DEBUG5("ddt_cmp: %s->alignment=%ld  !=  %s->alignment=%ld (on %s)",
775              d1->name,d1->alignment[cpt],d2->name,d2->alignment[cpt],
776              gras_arches[cpt].name);
777       return d1->alignment[cpt] > d2->alignment[cpt] ? 1 : -1;
778     }
779
780     if (d1->aligned_size[cpt] != d2->aligned_size[cpt]) {
781       DEBUG5("ddt_cmp: %s->aligned_size=%ld  !=  %s->aligned_size=%ld (on %s)",
782              d1->name,d1->aligned_size[cpt],d2->name,d2->aligned_size[cpt],
783              gras_arches[cpt].name);
784       return d1->aligned_size[cpt] > d2->aligned_size[cpt] ? 1 : -1;
785     }
786   }
787
788   if (d1->category_code != d2->category_code) {
789     DEBUG4("ddt_cmp: %s->cat=%s  !=  %s->cat=%s",
790            d1->name,gras_datadesc_cat_names[d1->category_code],
791            d2->name,gras_datadesc_cat_names[d2->category_code]);
792     return d1->category_code > d2->category_code ? 1 : -1;
793   }
794
795   if (d1->send != d2->send) {
796     DEBUG4("ddt_cmp: %s->send=%p  !=  %s->send=%p",
797            d1->name,(void*)d1->send, d2->name,(void*)d2->send);
798     return 1; /* ISO C forbids ordered comparisons of pointers to functions */
799   }
800
801   if (d1->recv != d2->recv) {
802     DEBUG4("ddt_cmp: %s->recv=%p  !=  %s->recv=%p",
803            d1->name,(void*)d1->recv, d2->name,(void*)d2->recv);
804     return 1; /* ISO C forbids ordered comparisons of pointers to functions */
805   }
806
807   switch (d1->category_code) {
808   case e_gras_datadesc_type_cat_scalar:
809     if (d1->category.scalar_data.encoding != d2->category.scalar_data.encoding)
810       return d1->category.scalar_data.encoding > d2->category.scalar_data.encoding ? 1 : -1 ;
811     break;
812     
813   case e_gras_datadesc_type_cat_struct:    
814     if (xbt_dynar_length(d1->category.struct_data.fields) != 
815         xbt_dynar_length(d2->category.struct_data.fields)) {
816       DEBUG4("ddt_cmp: %s (having %lu fields) !=  %s (having %lu fields)",
817              d1->name, xbt_dynar_length(d1->category.struct_data.fields),
818              d2->name, xbt_dynar_length(d2->category.struct_data.fields));
819       
820       return xbt_dynar_length(d1->category.struct_data.fields) >
821         xbt_dynar_length(d2->category.struct_data.fields) ?
822         1 : -1;
823     }
824     xbt_dynar_foreach(d1->category.struct_data.fields, cpt, field1) {
825       
826       field2 = xbt_dynar_get_as(d2->category.struct_data.fields, cpt, gras_dd_cat_field_t);
827       field_desc_1 = field1->type;
828       field_desc_2 = field2->type;
829       ret = gras_datadesc_type_cmp(field_desc_1,field_desc_2);
830       if (ret) {
831         DEBUG6("%s->field[%d]=%s != %s->field[%d]=%s",
832                d1->name,cpt,field1->name,              
833                d2->name,cpt,field2->name);
834         return ret;
835       }
836       
837     }
838     break;
839     
840   case e_gras_datadesc_type_cat_union:
841     if (d1->category.union_data.selector != d2->category.union_data.selector) 
842       return 1;  /* ISO C forbids ordered comparisons of pointers to functions */
843     
844     if (xbt_dynar_length(d1->category.union_data.fields) != 
845         xbt_dynar_length(d2->category.union_data.fields))
846       return xbt_dynar_length(d1->category.union_data.fields) >
847              xbt_dynar_length(d2->category.union_data.fields) ?
848         1 : -1;
849     
850     xbt_dynar_foreach(d1->category.union_data.fields, cpt, field1) {
851       
852       field2 = xbt_dynar_get_as(d2->category.union_data.fields, cpt, gras_dd_cat_field_t);
853       field_desc_1 = field1->type;
854       field_desc_2 = field2->type;
855       ret = gras_datadesc_type_cmp(field_desc_1,field_desc_2);
856       if (ret)
857         return ret;
858       
859     }
860     break;
861     
862     
863   case e_gras_datadesc_type_cat_ref:
864     if (d1->category.ref_data.selector != d2->category.ref_data.selector) 
865       return 1; /* ISO C forbids ordered comparisons of pointers to functions */
866     
867     if (d1->category.ref_data.type != d2->category.ref_data.type) 
868       return d1->category.ref_data.type > d2->category.ref_data.type ? 1 : -1;
869     break;
870     
871   case e_gras_datadesc_type_cat_array:
872     if (d1->category.array_data.type != d2->category.array_data.type) 
873       return d1->category.array_data.type > d2->category.array_data.type ? 1 : -1;
874     
875     if (d1->category.array_data.fixed_size != d2->category.array_data.fixed_size) 
876       return d1->category.array_data.fixed_size > d2->category.array_data.fixed_size ? 1 : -1;
877     
878     if (d1->category.array_data.dynamic_size != d2->category.array_data.dynamic_size) 
879       return 1; /* ISO C forbids ordered comparisons of pointers to functions */
880     
881     break;
882     
883   case e_gras_datadesc_type_cat_ignored:
884     /* That's ignored... */
885   default:
886     /* two stupidly created ddt are equally stupid ;) */
887     break;
888   }
889   return 0;
890   
891 }