Logo AND Algorithmique Numérique Distribuée

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