Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Remove old style logging macros.
[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       XBT_DEBUG("This is a reference");
50       type_modifier->is_ref++;
51
52     } else if (!strcmp(gras_ddt_parse_text, "unsigned")) {
53       XBT_DEBUG("This is an unsigned");
54       type_modifier->is_unsigned = 1;
55
56     } else if (!strcmp(gras_ddt_parse_text, "short")) {
57       XBT_DEBUG("This is short");
58       type_modifier->is_short = 1;
59
60     } else if (!strcmp(gras_ddt_parse_text, "long")) {
61       XBT_DEBUG("This is long");
62       type_modifier->is_long++; /* handle "long long" */
63
64     } else if (!strcmp(gras_ddt_parse_text, "struct")) {
65       XBT_DEBUG("This is a struct");
66       type_modifier->is_struct = 1;
67
68     } else if (!strcmp(gras_ddt_parse_text, "union")) {
69       XBT_DEBUG("This is an union");
70       type_modifier->is_union = 1;
71
72     } else if (!strcmp(gras_ddt_parse_text, "enum")) {
73       XBT_DEBUG("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       XBT_DEBUG("Pass space");
78
79     } else {
80       XBT_DEBUG("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       XBT_DEBUG("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   XBT_DEBUG("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   XBT_DEBUG("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     XBT_DEBUG("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     XBT_DEBUG("the base type is 'int', which were omited (you vicious user)");
284   } else {
285     identifier.type_name = (char *) strdup(gras_ddt_parse_text);
286     XBT_DEBUG("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       XBT_DEBUG("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 = xbt_dict_get_or_null(gras_dd_constants,
392                                                 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           XBT_DEBUG("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
424               ("Unparsable symbol: Expected 'GRAS_ANNOTE', got '%s'",
425                gras_ddt_parse_text);
426
427         gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
428         if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_LP)
429           PARSE_ERROR1
430               ("Unparsable annotation: Expected parenthesis, got '%s'",
431                gras_ddt_parse_text);
432
433         while ((gras_ddt_parse_tok_num =
434                 gras_ddt_parse_lex_n_dump()) ==
435                GRAS_DDT_PARSE_TOKEN_EMPTY);
436
437         if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_WORD)
438           PARSE_ERROR1
439               ("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()) ==
445                GRAS_DDT_PARSE_TOKEN_EMPTY);
446
447         if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_COLON)
448           PARSE_ERROR1
449               ("Unparsable annotation: expected ',' after the key name, got '%s'",
450                gras_ddt_parse_text);
451
452         while ((gras_ddt_parse_tok_num =
453                 gras_ddt_parse_lex_n_dump()) ==
454                GRAS_DDT_PARSE_TOKEN_EMPTY);
455
456         /* get the value */
457
458         if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_WORD)
459           PARSE_ERROR1
460               ("Unparsable annotation: Expected key value, got '%s'",
461                gras_ddt_parse_text);
462         keyval = (char *) strdup(gras_ddt_parse_text);
463
464         while ((gras_ddt_parse_tok_num =
465                 gras_ddt_parse_lex_n_dump()) ==
466                GRAS_DDT_PARSE_TOKEN_EMPTY);
467
468         /* Done with parsing the annotation. Now deal with it by replacing previously pushed type with the right one */
469
470         XBT_DEBUG("Anotation: %s=%s", keyname, keyval);
471         if (!strcmp(keyname, "size")) {
472           if (!identifier.tm.is_ref)
473             PARSE_ERROR0
474                 ("Size annotation for a field not being a reference");
475           identifier.tm.is_ref--;
476
477           if (!strcmp(keyval, "1")) {
478             change_to_ref(identifiers);
479             free(keyval);
480           } else {
481             char *p;
482             int fixed = 1;
483             for (p = keyval; *p != '\0'; p++)
484               if (!isdigit(*p))
485                 fixed = 0;
486             if (fixed) {
487               change_to_fixed_array(identifiers, atoi(keyval));
488               change_to_ref(identifiers);
489               free(keyval);
490
491             } else {
492               change_to_ref_pop_array(identifiers);
493               xbt_dynar_push(fields_to_push, &keyval);
494             }
495           }
496         } else if (!strcmp(keyname, "subtype")) {
497           gras_datadesc_type_t subtype = gras_datadesc_by_name(keyval);
498           if (identifier.tm.is_matrix) {
499             change_to_matrix_of(identifiers, subtype);
500             identifier.tm.is_matrix = -1;
501           } else if (identifier.tm.is_dynar) {
502             change_to_dynar_of(identifiers, subtype);
503             identifier.tm.is_dynar = -1;
504           } else {
505             PARSE_ERROR1
506                 ("subtype annotation only accepted for dynars and matrices, but passed to '%s'",
507                  identifier.type_name);
508           }
509           free(keyval);
510         } else if (!strcmp(keyname, "free_f")) {
511           int *storage = xbt_dict_get_or_null(gras_dd_constants, keyval);
512           if (!storage)
513             PARSE_ERROR1
514                 ("value for free_f annotation of field %s is not a known constant",
515                  identifier.name);
516           if (identifier.tm.is_matrix == -1) {
517             add_free_f(identifiers, *(void_f_pvoid_t *) storage);
518             identifier.tm.is_matrix = 0;
519           } else if (identifier.tm.is_dynar == -1) {
520             add_free_f(identifiers, *(void_f_pvoid_t *) storage);
521             identifier.tm.is_dynar = 0;
522           } else {
523             PARSE_ERROR1
524                 ("free_f annotation only accepted for dynars and matrices which subtype is already declared (field %s)",
525                  identifier.name);
526           }
527           free(keyval);
528         } else {
529           free(keyval);
530           PARSE_ERROR1("Unknown annotation type: '%s'", keyname);
531         }
532         free(keyname);
533
534         /* Get all the multipliers */
535         while (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_STAR) {
536
537           gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
538
539           if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_WORD)
540             PARSE_ERROR1
541                 ("Unparsable annotation: Expected field name after '*', got '%s'",
542                  gras_ddt_parse_text);
543
544           keyval = xbt_malloc(strlen(gras_ddt_parse_text) + 2);
545           sprintf(keyval, "*%s", gras_ddt_parse_text);
546
547           /* ask caller to push field as a multiplier */
548           xbt_dynar_push(fields_to_push, &keyval);
549
550           /* skip blanks after this block */
551           while ((gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump())
552                  == GRAS_DDT_PARSE_TOKEN_EMPTY);
553         }
554
555         if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_RP)
556           PARSE_ERROR1
557               ("Unparsable annotation: Expected parenthesis, got '%s'",
558                gras_ddt_parse_text);
559
560         continue;
561
562         /* End of annotation handling */
563       } else {
564         PARSE_ERROR1
565             ("Unparsable symbol: Got '%s' instead of expected comma (',')",
566              gras_ddt_parse_text);
567       }
568     } else if (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_COLON) {
569       PARSE_ERROR0("Unparsable symbol: Unexpected comma (',')");
570     }
571
572     if (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_STAR) {
573       identifier.tm.is_ref++;   /* We indeed deal with multiple references with multiple annotations */
574       continue;
575     }
576
577     /* found a symbol name. Build the type and push it to dynar */
578     if (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_WORD) {
579
580       identifier.name = (char *) strdup(gras_ddt_parse_text);
581       XBT_DEBUG("Found the identifier \"%s\"", identifier.name);
582
583       xbt_dynar_push(identifiers, &identifier);
584       XBT_DEBUG("Dynar_len=%lu", xbt_dynar_length(identifiers));
585       expect_id_separator = 1;
586       continue;
587     }
588
589     PARSE_ERROR0
590         ("Unparasable symbol (maybe a def struct in a def struct or a parser bug ;)");
591   }
592
593   if (identifier.tm.is_matrix > 0)
594     PARSE_ERROR0("xbt_matrix_t field without 'subtype' annotation");
595   if (identifier.tm.is_dynar > 0)
596     PARSE_ERROR0("xbt_dynar_t field without 'subtype' annotation");
597
598   XBT_OUT;
599 }
600
601 static gras_datadesc_type_t parse_struct(char *definition)
602 {
603
604   xbt_ex_t e;
605
606   char buffname[32];
607   static int anonymous_struct = 0;
608
609   xbt_dynar_t identifiers;
610   s_identifier_t field;
611   unsigned int iter;
612   int done;
613
614   xbt_dynar_t fields_to_push;
615   char *name;
616
617   gras_datadesc_type_t struct_type;
618
619   XBT_IN;
620   identifiers = xbt_dynar_new(sizeof(s_identifier_t), NULL);
621   fields_to_push = xbt_dynar_new(sizeof(char *), NULL);
622
623   /* Create the struct descriptor */
624   if (gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_WORD) {
625     struct_type = gras_datadesc_struct(gras_ddt_parse_text);
626     XBT_VERB("Parse the struct '%s'", gras_ddt_parse_text);
627     gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
628   } else {
629     sprintf(buffname, "anonymous struct %d", anonymous_struct++);
630     XBT_VERB("Parse the anonymous struct nb %d", anonymous_struct);
631     struct_type = gras_datadesc_struct(buffname);
632   }
633
634   if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_LA)
635     PARSE_ERROR1
636         ("Unparasable symbol: Expecting struct definition, but got %s instead of '{'",
637          gras_ddt_parse_text);
638
639   /* Parse the identifiers */
640   done = 0;
641   do {
642     TRY {
643       parse_statement(definition, identifiers, fields_to_push);
644     }
645     CATCH(e) {
646       if (e.category != mismatch_error)
647         RETHROW;
648       xbt_ex_free(e);
649       done = 1;
650     }
651
652     XBT_DEBUG("This statement contained %lu identifiers",
653            xbt_dynar_length(identifiers));
654     /* append the identifiers we've found */
655     xbt_dynar_foreach(identifiers, iter, field) {
656       if (field.tm.is_ref)
657         PARSE_ERROR2
658             ("Not enough GRAS_ANNOTATE to deal with all dereferencing levels of %s (%d '*' left)",
659              field.name, field.tm.is_ref);
660
661       XBT_VERB("Append field '%s' to %p", field.name, (void *) struct_type);
662       gras_datadesc_struct_append(struct_type, field.name, field.type);
663       free(field.name);
664       free(field.type_name);
665
666     }
667     xbt_dynar_reset(identifiers);
668     XBT_DEBUG("struct_type=%p", (void *) struct_type);
669
670     /* Make sure that all fields declaring a size push it into the cbps */
671     xbt_dynar_foreach(fields_to_push, iter, name) {
672       XBT_DEBUG("struct_type=%p", (void *) struct_type);
673       if (name[0] == '*') {
674         XBT_VERB("Push field '%s' as a multiplier into size stack of %p",
675               name + 1, (void *) struct_type);
676         gras_datadesc_cb_field_push_multiplier(struct_type, name + 1);
677       } else {
678         XBT_VERB("Push field '%s' into size stack of %p",
679               name, (void *) struct_type);
680         gras_datadesc_cb_field_push(struct_type, name);
681       }
682       free(name);
683     }
684     xbt_dynar_reset(fields_to_push);
685   } while (!done);
686   gras_datadesc_struct_close(struct_type);
687
688   /* terminates */
689   if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_RA)
690     PARSE_ERROR1
691         ("Unparasable symbol: Expected '}' at the end of struct definition, got '%s'",
692          gras_ddt_parse_text);
693
694   gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
695
696   xbt_dynar_free(&identifiers);
697   xbt_dynar_free(&fields_to_push);
698   XBT_OUT;
699   return struct_type;
700 }
701
702 static gras_datadesc_type_t parse_typedef(char *definition)
703 {
704
705   s_type_modifier_t tm;
706
707   gras_datadesc_type_t struct_desc = NULL;
708   gras_datadesc_type_t typedef_desc = NULL;
709
710   XBT_IN;
711   memset(&tm, 0, sizeof(tm));
712
713   /* get the aliased type */
714   parse_type_modifier(&tm);
715
716   if (tm.is_struct) {
717     struct_desc = parse_struct(definition);
718   }
719
720   parse_type_modifier(&tm);
721
722   if (tm.is_ref)
723     PARSE_ERROR0
724         ("GRAS_DEFINE_TYPE cannot handle reference without annotation");
725
726   /* get the aliasing name */
727   if (gras_ddt_parse_tok_num != GRAS_DDT_PARSE_TOKEN_WORD)
728     PARSE_ERROR1
729         ("Unparsable typedef: Expected the alias name, and got '%s'",
730          gras_ddt_parse_text);
731
732   /* (FIXME: should) build the alias */
733   PARSE_ERROR0
734       ("Unimplemented feature: GRAS_DEFINE_TYPE cannot handle typedef yet");
735
736   XBT_OUT;
737   return typedef_desc;
738 }
739
740
741 /**
742  * gras_datadesc_parse:
743  *
744  * Create a datadescription from the result of parsing the C type description
745  */
746 gras_datadesc_type_t
747 gras_datadesc_parse(const char *name, const char *C_statement)
748 {
749
750   gras_datadesc_type_t res = NULL;
751   char *definition;
752   int semicolon_count = 0;
753   int def_count, C_count;
754
755   XBT_IN;
756   /* reput the \n in place for debug */
757   for (C_count = 0; C_statement[C_count] != '\0'; C_count++)
758     if (C_statement[C_count] == ';' || C_statement[C_count] == '{')
759       semicolon_count++;
760   definition = (char *) xbt_malloc(C_count + semicolon_count + 1);
761   for (C_count = 0, def_count = 0; C_statement[C_count] != '\0'; C_count++) {
762     definition[def_count++] = C_statement[C_count];
763     if (C_statement[C_count] == ';' || C_statement[C_count] == '{') {
764       definition[def_count++] = '\n';
765     }
766   }
767   definition[def_count] = '\0';
768
769   /* init */
770   XBT_VERB("_gras_ddt_type_parse(%s) -> %d chars", definition, def_count);
771   gras_ddt_parse_pointer_string_init(definition);
772
773   /* Do I have a typedef, or a raw struct ? */
774   gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
775
776   if ((gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_WORD)
777       && (!strcmp(gras_ddt_parse_text, "struct"))) {
778     gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
779     res = parse_struct(definition);
780
781   } else if ((gras_ddt_parse_tok_num == GRAS_DDT_PARSE_TOKEN_WORD)
782              && (!strcmp(gras_ddt_parse_text, "typedef"))) {
783     gras_ddt_parse_tok_num = gras_ddt_parse_lex_n_dump();
784     res = parse_typedef(definition);
785
786   } else {
787     XBT_ERROR
788         ("Failed to parse the following symbol (not a struct neither a typedef) :\n%s",
789          definition);
790     xbt_abort();
791   }
792
793   gras_ddt_parse_pointer_string_close();
794   XBT_VERB("end of _gras_ddt_type_parse()");
795   free(definition);
796   /* register it under the name provided as symbol */
797   if (strcmp(res->name, name)) {
798     XBT_ERROR
799         ("In GRAS_DEFINE_TYPE, the provided symbol (here %s) must be the C type name (here %s)",
800          name, res->name);
801     xbt_abort();
802   }
803   gras_ddt_parse_lex_destroy();
804   XBT_OUT;
805   return res;
806 }
807
808 xbt_dict_t gras_dd_constants;
809 /** \brief Declare a constant to the parsing mecanism. See the "\#define and fixed size array" section */
810 void gras_datadesc_set_const(const char *name, int value)
811 {
812   int *stored = xbt_new(int, 1);
813   *stored = value;
814
815   xbt_dict_set(gras_dd_constants, name, stored, xbt_free_f);
816 }