Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
add_free_f use now a pointer to a free function
[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 add_free_f(xbt_dynar_t dynar,void_f_pvoid_t* free_f) {
213   s_identifier_t former,ref;
214   memset(&ref,0,sizeof(ref));
215
216   XBT_IN;
217   xbt_dynar_pop(dynar,&former);
218   memcpy(former.type->extra,free_f, sizeof(free_f));
219   xbt_dynar_push(dynar,&former);
220   XBT_OUT;
221 }
222
223 static void parse_statement(char         *definition,
224                             xbt_dynar_t  identifiers,
225                             xbt_dynar_t  fields_to_push) {
226   char buffname[512];
227
228   s_identifier_t identifier;
229
230   int expect_id_separator = 0;
231
232   XBT_IN;
233   memset(&identifier,0,sizeof(identifier));
234
235   gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
236   if(gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_RA) {
237     XBT_OUT;
238     THROW0(mismatch_error,0,"End of the englobing structure or union");
239   }
240   
241   if (XBT_LOG_ISENABLED(gras_ddt_parse,xbt_log_priority_debug)) {
242     int colon_pos;
243     for (colon_pos = gras_ddt_parse_col_pos;
244          definition[colon_pos] != ';';
245          colon_pos++);
246     definition[colon_pos] = '\0';
247     DEBUG3("Parse the statement \"%s%s;\" (col_pos=%d)",
248            gras_ddt_parse_text,
249            definition+gras_ddt_parse_col_pos,
250            gras_ddt_parse_col_pos);
251     definition[colon_pos] = ';';
252   }
253
254   if(gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_WORD)
255     PARSE_ERROR1("Unparsable symbol: found a typeless statement (got '%s' instead)",
256                  gras_ddt_parse_text);
257
258   /**** get the type modifier of this statement ****/
259   parse_type_modifier(&identifier.tm);
260
261   /*  FIXME: This does not detect recursive definitions at all? */
262   if (identifier.tm.is_union || identifier.tm.is_enum || identifier.tm.is_struct)
263     PARSE_ERROR0("Unimplemented feature: GRAS_DEFINE_TYPE cannot handle recursive type definition yet");
264
265   /**** get the base type, giving "short a" the needed love ****/
266   if (!identifier.tm.is_union &&
267       !identifier.tm.is_enum  && 
268       !identifier.tm.is_struct &&
269
270       (identifier.tm.is_short || identifier.tm.is_long || identifier.tm.is_unsigned) &&
271
272       strcmp(gras_ddt_parse_text,"char") && 
273       strcmp(gras_ddt_parse_text,"float") && 
274       strcmp(gras_ddt_parse_text,"double") && 
275       strcmp(gras_ddt_parse_text,"int") ) {
276
277     /* bastard user, they omited "int" ! */
278     identifier.type_name=(char*)strdup("int");
279     DEBUG0("the base type is 'int', which were omited (you vicious user)");
280   } else {
281     identifier.type_name=(char*)strdup(gras_ddt_parse_text);
282     DEBUG1("the base type is '%s'",identifier.type_name);
283     gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump(); 
284   }
285
286   /**** build the base type for latter use ****/
287   if (identifier.tm.is_union) {
288     PARSE_ERROR0("Unimplemented feature: GRAS_DEFINE_TYPE cannot handle union yet (get callback from annotation?)");
289
290   } else if (identifier.tm.is_enum) {
291     PARSE_ERROR0("Unimplemented feature: GRAS_DEFINE_TYPE cannot handle enum yet");
292
293   } else if (identifier.tm.is_struct) {
294     sprintf(buffname,"struct %s",identifier.type_name);
295     identifier.type = gras_datadesc_struct(buffname); /* Get created when does not exist */
296
297   } else if (identifier.tm.is_unsigned) {
298     if (!strcmp(identifier.type_name,"int")) {
299       if (identifier.tm.is_long == 2) {
300         identifier.type = gras_datadesc_by_name("unsigned long long int");
301       } else if (identifier.tm.is_long) {
302         identifier.type = gras_datadesc_by_name("unsigned long int");
303       } else if (identifier.tm.is_short) {
304         identifier.type = gras_datadesc_by_name("unsigned short int");
305       } else {
306         identifier.type = gras_datadesc_by_name("unsigned int");
307       }
308
309     } else if (!strcmp(identifier.type_name, "char")) {
310       identifier.type = gras_datadesc_by_name("unsigned char");
311
312     } else { /* impossible, gcc parses this shit before us */
313       THROW_IMPOSSIBLE;
314     }
315     
316   } else if (!strcmp(identifier.type_name, "float")) {
317     /* no modificator allowed by gcc */
318     identifier.type = gras_datadesc_by_name("float");
319
320   } else if (!strcmp(identifier.type_name, "double")) {
321     if (identifier.tm.is_long)
322       PARSE_ERROR0("long double not portable and thus not handled");
323
324     identifier.type = gras_datadesc_by_name("double");
325
326   } else { /* signed integer elemental */
327     if (!strcmp(identifier.type_name,"int")) {
328       if (identifier.tm.is_long == 2) {
329         identifier.type = gras_datadesc_by_name("signed long long int");
330       } else if (identifier.tm.is_long) {
331         identifier.type = gras_datadesc_by_name("signed long int");
332       } else if (identifier.tm.is_short) {
333         identifier.type = gras_datadesc_by_name("signed short int");
334       } else {
335         identifier.type = gras_datadesc_by_name("int");
336       }
337
338     } else if (!strcmp(identifier.type_name, "char")) {
339       identifier.type = gras_datadesc_by_name("char");
340
341     } else { 
342       DEBUG1("Base type is a constructed one (%s)",identifier.type_name);
343       if (!strcmp(identifier.type_name,"xbt_matrix_t")) {
344          identifier.tm.is_matrix = 1;
345       } else if (!strcmp(identifier.type_name,"xbt_dynar_t")) {
346          identifier.tm.is_dynar = 1;
347       } else {       
348          identifier.type = gras_datadesc_by_name(identifier.type_name);
349          if (!identifier.type)
350            PARSE_ERROR1("Unknown base type '%s'",identifier.type_name);
351       }
352     }
353   } 
354   /* Now identifier.type and identifier.name speak about the base type.
355      Stars are not eaten unless 'int' was omitted.
356      We will have to enhance it if we are in fact asked for array or reference.
357    
358      Dynars and matrices also need some extra love (prodiged as annotations)
359    */
360
361   /**** look for the symbols of this type ****/
362   for(expect_id_separator = 0;
363
364       (/*(gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_EMPTY) && FIXME*/
365        (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_SEMI_COLON)) ; 
366
367       gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump()          ) {   
368
369     if(expect_id_separator) {
370       if(gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_COLON) {
371         expect_id_separator = 0;
372         continue;
373
374       } else if (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_LB) {
375         /* Handle fixed size arrays */
376         gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
377         if (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_RB) {
378           PARSE_ERROR0("Unimplemented feature: GRAS_DEFINE_TYPE cannot deal with [] constructs (yet)");
379
380         } else if (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_WORD) {
381           char *end;
382           long int size=strtol(gras_ddt_parse_text, &end, 10);
383
384           if (end == gras_ddt_parse_text || *end != '\0') {
385             /* Not a number. Get the constant value, if any */
386             int *storage=xbt_dict_get_or_null(gras_dd_constants,gras_ddt_parse_text);
387             if (storage) {
388               size = *storage;
389             } else {
390               PARSE_ERROR1("Unparsable size of array. Found '%s', expected number or known constant. Need to use gras_datadesc_set_const(), huh?",
391                            gras_ddt_parse_text);
392             }
393           }
394
395           /* replace the previously pushed type to an array of it */
396           change_to_fixed_array(identifiers,size);
397
398           /* eat the closing bracket */
399           gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
400           if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_RB)
401             PARSE_ERROR0("Unparsable size of array");
402         DEBUG1("Fixed size array, size=%ld",size);
403         continue;
404         } else {
405           PARSE_ERROR0("Unparsable size of array");
406         }
407         /* End of fixed size arrays handling */
408
409       } else if (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_WORD) {
410         /* Handle annotation */
411         s_identifier_t array;
412         char *keyname = NULL;
413         char *keyval  = NULL;
414         memset(&array,0,sizeof(array));
415         if (strcmp(gras_ddt_parse_text,"GRAS_ANNOTE"))
416           PARSE_ERROR1("Unparsable symbol: Expected 'GRAS_ANNOTE', got '%s'",gras_ddt_parse_text);
417         
418         gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
419         if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_LP) 
420           PARSE_ERROR1("Unparsable annotation: Expected parenthesis, 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         if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_WORD) 
425           PARSE_ERROR1("Unparsable annotation: Expected key name, got '%s'",gras_ddt_parse_text);
426         keyname = (char*)strdup(gras_ddt_parse_text);
427
428         while ( (gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump()) == GRAS_DDT_PARSE_TOKEN_EMPTY );
429
430         if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_COLON) 
431           PARSE_ERROR1("Unparsable annotation: expected ',' after the key name, got '%s'",gras_ddt_parse_text);
432
433         while ( (gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump()) == GRAS_DDT_PARSE_TOKEN_EMPTY );
434
435         /* get the value */
436
437         if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_WORD) 
438           PARSE_ERROR1("Unparsable annotation: Expected key value, got '%s'",gras_ddt_parse_text);
439         keyval = (char*)strdup(gras_ddt_parse_text);
440
441         while ( (gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump()) == GRAS_DDT_PARSE_TOKEN_EMPTY );
442
443         /* Done with parsing the annotation. Now deal with it by replacing previously pushed type with the right one */
444
445         DEBUG2("Anotation: %s=%s",keyname,keyval);
446         if (!strcmp(keyname,"size")) {
447           free(keyname);
448           if (!identifier.tm.is_ref)
449             PARSE_ERROR0("Size annotation for a field not being a reference");
450           identifier.tm.is_ref--;
451
452           if (!strcmp(keyval,"1")) {
453             change_to_ref(identifiers);
454             free(keyval);
455           } else {
456             char *p;
457             int fixed = 1;
458             for (p = keyval; *p != '\0'; p++) 
459               if (! isdigit(*p) )
460                 fixed = 0;
461             if (fixed) {
462               change_to_fixed_array(identifiers,atoi(keyval));
463               change_to_ref(identifiers);
464               free(keyval);
465
466             } else {
467               change_to_ref_pop_array(identifiers);
468               xbt_dynar_push(fields_to_push,&keyval);
469             }
470           }
471         } else if (!strcmp(keyname,"subtype")) {
472            gras_datadesc_type_t subtype = gras_datadesc_by_name(keyval);
473            if (identifier.tm.is_matrix) {
474               change_to_matrix_of(identifiers,subtype);
475               identifier.tm.is_matrix = -1;
476            } else if (identifier.tm.is_dynar) {
477               change_to_dynar_of(identifiers,subtype);
478               identifier.tm.is_dynar = -1;
479            } else {       
480              PARSE_ERROR1("subtype annotation only accepted for dynars and matrices, but passed to '%s'",identifier.type_name);
481            }
482            free(keyval);
483         } else if (!strcmp(keyname,"free_f")) {
484            int *storage=xbt_dict_get_or_null(gras_dd_constants,keyval);
485            if (!storage)
486              PARSE_ERROR1("value for free_f annotation of field %s is not a known constant",identifier.name);
487            if (identifier.tm.is_matrix == -1) {
488               add_free_f(identifiers,*(void_f_pvoid_t**)storage);
489               identifier.tm.is_matrix = 0;
490            } else if (identifier.tm.is_dynar == -1) {
491               add_free_f(identifiers,*(void_f_pvoid_t**)storage);
492               identifier.tm.is_dynar = 0;
493            } else {       
494              PARSE_ERROR1("free_f annotation only accepted for dynars and matrices which subtype is already declared (field %s)",
495                           identifier.name);
496            }
497            free(keyval);
498         } else {
499           free(keyval);
500           PARSE_ERROR1("Unknown annotation type: '%s'",keyname);
501         }
502
503         /* Get all the multipliers */
504         while (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_STAR) {
505
506           gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
507
508           if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_WORD) 
509             PARSE_ERROR1("Unparsable annotation: Expected field name after '*', got '%s'",gras_ddt_parse_text);
510           
511           keyval = xbt_malloc(strlen(gras_ddt_parse_text)+2);
512           sprintf(keyval,"*%s",gras_ddt_parse_text);
513
514           /* ask caller to push field as a multiplier */
515           xbt_dynar_push(fields_to_push,&keyval);
516
517           /* skip blanks after this block*/
518           while ( (gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump()) 
519                   == GRAS_DDT_PARSE_TOKEN_EMPTY );
520         }
521
522         if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_RP) 
523           PARSE_ERROR1("Unparsable annotation: Expected parenthesis, got '%s'",
524                        gras_ddt_parse_text);
525
526         continue;
527
528         /* End of annotation handling */
529       } else {
530         PARSE_ERROR1("Unparsable symbol: Got '%s' instead of expected comma (',')",gras_ddt_parse_text);
531       }
532     } else if(gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_COLON) {
533       PARSE_ERROR0("Unparsable symbol: Unexpected comma (',')");
534     }
535
536     if (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_STAR) {
537       identifier.tm.is_ref++; /* We indeed deal with multiple references with multiple annotations */
538       continue;
539     }
540
541     /* found a symbol name. Build the type and push it to dynar */
542     if(gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_WORD) {
543
544       identifier.name=(char*)strdup(gras_ddt_parse_text);
545       DEBUG1("Found the identifier \"%s\"",identifier.name);
546       
547       xbt_dynar_push(identifiers, &identifier);
548       DEBUG1("Dynar_len=%lu",xbt_dynar_length(identifiers));
549       expect_id_separator = 1;
550       continue;
551     }
552
553     PARSE_ERROR0("Unparasable symbol (maybe a def struct in a def struct or a parser bug ;)");
554   }
555
556   if (identifier.tm.is_matrix>0) 
557      PARSE_ERROR0("xbt_matrix_t field without 'subtype' annotation");
558   if (identifier.tm.is_dynar>0)
559      PARSE_ERROR0("xbt_dynar_t field without 'subtype' annotation");
560    
561   XBT_OUT;
562 }
563
564 static gras_datadesc_type_t parse_struct(char *definition) {
565
566   xbt_ex_t e;
567
568   char buffname[32];
569   static int anonymous_struct=0;
570
571   xbt_dynar_t identifiers;
572   s_identifier_t field;
573   int i;
574   int done;
575
576   xbt_dynar_t fields_to_push;
577   char *name;
578
579   gras_datadesc_type_t struct_type;
580
581   XBT_IN;
582   identifiers = xbt_dynar_new(sizeof(s_identifier_t),NULL);
583   fields_to_push = xbt_dynar_new(sizeof(char*),NULL);
584
585   /* Create the struct descriptor */
586   if (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_WORD) {
587     struct_type = gras_datadesc_struct(gras_ddt_parse_text);
588     VERB1("Parse the struct '%s'", gras_ddt_parse_text);
589     gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
590   } else {
591     sprintf(buffname,"anonymous struct %d",anonymous_struct++); 
592     VERB1("Parse the anonymous struct nb %d", anonymous_struct);
593     struct_type = gras_datadesc_struct(buffname);
594   }
595
596   if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_LA)
597     PARSE_ERROR1("Unparasable symbol: Expecting struct definition, but got %s instead of '{'",
598                  gras_ddt_parse_text);
599
600   /* Parse the identifiers */
601   done = 0;
602   do {
603     TRY {
604       parse_statement(definition,identifiers,fields_to_push);
605     } CATCH(e) {
606       if (e.category != mismatch_error)
607         RETHROW;
608       xbt_ex_free(e);
609       done = 1;
610     }
611     
612     DEBUG1("This statement contained %lu identifiers",xbt_dynar_length(identifiers));
613     /* append the identifiers we've found */
614     xbt_dynar_foreach(identifiers,i, field) {
615       if (field.tm.is_ref)
616         PARSE_ERROR2("Not enough GRAS_ANNOTATE to deal with all dereferencing levels of %s (%d '*' left)",
617                      field.name,field.tm.is_ref);
618
619       VERB2("Append field '%s' to %p",field.name, (void*)struct_type);      
620       gras_datadesc_struct_append(struct_type, field.name, field.type);
621       free(field.name);
622       free(field.type_name);
623
624     }
625     xbt_dynar_reset(identifiers);
626     DEBUG1("struct_type=%p",(void*)struct_type);
627     
628     /* Make sure that all fields declaring a size push it into the cbps */
629     xbt_dynar_foreach(fields_to_push,i, name) {
630       DEBUG1("struct_type=%p",(void*)struct_type);
631       if (name[0] == '*') {
632         VERB2("Push field '%s' as a multiplier into size stack of %p",
633               name+1, (void*)struct_type);
634         gras_datadesc_cb_field_push_multiplier(struct_type, name+1);
635       } else {
636         VERB2("Push field '%s' into size stack of %p",
637               name, (void*)struct_type);
638         gras_datadesc_cb_field_push(struct_type, name);
639       }
640       free(name);
641     }
642     xbt_dynar_reset(fields_to_push);
643   } while (!done);
644   gras_datadesc_struct_close(struct_type);
645
646   /* terminates */
647   if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_RA)
648     PARSE_ERROR1("Unparasable symbol: Expected '}' at the end of struct definition, got '%s'",
649                  gras_ddt_parse_text);
650
651   gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
652
653   xbt_dynar_free(&identifiers);
654   xbt_dynar_free(&fields_to_push);
655   XBT_OUT;
656   return struct_type;
657 }
658
659 static gras_datadesc_type_t parse_typedef(char *definition) {
660
661   s_type_modifier_t tm;
662
663   gras_datadesc_type_t struct_desc=NULL;
664   gras_datadesc_type_t typedef_desc=NULL;
665
666   XBT_IN;
667   memset(&tm,0,sizeof(tm));
668
669   /* get the aliased type */
670   parse_type_modifier(&tm);
671
672   if (tm.is_struct) {
673     struct_desc = parse_struct(definition);
674   }
675
676   parse_type_modifier(&tm);
677
678   if (tm.is_ref) 
679     PARSE_ERROR0("GRAS_DEFINE_TYPE cannot handle reference without annotation");
680
681   /* get the aliasing name */
682   if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_WORD)
683     PARSE_ERROR1("Unparsable typedef: Expected the alias name, and got '%s'",
684                  gras_ddt_parse_text);
685   
686   /* (FIXME: should) build the alias */
687   PARSE_ERROR0("Unimplemented feature: GRAS_DEFINE_TYPE cannot handle typedef yet");
688
689   XBT_OUT;
690   return typedef_desc;
691 }
692
693
694 /**
695  * gras_datadesc_parse:
696  *
697  * Create a datadescription from the result of parsing the C type description
698  */
699 gras_datadesc_type_t 
700 gras_datadesc_parse(const char            *name,
701                     const char            *C_statement) {
702
703   gras_datadesc_type_t res=NULL;
704   char *definition;
705   int semicolon_count=0;
706   int def_count,C_count;
707
708   XBT_IN;
709   /* reput the \n in place for debug */
710   for (C_count=0; C_statement[C_count] != '\0'; C_count++)
711     if (C_statement[C_count] == ';' || C_statement[C_count] == '{')
712       semicolon_count++;
713   definition = (char*)xbt_malloc(C_count + semicolon_count + 1);
714   for (C_count=0,def_count=0; C_statement[C_count] != '\0'; C_count++) {
715     definition[def_count++] = C_statement[C_count];
716     if (C_statement[C_count] == ';' || C_statement[C_count] == '{') {
717       definition[def_count++] = '\n';
718     }
719   }
720   definition[def_count] = '\0';
721
722   /* init */ 
723   VERB2("_gras_ddt_type_parse(%s) -> %d chars",definition, def_count);
724   gras_ddt_parse_pointer_string_init(definition);
725
726   /* Do I have a typedef, or a raw struct ?*/
727   gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
728   
729   if ((gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_WORD) && (!strcmp(gras_ddt_parse_text,"struct"))) {
730     gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
731     res = parse_struct(definition);
732       
733   } else if ((gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_WORD) && (!strcmp(gras_ddt_parse_text,"typedef"))) {
734     gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
735     res = parse_typedef(definition);
736
737   } else {
738     ERROR1("Failed to parse the following symbol (not a struct neither a typedef) :\n%s",definition);    
739     xbt_abort();
740   }
741
742   gras_ddt_parse_pointer_string_close();
743   VERB0("end of _gras_ddt_type_parse()");
744   free(definition);
745   /* register it under the name provided as symbol */
746   if (strcmp(res->name,name)) {
747     ERROR2("In GRAS_DEFINE_TYPE, the provided symbol (here %s) must be the C type name (here %s)",
748            name,res->name);
749     xbt_abort();
750   }    
751   gras_ddt_parse_lex_destroy();
752   XBT_OUT;
753   return res;
754 }
755
756 xbt_dict_t gras_dd_constants;
757 /** \brief Declare a constant to the parsing mecanism. See the "\#define and fixed size array" section */
758 void gras_datadesc_set_const(const char*name, int value) {
759   int *stored = xbt_new(int, 1);
760   *stored=value;
761
762   xbt_dict_set(gras_dd_constants,name, stored, xbt_free_f); 
763 }