Logo AND Algorithmique Numérique Distribuée

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