Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
* Change the semantic of gras_datadesc_by_name() to raise an exception when
[simgrid.git] / src / gras / DataDesc / ddt_parse.c
1 /* $Id$ */
2
3 /* DataDesc/ddt_parse.c -- automatic parsing of data structures             */
4
5 /* Copyright (c) 2003 Arnaud Legrand.                                       */
6 /* Copyright (c) 2003, 2004 Martin Quinson.                                 */
7 /* All rights reserved.                                                     */
8
9 /* This program is free software; you can redistribute it and/or modify it
10  * under the terms of the license (GNU LGPL) which comes with this package. */
11
12 #include <ctype.h> /* isdigit */
13
14 #include "xbt/ex.h"
15 #include "gras/DataDesc/datadesc_private.h"
16 #include "gras/DataDesc/ddt_parse.yy.h"
17
18 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(gras_ddt_parse,gras_ddt,
19   "Parsing C data structures to build GRAS data description");
20
21 typedef struct s_type_modifier{
22   short is_long;
23   int is_unsigned:1;
24   int is_short:1;
25
26   int is_struct:1;
27   int is_union:1;
28   int is_enum:1;
29
30   int is_ref:1;
31    
32   int is_dynar:2;
33   int is_matrix:2;
34 } s_type_modifier_t,*type_modifier_t;
35
36 typedef struct s_field {
37   gras_datadesc_type_t type;
38   char *type_name;
39   char *name;
40   s_type_modifier_t tm;
41 } s_identifier_t;
42  
43 extern char *gras_ddt_parse_text; /* text being considered in the parser */
44
45 /* local functions */
46 static void parse_type_modifier(type_modifier_t type_modifier)  {
47   XBT_IN;
48   do {
49     if (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_STAR) {
50       /* This only used when parsing 'short *' since this function returns when int, float, double,... is encountered */
51       DEBUG0("This is a reference"); 
52       type_modifier->is_ref++;
53       
54     } else if (!strcmp(gras_ddt_parse_text,"unsigned")) {
55       DEBUG0("This is an unsigned");
56       type_modifier->is_unsigned = 1;
57       
58     } else if (!strcmp(gras_ddt_parse_text,"short")) {
59       DEBUG0("This is short");
60       type_modifier->is_short = 1;
61       
62     } else if (!strcmp(gras_ddt_parse_text,"long")) {
63       DEBUG0("This is long");
64       type_modifier->is_long++; /* handle "long long" */
65       
66     } else if (!strcmp(gras_ddt_parse_text,"struct")) {
67       DEBUG0("This is a struct");
68       type_modifier->is_struct = 1;
69       
70     } else if (!strcmp(gras_ddt_parse_text,"union")) {
71       DEBUG0("This is an union");
72       type_modifier->is_union = 1;
73       
74     } else if (!strcmp(gras_ddt_parse_text,"enum")) {
75       DEBUG0("This is an enum");
76       type_modifier->is_enum = 1;
77       
78     } else if (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_EMPTY) {
79       DEBUG0("Pass space");
80
81     } else {
82       DEBUG1("Done with modifiers (got %s)",gras_ddt_parse_text);
83       break;
84     }
85
86     gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
87     if((gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_WORD) && 
88        (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_STAR)) {
89       DEBUG2("Done with modifiers (got %s,%d)",gras_ddt_parse_text,gras_ddt_parse_tok_num);      
90       break;
91     }
92   } while(1);
93   XBT_OUT;
94 }
95
96 static void print_type_modifier(s_type_modifier_t tm) {
97   int i;
98
99   XBT_IN;
100   if (tm.is_unsigned)             printf("(unsigned) ");
101   if (tm.is_short)                printf("(short) ");
102   for (i=0 ; i<tm.is_long ; i++)  printf("(long) ");
103
104   if(tm.is_struct)                printf("(struct) ");
105   if(tm.is_enum)                  printf("(enum) ");
106   if(tm.is_union)                 printf("(union) ");
107
108   for (i=0 ; i<tm.is_ref ; i++)   printf("(ref) ");
109   XBT_OUT;
110 }
111
112 static void change_to_fixed_array(xbt_dynar_t dynar, long int size) {
113   s_identifier_t former,array;
114   memset(&array,0,sizeof(array));
115
116   XBT_IN;
117   xbt_dynar_pop(dynar,&former);
118   array.type_name=(char*)xbt_malloc(strlen(former.type->name)+48);
119   DEBUG2("Array specification (size=%ld, elm='%s'), change pushed type",
120          size,former.type_name);
121   sprintf(array.type_name,"%s%s%s%s[%ld]",
122           (former.tm.is_unsigned?"u ":""),
123           (former.tm.is_short?"s ":""),
124           (former.tm.is_long?"l ":""),
125           former.type_name,
126           size);
127   free(former.type_name);
128
129   array.type = gras_datadesc_array_fixed(array.type_name, former.type, size); /* redeclaration are ignored */
130   array.name = former.name;
131
132   xbt_dynar_push(dynar,&array);
133   XBT_OUT;
134 }
135 static void change_to_ref(xbt_dynar_t dynar) {
136   s_identifier_t former,ref;
137   memset(&ref,0,sizeof(ref));
138
139   XBT_IN;
140   xbt_dynar_pop(dynar,&former);
141   ref.type_name=(char*)xbt_malloc(strlen(former.type->name)+2);
142   DEBUG1("Ref specification (elm='%s'), change pushed type", former.type_name);
143   sprintf(ref.type_name,"%s*",former.type_name);
144   free(former.type_name);
145
146   ref.type = gras_datadesc_ref(ref.type_name, former.type); /* redeclaration are ignored */
147   ref.name = former.name;
148
149   xbt_dynar_push(dynar,&ref);
150   XBT_OUT;
151 }
152
153 static void change_to_ref_pop_array(xbt_dynar_t dynar) {
154   s_identifier_t former,ref;
155   memset(&ref,0,sizeof(ref));
156
157   XBT_IN;
158   xbt_dynar_pop(dynar,&former);
159   ref.type = gras_datadesc_ref_pop_arr(former.type); /* redeclaration are ignored */
160   ref.type_name = (char*)strdup(ref.type->name);
161   ref.name = former.name;
162
163   free(former.type_name);
164
165   xbt_dynar_push(dynar,&ref);
166   XBT_OUT;
167 }
168
169 static void change_to_dynar_of(xbt_dynar_t dynar,gras_datadesc_type_t subtype) {
170   s_identifier_t former,ref;
171   memset(&ref,0,sizeof(ref));
172
173   XBT_IN;
174   xbt_dynar_pop(dynar,&former);
175   ref.type = gras_datadesc_dynar(subtype,NULL); /* redeclaration are ignored */
176   ref.type_name = (char*)strdup(ref.type->name);
177   ref.name = former.name;
178
179   free(former.type_name);
180
181   xbt_dynar_push(dynar,&ref);
182   XBT_OUT;
183 }
184
185 static void change_to_matrix_of(xbt_dynar_t dynar,gras_datadesc_type_t subtype) {
186   s_identifier_t former,ref;
187   memset(&ref,0,sizeof(ref));
188
189   XBT_IN;
190   xbt_dynar_pop(dynar,&former);
191   ref.type = gras_datadesc_matrix(subtype,NULL); /* redeclaration are ignored */
192   ref.type_name = (char*)strdup(ref.type->name);
193   ref.name = former.name;
194
195   free(former.type_name);
196
197   xbt_dynar_push(dynar,&ref);
198   XBT_OUT;
199 }
200
201 static void add_free_f(xbt_dynar_t dynar,void_f_pvoid_t free_f) {
202   s_identifier_t former,ref;
203   memset(&ref,0,sizeof(ref));
204
205   XBT_IN;
206   xbt_dynar_pop(dynar,&former);
207   memcpy(former.type->extra,&free_f, sizeof(free_f));
208   xbt_dynar_push(dynar,&former);
209   XBT_OUT;
210 }
211
212 static void parse_statement(char         *definition,
213                             xbt_dynar_t  identifiers,
214                             xbt_dynar_t  fields_to_push) {
215   char buffname[512];
216
217   s_identifier_t identifier;
218
219   int expect_id_separator = 0;
220
221   XBT_IN;
222   memset(&identifier,0,sizeof(identifier));
223
224   gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
225   if(gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_RA) {
226     XBT_OUT;
227     THROW0(mismatch_error,0,"End of the englobing structure or union");
228   }
229   
230   if (XBT_LOG_ISENABLED(gras_ddt_parse,xbt_log_priority_debug)) {
231     int colon_pos;
232     for (colon_pos = gras_ddt_parse_col_pos;
233          definition[colon_pos] != ';';
234          colon_pos++);
235     definition[colon_pos] = '\0';
236     DEBUG3("Parse the statement \"%s%s;\" (col_pos=%d)",
237            gras_ddt_parse_text,
238            definition+gras_ddt_parse_col_pos,
239            gras_ddt_parse_col_pos);
240     definition[colon_pos] = ';';
241   }
242
243   if(gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_WORD)
244     PARSE_ERROR1("Unparsable symbol: found a typeless statement (got '%s' instead)",
245                  gras_ddt_parse_text);
246
247   /**** get the type modifier of this statement ****/
248   parse_type_modifier(&identifier.tm);
249
250   /*  FIXME: This does not detect recursive definitions at all? */
251   if (identifier.tm.is_union || identifier.tm.is_enum || identifier.tm.is_struct)
252     PARSE_ERROR0("Cannot handle recursive type definition yet");
253
254   /**** get the base type, giving "short a" the needed love ****/
255   if (!identifier.tm.is_union &&
256       !identifier.tm.is_enum  && 
257       !identifier.tm.is_struct &&
258
259       (identifier.tm.is_short || identifier.tm.is_long || identifier.tm.is_unsigned) &&
260
261       strcmp(gras_ddt_parse_text,"char") && 
262       strcmp(gras_ddt_parse_text,"float") && 
263       strcmp(gras_ddt_parse_text,"double") && 
264       strcmp(gras_ddt_parse_text,"int") ) {
265
266     /* bastard user, they omited "int" ! */
267     identifier.type_name=(char*)strdup("int");
268     DEBUG0("the base type is 'int', which were omited (you vicious user)");
269   } else {
270     identifier.type_name=(char*)strdup(gras_ddt_parse_text);
271     DEBUG1("the base type is '%s'",identifier.type_name);
272     gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump(); 
273   }
274
275   /**** build the base type for latter use ****/
276   if (identifier.tm.is_union) {
277     PARSE_ERROR0("Cannot handle union yet (get callback from annotation?)");
278
279   } else if (identifier.tm.is_enum) {
280     PARSE_ERROR0("Cannot handle enum yet");
281
282   } else if (identifier.tm.is_struct) {
283     sprintf(buffname,"struct %s",identifier.type_name);
284     identifier.type = gras_datadesc_struct(buffname); /* Get created when does not exist */
285
286   } else if (identifier.tm.is_unsigned) {
287     if (!strcmp(identifier.type_name,"int")) {
288       if (identifier.tm.is_long == 2) {
289         identifier.type = gras_datadesc_by_name("unsigned long long int");
290       } else if (identifier.tm.is_long) {
291         identifier.type = gras_datadesc_by_name("unsigned long int");
292       } else if (identifier.tm.is_short) {
293         identifier.type = gras_datadesc_by_name("unsigned short int");
294       } else {
295         identifier.type = gras_datadesc_by_name("unsigned int");
296       }
297
298     } else if (!strcmp(identifier.type_name, "char")) {
299       identifier.type = gras_datadesc_by_name("unsigned char");
300
301     } else { /* impossible, gcc parses this shit before us */
302       THROW_IMPOSSIBLE;
303     }
304     
305   } else if (!strcmp(identifier.type_name, "float")) {
306     /* no modificator allowed by gcc */
307     identifier.type = gras_datadesc_by_name("float");
308
309   } else if (!strcmp(identifier.type_name, "double")) {
310     if (identifier.tm.is_long)
311       PARSE_ERROR0("long double not portable and thus not handled");
312
313     identifier.type = gras_datadesc_by_name("double");
314
315   } else { /* signed integer elemental */
316     if (!strcmp(identifier.type_name,"int")) {
317       if (identifier.tm.is_long == 2) {
318         identifier.type = gras_datadesc_by_name("signed long long int");
319       } else if (identifier.tm.is_long) {
320         identifier.type = gras_datadesc_by_name("signed long int");
321       } else if (identifier.tm.is_short) {
322         identifier.type = gras_datadesc_by_name("signed short int");
323       } else {
324         identifier.type = gras_datadesc_by_name("int");
325       }
326
327     } else if (!strcmp(identifier.type_name, "char")) {
328       identifier.type = gras_datadesc_by_name("char");
329
330     } else { 
331       DEBUG1("Base type is a constructed one (%s)",identifier.type_name);
332       if (!strcmp(identifier.type_name,"xbt_matrix_t")) {
333          identifier.tm.is_matrix = 1;
334       } else if (!strcmp(identifier.type_name,"xbt_dynar_t")) {
335          identifier.tm.is_dynar = 1;
336       } else {       
337          identifier.type = gras_datadesc_by_name(identifier.type_name);
338          if (!identifier.type)
339            PARSE_ERROR1("Unknown base type '%s'",identifier.type_name);
340       }
341     }
342   } 
343   /* Now identifier.type and identifier.name speak about the base type.
344      Stars are not eaten unless 'int' was omitted.
345      We will have to enhance it if we are in fact asked for array or reference.
346    
347      Dynars and matrices also need some extra love (prodiged as annotations)
348    */
349
350   /**** look for the symbols of this type ****/
351   for(expect_id_separator = 0;
352
353       (/*(gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_EMPTY) && FIXME*/
354        (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_SEMI_COLON)) ; 
355
356       gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump()          ) {   
357
358     if(expect_id_separator) {
359       if(gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_COLON) {
360         expect_id_separator = 0;
361         continue;
362
363       } else if (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_LB) {
364         /* Handle fixed size arrays */
365         gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
366         if (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_RB) {
367           PARSE_ERROR0("Cannot deal with [] constructs (yet)");
368
369         } else if (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_WORD) {
370           char *end;
371           long int size=strtol(gras_ddt_parse_text, &end, 10);
372
373           if (end == gras_ddt_parse_text || *end != '\0') {
374             /* Not a number. Get the constant value, if any */
375             int *storage=xbt_dict_get_or_null(gras_dd_constants,gras_ddt_parse_text);
376             if (storage) {
377               size = *storage;
378             } else {
379               PARSE_ERROR1("Unparsable size of array. Found '%s', expected number or known constant. Need to use gras_datadesc_set_const(), huh?",
380                            gras_ddt_parse_text);
381             }
382           }
383
384           /* replace the previously pushed type to an array of it */
385           change_to_fixed_array(identifiers,size);
386
387           /* eat the closing bracket */
388           gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
389           if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_RB)
390             PARSE_ERROR0("Unparsable size of array");
391         DEBUG1("Fixed size array, size=%ld",size);
392         continue;
393         } else {
394           PARSE_ERROR0("Unparsable size of array");
395         }
396         /* End of fixed size arrays handling */
397
398       } else if (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_WORD) {
399         /* Handle annotation */
400         s_identifier_t array;
401         char *keyname = NULL;
402         char *keyval  = NULL;
403         memset(&array,0,sizeof(array));
404         if (strcmp(gras_ddt_parse_text,"GRAS_ANNOTE"))
405           PARSE_ERROR1("Unparsable symbol: Expected 'GRAS_ANNOTE', got '%s'",gras_ddt_parse_text);
406         
407         gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
408         if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_LP) 
409           PARSE_ERROR1("Unparsable annotation: Expected parenthesis, got '%s'",gras_ddt_parse_text);
410
411         while ( (gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump()) == GRAS_DDT_PARSE_TOKEN_EMPTY );
412
413         if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_WORD) 
414           PARSE_ERROR1("Unparsable annotation: Expected key name, got '%s'",gras_ddt_parse_text);
415         keyname = (char*)strdup(gras_ddt_parse_text);
416
417         while ( (gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump()) == GRAS_DDT_PARSE_TOKEN_EMPTY );
418
419         if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_COLON) 
420           PARSE_ERROR1("Unparsable annotation: expected ',' after the key name, got '%s'",gras_ddt_parse_text);
421
422         while ( (gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump()) == GRAS_DDT_PARSE_TOKEN_EMPTY );
423
424         /* get the value */
425
426         if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_WORD) 
427           PARSE_ERROR1("Unparsable annotation: Expected key value, got '%s'",gras_ddt_parse_text);
428         keyval = (char*)strdup(gras_ddt_parse_text);
429
430         while ( (gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump()) == GRAS_DDT_PARSE_TOKEN_EMPTY );
431
432         /* Done with parsing the annotation. Now deal with it by replacing previously pushed type with the right one */
433
434         DEBUG2("Anotation: %s=%s",keyname,keyval);
435         if (!strcmp(keyname,"size")) {
436           free(keyname);
437           if (!identifier.tm.is_ref)
438             PARSE_ERROR0("Size annotation for a field not being a reference");
439           identifier.tm.is_ref--;
440
441           if (!strcmp(keyval,"1")) {
442             change_to_ref(identifiers);
443             free(keyval);
444           } else {
445             char *p;
446             int fixed = 1;
447             for (p = keyval; *p != '\0'; p++) 
448               if (! isdigit(*p) )
449                 fixed = 0;
450             if (fixed) {
451               change_to_fixed_array(identifiers,atoi(keyval));
452               change_to_ref(identifiers);
453               free(keyval);
454
455             } else {
456               change_to_ref_pop_array(identifiers);
457               xbt_dynar_push(fields_to_push,&keyval);
458             }
459           }
460         } else if (!strcmp(keyname,"subtype")) {
461            gras_datadesc_type_t subtype = gras_datadesc_by_name(keyval);
462            if (identifier.tm.is_matrix) {
463               change_to_matrix_of(identifiers,subtype);
464               identifier.tm.is_matrix = -1;
465            } else if (identifier.tm.is_dynar) {
466               change_to_dynar_of(identifiers,subtype);
467               identifier.tm.is_dynar = -1;
468            } else {       
469              PARSE_ERROR1("subtype annotation only accepted for dynars and matrices, but passed to '%s'",identifier.type_name);
470            }
471         } else if (!strcmp(keyname,"free_f")) {
472            int *storage=xbt_dict_get_or_null(gras_dd_constants,keyval);
473            if (!storage)
474              PARSE_ERROR1("value for free_f annotation of field %s is not a known constant",identifier.name);
475            if (identifier.tm.is_matrix == -1) {
476               add_free_f(identifiers,*(void_f_pvoid_t**)storage);
477               identifier.tm.is_matrix = 0;
478            } else if (identifier.tm.is_dynar == -1) {
479               add_free_f(identifiers,*(void_f_pvoid_t**)storage);
480               identifier.tm.is_dynar = 0;
481            } else {       
482              PARSE_ERROR1("free_f annotation only accepted for dynars and matrices which subtype is already declared (field %s)",
483                           identifier.name);
484            }
485         } else {
486           PARSE_ERROR1("Unknown annotation type: '%s'",keyname);
487         }
488
489         /* Get all the multipliers */
490         while (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_STAR) {
491
492           gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
493
494           if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_WORD) 
495             PARSE_ERROR1("Unparsable annotation: Expected field name after '*', got '%s'",gras_ddt_parse_text);
496           
497           keyval = xbt_malloc(strlen(gras_ddt_parse_text)+2);
498           sprintf(keyval,"*%s",gras_ddt_parse_text);
499
500           /* ask caller to push field as a multiplier */
501           xbt_dynar_push(fields_to_push,&keyval);
502
503           /* skip blanks after this block*/
504           while ( (gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump()) 
505                   == GRAS_DDT_PARSE_TOKEN_EMPTY );
506         }
507
508         if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_RP) 
509           PARSE_ERROR1("Unparsable annotation: Expected parenthesis, got '%s'",
510                        gras_ddt_parse_text);
511
512         continue;
513
514         /* End of annotation handling */
515       } else {
516         PARSE_ERROR1("Unparsable symbol: Got '%s' instead of expected comma (',')",gras_ddt_parse_text);
517       }
518     } else if(gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_COLON) {
519       PARSE_ERROR0("Unparsable symbol: Unexpected comma (',')");
520     }
521
522     if (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_STAR) {
523       identifier.tm.is_ref++; /* We indeed deal with multiple references with multiple annotations */
524       continue;
525     }
526
527     /* found a symbol name. Build the type and push it to dynar */
528     if(gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_WORD) {
529
530       identifier.name=(char*)strdup(gras_ddt_parse_text);
531       DEBUG1("Found the identifier \"%s\"",identifier.name);
532       
533       xbt_dynar_push(identifiers, &identifier);
534       DEBUG1("Dynar_len=%lu",xbt_dynar_length(identifiers));
535       expect_id_separator = 1;
536       continue;
537     }
538
539     PARSE_ERROR0("Unparasable symbol (maybe a def struct in a def struct or a parser bug ;)");
540   }
541
542   if (identifier.tm.is_matrix>0) 
543      PARSE_ERROR0("xbt_matrix_t field without 'subtype' annotation");
544   if (identifier.tm.is_dynar>0)
545      PARSE_ERROR0("xbt_dynar_t field without 'subtype' annotation");
546    
547   XBT_OUT;
548 }
549
550 static gras_datadesc_type_t parse_struct(char *definition) {
551
552   xbt_ex_t e;
553
554   char buffname[32];
555   static int anonymous_struct=0;
556
557   xbt_dynar_t identifiers;
558   s_identifier_t field;
559   int i;
560   int done;
561
562   xbt_dynar_t fields_to_push;
563   char *name;
564
565   gras_datadesc_type_t struct_type;
566
567   XBT_IN;
568   identifiers = xbt_dynar_new(sizeof(s_identifier_t),NULL);
569   fields_to_push = xbt_dynar_new(sizeof(char*),NULL);
570
571   /* Create the struct descriptor */
572   if (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_WORD) {
573     struct_type = gras_datadesc_struct(gras_ddt_parse_text);
574     VERB1("Parse the struct '%s'", gras_ddt_parse_text);
575     gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
576   } else {
577     sprintf(buffname,"anonymous struct %d",anonymous_struct++); 
578     VERB1("Parse the anonymous struct nb %d", anonymous_struct);
579     struct_type = gras_datadesc_struct(buffname);
580   }
581
582   if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_LA)
583     PARSE_ERROR1("Unparasable symbol: Expecting struct definition, but got %s instead of '{'",
584                  gras_ddt_parse_text);
585
586   /* Parse the identifiers */
587   done = 0;
588   do {
589     TRY {
590       parse_statement(definition,identifiers,fields_to_push);
591     } CATCH(e) {
592       if (e.category != mismatch_error)
593         RETHROW;
594       xbt_ex_free(e);
595       done = 1;
596     }
597     
598     DEBUG1("This statement contained %lu identifiers",xbt_dynar_length(identifiers));
599     /* append the identifiers we've found */
600     xbt_dynar_foreach(identifiers,i, field) {
601       if (field.tm.is_ref)
602         PARSE_ERROR2("Not enough GRAS_ANNOTATE to deal with all dereferencing levels of %s (%d '*' left)",
603                      field.name,field.tm.is_ref);
604
605       VERB2("Append field '%s' to %p",field.name, (void*)struct_type);      
606       gras_datadesc_struct_append(struct_type, field.name, field.type);
607       free(field.name);
608       free(field.type_name);
609
610     }
611     xbt_dynar_reset(identifiers);
612     DEBUG1("struct_type=%p",(void*)struct_type);
613     
614     /* Make sure that all fields declaring a size push it into the cbps */
615     xbt_dynar_foreach(fields_to_push,i, name) {
616       DEBUG1("struct_type=%p",(void*)struct_type);
617       if (name[0] == '*') {
618         VERB2("Push field '%s' as a multiplier into size stack of %p",
619               name+1, (void*)struct_type);
620         gras_datadesc_cb_field_push_multiplier(struct_type, name+1);
621       } else {
622         VERB2("Push field '%s' into size stack of %p",
623               name, (void*)struct_type);
624         gras_datadesc_cb_field_push(struct_type, name);
625       }
626       free(name);
627     }
628     xbt_dynar_reset(fields_to_push);
629   } while (!done);
630   gras_datadesc_struct_close(struct_type);
631
632   /* terminates */
633   if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_RA)
634     PARSE_ERROR1("Unparasable symbol: Expected '}' at the end of struct definition, got '%s'",
635                  gras_ddt_parse_text);
636
637   gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
638
639   xbt_dynar_free(&identifiers);
640   xbt_dynar_free(&fields_to_push);
641   XBT_OUT;
642   return struct_type;
643 }
644
645 static gras_datadesc_type_t parse_typedef(char *definition) {
646
647   s_type_modifier_t tm;
648
649   gras_datadesc_type_t struct_desc=NULL;
650   gras_datadesc_type_t typedef_desc=NULL;
651
652   XBT_IN;
653   memset(&tm,0,sizeof(tm));
654
655   /* get the aliased type */
656   parse_type_modifier(&tm);
657
658   if (tm.is_struct) {
659     struct_desc = parse_struct(definition);
660   }
661
662   parse_type_modifier(&tm);
663
664   if (tm.is_ref) 
665     PARSE_ERROR0("Cannot handle reference without annotation");
666
667   /* get the aliasing name */
668   if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_WORD)
669     PARSE_ERROR1("Unparsable typedef: Expected the alias name, and got '%s'",
670                  gras_ddt_parse_text);
671   
672   /* (FIXME: should) build the alias */
673   PARSE_ERROR0("Cannot handle typedef yet");
674
675   XBT_OUT;
676   return typedef_desc;
677 }
678
679
680 /**
681  * gras_datadesc_parse:
682  *
683  * Create a datadescription from the result of parsing the C type description
684  */
685 gras_datadesc_type_t 
686 gras_datadesc_parse(const char            *name,
687                     const char            *C_statement) {
688
689   gras_datadesc_type_t res=NULL;
690   char *definition;
691   int semicolon_count=0;
692   int def_count,C_count;
693
694   XBT_IN;
695   /* reput the \n in place for debug */
696   for (C_count=0; C_statement[C_count] != '\0'; C_count++)
697     if (C_statement[C_count] == ';' || C_statement[C_count] == '{')
698       semicolon_count++;
699   definition = (char*)xbt_malloc(C_count + semicolon_count + 1);
700   for (C_count=0,def_count=0; C_statement[C_count] != '\0'; C_count++) {
701     definition[def_count++] = C_statement[C_count];
702     if (C_statement[C_count] == ';' || C_statement[C_count] == '{') {
703       definition[def_count++] = '\n';
704     }
705   }
706   definition[def_count] = '\0';
707
708   /* init */ 
709   VERB2("_gras_ddt_type_parse(%s) -> %d chars",definition, def_count);
710   gras_ddt_parse_pointer_string_init(definition);
711
712   /* Do I have a typedef, or a raw struct ?*/
713   gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
714   
715   if ((gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_WORD) && (!strcmp(gras_ddt_parse_text,"struct"))) {
716     gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
717     res = parse_struct(definition);
718       
719   } else if ((gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_WORD) && (!strcmp(gras_ddt_parse_text,"typedef"))) {
720     gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
721     res = parse_typedef(definition);
722
723   } else {
724     ERROR1("Failed to parse the following symbol (not a struct neither a typedef) :\n%s",definition);    
725     xbt_abort();
726   }
727
728   gras_ddt_parse_pointer_string_close();
729   VERB0("end of _gras_ddt_type_parse()");
730   free(definition);
731   /* register it under the name provided as symbol */
732   if (strcmp(res->name,name)) {
733     ERROR2("In GRAS_DEFINE_TYPE, the provided symbol (here %s) must be the C type name (here %s)",
734            name,res->name);
735     xbt_abort();
736   }    
737   gras_ddt_parse_lex_destroy();
738   XBT_OUT;
739   return res;
740 }
741
742 xbt_dict_t gras_dd_constants;
743 /** \brief Declare a constant to the parsing mecanism. See the "\#define and fixed size array" section */
744 void gras_datadesc_set_const(const char*name, int value) {
745   int *stored = xbt_new(int, 1);
746   *stored=value;
747
748   xbt_dict_set(gras_dd_constants,name, stored, free); 
749 }