Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Less debugging info
[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("Unimplemented feature: GRAS_DEFINE_TYPE 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("Unimplemented feature: GRAS_DEFINE_TYPE cannot handle union yet (get callback from annotation?)");
278
279         } else if (identifier.tm.is_enum) {
280                 PARSE_ERROR0("Unimplemented feature: GRAS_DEFINE_TYPE 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("Unimplemented feature: GRAS_DEFINE_TYPE 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                                         free(keyval);
472                                 } else if (!strcmp(keyname,"free_f")) {
473                                         int *storage=xbt_dict_get_or_null(gras_dd_constants,keyval);
474                                         if (!storage)
475                                                 PARSE_ERROR1("value for free_f annotation of field %s is not a known constant",identifier.name);
476                                         if (identifier.tm.is_matrix == -1) {
477                                                 add_free_f(identifiers,*(void_f_pvoid_t*)storage);
478                                                 identifier.tm.is_matrix = 0;
479                                         } else if (identifier.tm.is_dynar == -1) {
480                                                 add_free_f(identifiers,*(void_f_pvoid_t*)storage);
481                                                 identifier.tm.is_dynar = 0;
482                                         } else {
483                                                 PARSE_ERROR1("free_f annotation only accepted for dynars and matrices which subtype is already declared (field %s)",
484                                                                 identifier.name);
485                                         }
486                                         free(keyval);
487                                 } else {
488                                         free(keyval);
489                                         PARSE_ERROR1("Unknown annotation type: '%s'",keyname);
490                                 }
491
492                                 /* Get all the multipliers */
493                                 while (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_STAR) {
494
495                                         gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
496
497                                         if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_WORD)
498                                                 PARSE_ERROR1("Unparsable annotation: Expected field name after '*', got '%s'",gras_ddt_parse_text);
499
500                                         keyval = xbt_malloc(strlen(gras_ddt_parse_text)+2);
501                                         sprintf(keyval,"*%s",gras_ddt_parse_text);
502
503                                         /* ask caller to push field as a multiplier */
504                                         xbt_dynar_push(fields_to_push,&keyval);
505
506                                         /* skip blanks after this block*/
507                                         while ( (gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump())
508                                                         == GRAS_DDT_PARSE_TOKEN_EMPTY );
509                                 }
510
511                                 if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_RP)
512                                         PARSE_ERROR1("Unparsable annotation: Expected parenthesis, got '%s'",
513                                                         gras_ddt_parse_text);
514
515                                 continue;
516
517                                 /* End of annotation handling */
518                         } else {
519                                 PARSE_ERROR1("Unparsable symbol: Got '%s' instead of expected comma (',')",gras_ddt_parse_text);
520                         }
521                 } else if(gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_COLON) {
522                         PARSE_ERROR0("Unparsable symbol: Unexpected comma (',')");
523                 }
524
525                 if (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_STAR) {
526                         identifier.tm.is_ref++; /* We indeed deal with multiple references with multiple annotations */
527                         continue;
528                 }
529
530                 /* found a symbol name. Build the type and push it to dynar */
531                 if(gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_WORD) {
532
533                         identifier.name=(char*)strdup(gras_ddt_parse_text);
534                         DEBUG1("Found the identifier \"%s\"",identifier.name);
535
536                         xbt_dynar_push(identifiers, &identifier);
537                         DEBUG1("Dynar_len=%lu",xbt_dynar_length(identifiers));
538                         expect_id_separator = 1;
539                         continue;
540                 }
541
542                 PARSE_ERROR0("Unparasable symbol (maybe a def struct in a def struct or a parser bug ;)");
543         }
544
545         if (identifier.tm.is_matrix>0)
546                 PARSE_ERROR0("xbt_matrix_t field without 'subtype' annotation");
547         if (identifier.tm.is_dynar>0)
548                 PARSE_ERROR0("xbt_dynar_t field without 'subtype' annotation");
549
550         XBT_OUT;
551 }
552
553 static gras_datadesc_type_t parse_struct(char *definition) {
554
555         xbt_ex_t e;
556
557         char buffname[32];
558         static int anonymous_struct=0;
559
560         xbt_dynar_t identifiers;
561         s_identifier_t field;
562         unsigned int iter;
563         int done;
564
565         xbt_dynar_t fields_to_push;
566         char *name;
567
568         gras_datadesc_type_t struct_type;
569
570         XBT_IN;
571         identifiers = xbt_dynar_new(sizeof(s_identifier_t),NULL);
572         fields_to_push = xbt_dynar_new(sizeof(char*),NULL);
573
574         /* Create the struct descriptor */
575         if (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_WORD) {
576                 struct_type = gras_datadesc_struct(gras_ddt_parse_text);
577                 VERB1("Parse the struct '%s'", gras_ddt_parse_text);
578                 gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
579         } else {
580                 sprintf(buffname,"anonymous struct %d",anonymous_struct++);
581                 VERB1("Parse the anonymous struct nb %d", anonymous_struct);
582                 struct_type = gras_datadesc_struct(buffname);
583         }
584
585         if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_LA)
586                 PARSE_ERROR1("Unparasable symbol: Expecting struct definition, but got %s instead of '{'",
587                                 gras_ddt_parse_text);
588
589         /* Parse the identifiers */
590         done = 0;
591         do {
592                 TRY {
593                         parse_statement(definition,identifiers,fields_to_push);
594                 } CATCH(e) {
595                         if (e.category != mismatch_error)
596                                 RETHROW;
597                         xbt_ex_free(e);
598                         done = 1;
599                 }
600
601                 DEBUG1("This statement contained %lu identifiers",xbt_dynar_length(identifiers));
602                 /* append the identifiers we've found */
603                 xbt_dynar_foreach(identifiers,iter, field) {
604                         if (field.tm.is_ref)
605                                 PARSE_ERROR2("Not enough GRAS_ANNOTATE to deal with all dereferencing levels of %s (%d '*' left)",
606                                                 field.name,field.tm.is_ref);
607
608                         VERB2("Append field '%s' to %p",field.name, (void*)struct_type);
609                         gras_datadesc_struct_append(struct_type, field.name, field.type);
610                         free(field.name);
611                         free(field.type_name);
612
613                 }
614                 xbt_dynar_reset(identifiers);
615                 DEBUG1("struct_type=%p",(void*)struct_type);
616
617                 /* Make sure that all fields declaring a size push it into the cbps */
618                 xbt_dynar_foreach(fields_to_push,iter, name) {
619                         DEBUG1("struct_type=%p",(void*)struct_type);
620                         if (name[0] == '*') {
621                                 VERB2("Push field '%s' as a multiplier into size stack of %p",
622                                                 name+1, (void*)struct_type);
623                                 gras_datadesc_cb_field_push_multiplier(struct_type, name+1);
624                         } else {
625                                 VERB2("Push field '%s' into size stack of %p",
626                                                 name, (void*)struct_type);
627                                 gras_datadesc_cb_field_push(struct_type, name);
628                         }
629                         free(name);
630                 }
631                 xbt_dynar_reset(fields_to_push);
632         } while (!done);
633         gras_datadesc_struct_close(struct_type);
634
635         /* terminates */
636         if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_RA)
637                 PARSE_ERROR1("Unparasable symbol: Expected '}' at the end of struct definition, got '%s'",
638                                 gras_ddt_parse_text);
639
640         gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
641
642         xbt_dynar_free(&identifiers);
643         xbt_dynar_free(&fields_to_push);
644         XBT_OUT;
645         return struct_type;
646 }
647
648 static gras_datadesc_type_t parse_typedef(char *definition) {
649
650         s_type_modifier_t tm;
651
652         gras_datadesc_type_t struct_desc=NULL;
653         gras_datadesc_type_t typedef_desc=NULL;
654
655         XBT_IN;
656         memset(&tm,0,sizeof(tm));
657
658         /* get the aliased type */
659         parse_type_modifier(&tm);
660
661         if (tm.is_struct) {
662                 struct_desc = parse_struct(definition);
663         }
664
665         parse_type_modifier(&tm);
666
667         if (tm.is_ref)
668                 PARSE_ERROR0("GRAS_DEFINE_TYPE cannot handle reference without annotation");
669
670         /* get the aliasing name */
671         if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_WORD)
672                 PARSE_ERROR1("Unparsable typedef: Expected the alias name, and got '%s'",
673                                 gras_ddt_parse_text);
674
675         /* (FIXME: should) build the alias */
676         PARSE_ERROR0("Unimplemented feature: GRAS_DEFINE_TYPE cannot handle typedef yet");
677
678         XBT_OUT;
679         return typedef_desc;
680 }
681
682
683 /**
684  * gras_datadesc_parse:
685  *
686  * Create a datadescription from the result of parsing the C type description
687  */
688 gras_datadesc_type_t
689 gras_datadesc_parse(const char            *name,
690                 const char            *C_statement) {
691
692         gras_datadesc_type_t res=NULL;
693         char *definition;
694         int semicolon_count=0;
695         int def_count,C_count;
696
697         XBT_IN;
698         /* reput the \n in place for debug */
699         for (C_count=0; C_statement[C_count] != '\0'; C_count++)
700                 if (C_statement[C_count] == ';' || C_statement[C_count] == '{')
701                         semicolon_count++;
702         definition = (char*)xbt_malloc(C_count + semicolon_count + 1);
703         for (C_count=0,def_count=0; C_statement[C_count] != '\0'; C_count++) {
704                 definition[def_count++] = C_statement[C_count];
705                 if (C_statement[C_count] == ';' || C_statement[C_count] == '{') {
706                         definition[def_count++] = '\n';
707                 }
708         }
709         definition[def_count] = '\0';
710
711         /* init */
712         VERB2("_gras_ddt_type_parse(%s) -> %d chars",definition, def_count);
713         gras_ddt_parse_pointer_string_init(definition);
714
715         /* Do I have a typedef, or a raw struct ?*/
716         gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
717
718         if ((gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_WORD) && (!strcmp(gras_ddt_parse_text,"struct"))) {
719                 gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
720                 res = parse_struct(definition);
721
722         } else if ((gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_WORD) && (!strcmp(gras_ddt_parse_text,"typedef"))) {
723                 gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
724                 res = parse_typedef(definition);
725
726         } else {
727                 ERROR1("Failed to parse the following symbol (not a struct neither a typedef) :\n%s",definition);
728                 xbt_abort();
729         }
730
731         gras_ddt_parse_pointer_string_close();
732         VERB0("end of _gras_ddt_type_parse()");
733         free(definition);
734         /* register it under the name provided as symbol */
735         if (strcmp(res->name,name)) {
736                 ERROR2("In GRAS_DEFINE_TYPE, the provided symbol (here %s) must be the C type name (here %s)",
737                                 name,res->name);
738                 xbt_abort();
739         }
740         gras_ddt_parse_lex_destroy();
741         XBT_OUT;
742         return res;
743 }
744
745 xbt_dict_t gras_dd_constants;
746 /** \brief Declare a constant to the parsing mecanism. See the "\#define and fixed size array" section */
747 void gras_datadesc_set_const(const char*name, int value) {
748         int *stored = xbt_new(int, 1);
749         *stored=value;
750
751         xbt_dict_set(gras_dd_constants,name, stored, xbt_free_f);
752 }