Logo AND Algorithmique Numérique Distribuée

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