Logo AND Algorithmique Numérique Distribuée

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