Logo AND Algorithmique Numérique Distribuée

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