Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
J'en ai marre de faire des messages detailles. 'Current state' ;)
[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 "DataDesc/datadesc_private.h"
12
13 GRAS_LOG_NEW_DEFAULT_SUBCATEGORY(new,DataDesc);
14
15 static gras_error_t
16 gras_ddt_new(const char            *name,
17              gras_datadesc_type_t **dst) {
18
19   gras_datadesc_type_t *res=malloc(sizeof(gras_datadesc_type_t));
20   if (!res) 
21     RAISE_MALLOC;
22
23   memset(res, 0, sizeof(res));
24   res->name = strdup(name);
25   
26   *dst=res;
27   return no_error;
28 }
29
30 /**
31  * gras_ddt_new_scalar:
32  *
33  * Create a new scalar and give a pointer to it 
34  */
35 gras_error_t 
36 gras_ddt_new_scalar(const char                      *name,
37                     gras_ddt_scalar_type_t           type,
38                     enum e_gras_dd_scalar_encoding   encoding,
39                     gras_datadesc_type_cb_void_t     cb,
40                     gras_datadesc_type_t           **dst) {
41
42   gras_error_t errcode;
43   gras_datadesc_type_t *res;
44   long int arch;
45
46   TRY(gras_ddt_new(name,dst));
47   res=*dst;
48
49   for (arch = 0; arch < gras_arch_count; arch ++) {
50     long int sz;
51     long int mask;
52
53     res->size[arch] = gras_arch_sizes[arch].sizeof_scalars[type];
54     
55     sz = res->size[arch];
56     mask = sz;
57     
58     /* just in case you wonder, x>>1 == x/2 on all architectures when x>=0 and a size is always>=0 */
59
60     /* make sure mask have all the bits under the biggest one of size set to 1
61        Example: size=000100101 => mask=0000111111 */
62     while ((sz >>= 1)) {
63       mask |= sz;
64     }
65     
66     if (res->size[arch] & (mask >> 1)) { /* if size have bits to one beside its biggest */
67       /* size is not a power of 2 */
68       /* alignment= next power of 2 after size */
69       res->alignment[arch] = (res->size[arch] & ~(mask >> 1)) << 1;
70       gras_assert0(res->alignment[arch] != 0,
71                    "scalar type too large");
72       
73       res->aligned_size[arch]    = aligned(res->size[arch], res->alignment[arch]);
74       gras_assert0 (res->aligned_size[arch] >= 0,
75                     "scalar type too large");
76       
77     } else {
78       /* size is a power of 2, life is great */
79       res->alignment[arch]       = res->size[arch];
80       res->aligned_size[arch]    = res->size[arch];
81     }
82
83     /* FIXME size < 0 sometimes? 
84        } else {
85        res->alignment    = 0;
86        res->aligned_size = 0;
87        }
88     */
89   }
90
91   res->category_code                 = e_gras_datadesc_type_cat_scalar;
92   res->category.scalar_data.encoding = encoding;
93
94   res->pre = cb;
95   return no_error;
96 }
97
98
99 /**
100  * gras_dd_cat_field_free:
101  *
102  * Frees one struct or union field
103  */
104 void gras_dd_cat_field_free(void *f) {
105   gras_dd_cat_field_t *field = (gras_dd_cat_field_t *)f;
106   if (field) {
107     if (field->name) 
108       free(field->name);
109     free(field);
110   }
111 }
112
113 /**
114  * gras_ddt_new_struct:
115  *
116  * Create a new struct and give a pointer to it 
117  */
118 gras_error_t 
119 gras_ddt_new_struct(const char                      *name,
120                     gras_datadesc_type_cb_void_t     pre,
121                     gras_datadesc_type_cb_void_t     post,
122                     gras_datadesc_type_t           **dst) {
123
124   gras_error_t errcode;
125   gras_datadesc_type_t *res;
126   long int arch;
127
128   TRY(gras_ddt_new(name,dst));
129   res=*dst;
130
131   for (arch=0; arch<gras_arch_count; arch ++) {
132     res->size[arch]                     = 0;
133     res->alignment[arch]                = 0;
134     res->aligned_size[arch]             = 0;
135   }
136   res->category_code            = e_gras_datadesc_type_cat_struct;
137   TRY(gras_dynar_new(&(res->category.struct_data.fields),
138                      sizeof(gras_dd_cat_field_t*),
139                      &gras_dd_cat_field_free));
140   res->pre                      = pre;
141   res->post                     = post;
142
143   return no_error;
144 }
145
146 /**
147  * gras_ddt_new_struct_append:
148  *
149  * Append a field to the struct
150  */
151 gras_error_t 
152 gras_ddt_new_struct_append(gras_datadesc_type_t            *struct_type,
153                            const char                      *name,
154                            gras_datadesc_type_t            *field_type,
155                            gras_datadesc_type_cb_void_t     pre,
156                            gras_datadesc_type_cb_void_t     post) {
157
158   gras_error_t errcode;
159   gras_dd_cat_field_t *field;
160   int arch;
161
162   gras_assert0(field_type->size >= 0,
163                "Cannot add a dynamically sized field in a structure");
164     
165   field=malloc(sizeof(gras_dd_cat_field_t));
166   if (!field)
167     RAISE_MALLOC;
168
169   field->name   = strdup(name);
170
171   for (arch=0; arch<gras_arch_count; arch ++) {
172     field->offset[arch] = aligned(struct_type->size[arch], field_type->alignment[arch]);
173   }
174   field->code   = field_type->code;
175   field->pre    = pre;
176   field->post   = post;
177   
178   TRY(gras_dynar_push(struct_type->category.struct_data.fields, field));
179
180   for (arch=0; arch<gras_arch_count; arch ++) {
181     struct_type->size[arch]             = field->offset[arch] + field_type->size[arch];
182     struct_type->alignment[arch]        = max(struct_type->alignment[arch], field_type->alignment[arch]);
183     struct_type->aligned_size[arch]     = aligned(struct_type->size[arch], struct_type->alignment[arch]);
184   }
185
186   return no_error;
187 }
188
189 /**
190  * gras_ddt_new_union:
191  *
192  * Create a new union and give a pointer to it 
193  */
194 gras_error_t 
195 gras_ddt_new_union(const char                      *name,
196                    gras_datadesc_type_cb_int_t      field_count,
197                    gras_datadesc_type_cb_void_t     post,
198                    gras_datadesc_type_t           **dst) {
199
200   gras_error_t errcode;
201   gras_datadesc_type_t *res;
202   int arch;
203
204   gras_assert0(field_count,
205                "Attempt to creat an union without field_count function");
206
207   TRY(gras_ddt_new(name,dst));
208   res=*dst;
209
210   for (arch=0; arch<gras_arch_count; arch ++) {
211     res->size[arch]                     = 0;
212     res->alignment[arch]                = 0;
213     res->aligned_size[arch]             = 0;
214   }
215   res->category_code            = e_gras_datadesc_type_cat_union;
216   TRY(gras_dynar_new(&(res->category.union_data.fields),
217                      sizeof(gras_dd_cat_field_t*),
218                      &gras_dd_cat_field_free));
219   res->category.union_data.field_count = field_count;
220   res->pre                      = NULL;
221   res->post                     = post;
222
223   return no_error;
224 }
225
226 /**
227  * gras_ddt_new_union_append:
228  *
229  * Append a field to the union
230  */
231 gras_error_t 
232 gras_ddt_new_union_append(gras_datadesc_type_t            *union_type,
233                           const char                      *name,
234                           gras_datadesc_type_t            *field_type,
235                           gras_datadesc_type_cb_void_t     pre,
236                           gras_datadesc_type_cb_void_t     post) {
237
238   gras_error_t errcode;
239   gras_dd_cat_field_t *field;
240   int arch;
241
242   gras_assert0(field_type->size >= 0,
243                "Cannot add a dynamically sized field in an union");
244     
245   field=malloc(sizeof(gras_dd_cat_field_t));
246   if (!field)
247     RAISE_MALLOC;
248
249   field->name   = strdup(name);
250   for (arch=0; arch<gras_arch_count; arch ++) {
251     field->offset[arch] = 0; /* that's the purpose of union ;) */
252   }
253   field->code   = field_type->code;
254   field->pre    = pre;
255   field->post   = post;
256   
257   TRY(gras_dynar_push(union_type->category.union_data.fields, field));
258
259   for (arch=0; arch<gras_arch_count; arch ++) {
260     union_type->size[arch]         = max(union_type->size[arch], field_type->size[arch]);
261     union_type->alignment[arch]    = max(union_type->alignment[arch], field_type->alignment[arch]);
262     union_type->aligned_size[arch] = aligned(union_type->size[arch], union_type->alignment[arch]);
263   }
264
265   return no_error;
266 }
267
268 /**
269  * gras_ddt_new_ref:
270  *
271  * Create a new ref and give a pointer to it 
272  */
273 gras_error_t 
274 gras_ddt_new_ref(const char                      *name,
275                  gras_datadesc_type_t            *referenced_type,
276                  gras_datadesc_type_cb_int_t      discriminant,
277                  gras_datadesc_type_cb_void_t     post,
278                  gras_datadesc_type_t           **dst) {
279
280   gras_error_t errcode;
281   gras_datadesc_type_t *res;
282   int arch;
283
284   gras_assert0(discriminant || referenced_type,
285                "Attempt to create a generic reference without discriminant");
286
287   TRY(gras_ddt_new(name,dst));
288   res=*dst;
289
290   /* FIXME: Size from bootstraping */
291   for (arch=0; arch<gras_arch_count; arch ++) {
292     res->size[arch]                     = 0;
293     res->alignment[arch]                = 0;
294     res->aligned_size[arch]             = 0;
295   }
296
297   res->category_code            = e_gras_datadesc_type_cat_ref;
298
299   res->category.ref_data.code         = referenced_type ? referenced_type->code : -1;
300   res->category.ref_data.discriminant = discriminant;
301   res->pre                      = NULL;
302   res->post                     = post;
303
304   return no_error;
305 }
306
307 /**
308  * gras_ddt_new_array:
309  *
310  * Create a new array and give a pointer to it 
311  */
312 gras_error_t 
313 gras_ddt_new_array(const char                      *name,
314                    gras_datadesc_type_t            *element_type,
315                    long int                         fixed_size,
316                    gras_datadesc_type_cb_int_t      dynamic_size,
317                    gras_datadesc_type_cb_void_t     post,
318                    gras_datadesc_type_t           **dst) {
319
320   gras_error_t errcode;
321   gras_datadesc_type_t *res;
322   int arch;
323
324   gras_assert0(dynamic_size || fixed_size>0,
325                "Attempt to create a dynamic array without size discriminant");
326
327   TRY(gras_ddt_new(name,dst));
328   res=*dst;
329
330   for (arch=0; arch<gras_arch_count; arch ++) {
331     if (fixed_size <= 0) {
332       res->size[arch] = fixed_size; /* make sure it indicates "dynamic" */
333     } else {
334       res->size[arch] = fixed_size * element_type->aligned_size[arch];
335     }
336     res->alignment[arch]        = element_type->alignment[arch];
337     res->aligned_size[arch]     = fixed_size; /*FIXME: That was so in GS, but looks stupid*/
338   }
339   res->category_code            = e_gras_datadesc_type_cat_array;
340
341   res->category.array_data.code         = element_type->code;
342   res->category.array_data.fixed_size   = fixed_size;
343   res->category.array_data.dynamic_size = dynamic_size;
344
345   res->pre                      = NULL;
346   res->post                     = post;
347
348   return no_error;
349 }
350
351 /**
352  * gras_ddt_new_ignored:
353  *
354  * Create a new ignored field and give a pointer to it. 
355  *
356  * If you give a default value, it will be copied away so that you can free your copy.
357  */
358 gras_error_t 
359 gras_ddt_new_ignored(const char *name,
360                      void *default_value,
361                      void_f_pvoid_t   *free_func,
362                      long int                       size,
363                      long int                       alignment,
364                      gras_datadesc_type_cb_void_t     post,
365                      gras_datadesc_type_t           **dst) {
366   RAISE_UNIMPLEMENTED;
367   /*
368   gras_error_t errcode;
369   gras_datadesc_type_t *res;
370
371   TRY(gras_ddt_new(name,dst));
372   res=*dst;
373
374   res->size             = size > 0?size:0;
375   res->alignment        = alignment;
376
377   if (size > 0) {
378     res->aligned_size   = aligned(size, alignment);
379   } else {
380     res->aligned_size   = 0;
381   }
382
383   if (default_value && res->size) {
384     res->category.ignored_data.default_value = malloc((size_t)size);
385     if (! (res->category.ignored_data.default_value) ) 
386       RAISE_MALLOC;
387     memcpy(res->category.ignored_data.default_value,
388            default_value, (size_t)size);
389   }
390
391   res->category_code = e_gras_datadesc_type_cat_ignored;
392   res->category.ignored_data.free_func = free_func;
393
394   res->post = post;
395
396
397   res->size = size;
398
399   return no_error;
400   */
401 }
402
403 /**
404  * gras_ddt_new_parse:
405  *
406  * Create a datadescription from the result of parsing the C type description
407  */
408 gras_error_t
409 gras_ddt_new_parse(const char            *name,
410                    const char            *C_statement,
411                    gras_datadesc_type_t **dst) {
412   RAISE_UNIMPLEMENTED;
413 }
414
415
416 gras_error_t
417 gras_ddt_new_from_nws(const char           *name,
418                       const DataDescriptor *desc,
419                       size_t                howmany,
420                       gras_datadesc_type_t **dst) {
421   RAISE_UNIMPLEMENTED;
422 }
423
424 /**
425  * gras_ddt_free:
426  *
427  * Frees a datadescription.
428  */
429 void gras_ddt_free(gras_datadesc_type_t **type) {
430   gras_datadesc_type_t *t;
431
432   if (type && *type) {
433     t=*type;
434
435     free(t->name);
436     switch (t->category_code) {
437     case e_gras_datadesc_type_cat_scalar:
438     case e_gras_datadesc_type_cat_ref:
439     case e_gras_datadesc_type_cat_array:
440       /* nothing to free in there */
441       break;
442
443     case e_gras_datadesc_type_cat_ignored:
444       if (t->category.ignored_data.free_func) {
445         t->category.ignored_data.free_func(t->category.ignored_data.default_value);
446       }
447       break;
448
449     case e_gras_datadesc_type_cat_struct:
450       gras_dynar_free(t->category.struct_data.fields);
451       break;
452
453     case e_gras_datadesc_type_cat_union:
454       gras_dynar_free(t->category.union_data.fields);
455       break;
456       
457     default:
458       /* datadesc was invalid. Killing it is like euthanasy, I guess */
459       break;
460     }
461   }
462 }