Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
mv gs/ DataDesc/
[simgrid.git] / src / gras / gs / parse.c
1 /* $Id$ */
2
3 /* gs/parse.c -- automatic parsing of data structures */
4
5 /* Authors: Arnaud Legrand, Martin Quinson            */
6
7 #include "gs/gs_private.h"
8 #include "gs/parse.yy.h"
9
10 GRAS_LOG_NEW_DEFAULT_SUBCATEGORY(NDR_parse,NDR);
11
12 typedef struct s_type_modifier{
13   short is_unsigned;
14   short is_short;
15   short is_long;
16
17   short is_struct;
18   short is_union;
19   short is_enum;
20
21   short is_ref;
22 } type_modifier_t;
23  
24 extern char *gs_parse_text;
25
26 /* prototypes */
27 static void parse_type_modifier(type_modifier_t         *type_modifier);
28 static void print_type_modifier(type_modifier_t          type_modifier);
29
30 static gras_error_t parse_statement(gras_type_bag_t     *p_bag,
31                                     const char          *definition,
32                                     gras_dynar_t        **dynar);
33 static gras_type_t * parse_struct(gras_type_bag_t       *p_bag,
34                                   const char            *definition);
35 static gras_type_t * parse_typedef(gras_type_bag_t      *p_bag,
36                                    const char           *definition);
37
38 /* local functions */
39 static void parse_type_modifier(type_modifier_t         *type_modifier)  {
40   do {
41     if (gs_parse_tok_num == GS_PARSE_TOKEN_STAR) {
42       DEBUG0("This is a reference");
43       type_modifier->is_ref++;
44
45     } else if (!strcmp(gs_parse_text,"unsigned")) {
46       DEBUG0("This is an unsigned");
47       type_modifier->is_unsigned = 1;
48
49     } else if (!strcmp(gs_parse_text,"short")) {
50       DEBUG0("This is short");
51       type_modifier->is_short = 1;
52
53     } else if (!strcmp(gs_parse_text,"long")) {
54       DEBUG0("This is long");
55       type_modifier->is_long++; /* "long long" needs love */
56
57     } else if (!strcmp(gs_parse_text,"struct")) {
58       DEBUG0("This is a struct");
59       type_modifier->is_struct = 1;
60
61     } else if (!strcmp(gs_parse_text,"union")) {
62       DEBUG0("This is an union");
63       type_modifier->is_union = 1;
64
65     } else if (!strcmp(gs_parse_text,"enum")) {
66       DEBUG0("This is an enum");
67       type_modifier->is_enum = 1;
68
69     } else {
70       break;
71     }
72     
73
74     gs_parse_tok_num = gs_parse_lex_n_dump();
75     if((gs_parse_tok_num != GS_PARSE_TOKEN_WORD) && 
76        (gs_parse_tok_num != GS_PARSE_TOKEN_STAR)) 
77       break;
78   } while(1);
79 }
80
81 static void print_type_modifier(type_modifier_t tm) {
82   int i;
83
84   if (tm.is_unsigned)             printf("(unsigned) ");
85   if (tm.is_short)                printf("(short) ");
86   for (i=0 ; i<tm.is_long ; i++)  printf("(long) ");
87
88   if(tm.is_struct)                printf("(struct) ");
89   if(tm.is_enum)                  printf("(enum) ");
90   if(tm.is_union)                 printf("(union) ");
91
92   for (i=0 ; i<tm.is_ref ; i++)   printf("(ref) ");
93 }
94
95 /* FIXME: Missing function. Do not free the dynar... */
96 #define gs_type_copy(a) a
97
98 static gras_error_t parse_statement(gras_type_bag_t     *bag,
99                                     const char          *definition,
100                                     gras_dynar_t        **dynar) {
101   gras_error_t errcode;
102   char buffname[512];
103
104   char *base_type = NULL;
105   type_modifier_t tm;
106
107   gras_type_t *res;
108
109   int starred = 0;
110   int expect_a_colon = 0;
111
112   gras_dynar_reset(*dynar);
113   memset(&tm,0,sizeof(tm));
114     
115   gs_parse_tok_num = gs_parse_lex_n_dump();
116   if(gs_parse_tok_num == GS_PARSE_TOKEN_RP) {
117     return mismatch_error; /* end of the englobing structure or union */
118   }
119   DEBUG0("Parse a new statement.");
120
121
122   if(gs_parse_tok_num != GS_PARSE_TOKEN_WORD) {
123     fprintf(stderr,
124             "Unparsable symbol: found a typeless statement (got '%s' instead). Definition was:\n%s\n",
125             gs_parse_text, definition);
126     abort();
127   }
128
129   /**** get the type modifier of this statement ****/
130   parse_type_modifier(&tm);
131
132   /*  FIXME: This does not detect recursive definitions at all
133   if (tm.is_union || tm.is_enum || tm.is_struct) {
134     fprintf(stderr,
135             "Cannot handle recursive type definition yet. Definition was:\n%s\n",
136             definition);
137     abort();
138     }*/
139
140   /**** get the base type, giving "short a" the needed love ****/
141   if (!tm.is_union &&
142       !tm.is_enum  && 
143       !tm.is_struct &&
144
145       (tm.is_short || tm.is_long || tm.is_unsigned) &&
146
147       strcmp(gs_parse_text,"char") && 
148       strcmp(gs_parse_text,"float") && 
149       strcmp(gs_parse_text,"double") && 
150       strcmp(gs_parse_text,"int") ) {
151
152     /* bastard user, they omited "int" ! */
153     base_type=strdup("int");
154     DEBUG0("the base type is 'int', which were omited");
155   } else {
156     base_type=strdup(gs_parse_text);
157     DEBUG1("the base type is '%s'",base_type);
158     gs_parse_tok_num = gs_parse_lex_n_dump(); 
159   }
160
161   /**** build the base type for latter use ****/
162   if (tm.is_union) {
163     fprintf(stderr,
164             "Cannot handle union yet (need annotation to get the callback), sorry. Definition was:\n%s\n",
165             definition);
166     abort();
167
168     /* FIXME 
169     sprintf(buffname,"union %s",base_type);
170     res = bag->bag_ops->get_type_by_name(bag, NULL, buffname);
171     if (!res) {
172       res = gs_type_new_union(bag,NULL,buffname);
173     }
174     */
175
176   } else if (tm.is_enum) {
177     fprintf(stderr,
178             "Cannot handle enum yet (need grassouillet's love), sorry. Definition was:\n%s\n",
179             definition);
180     abort();
181     /* FIXME
182     sprintf(buffname,"enum %s",base_type);
183     res = bag->bag_ops->get_type_by_name(bag, NULL, bufname);
184     if (!res) {
185       res = gs_type_new_enum(bag,connection,buffname);
186     }
187     */
188
189   } else if (tm.is_struct) {
190     sprintf(buffname,"struct %s",base_type);
191     res = bag->bag_ops->get_type_by_name(bag, NULL, buffname);
192     if (!res) {
193       res = gs_type_new_struct(bag,NULL,buffname);
194     }
195
196     /* Let's code like Alvin ;) */
197 #define gs_parse_get_or_create(name,func)               \
198    (bag->bag_ops->get_type_by_name(bag, NULL, #name) ?  \
199     bag->bag_ops->get_type_by_name(bag, NULL, #name) :  \
200     gs_type_new_##func##_elemental(bag, NULL,           \
201                                    #name, sizeof(name)) \
202    )
203
204   } else if (tm.is_unsigned) {
205     if (!strcmp(base_type,"int")) {
206       if (tm.is_long == 2) {
207         res = gs_parse_get_or_create(unsigned long long int,unsigned_integer);
208       } else if (tm.is_long) {
209         res = gs_parse_get_or_create(unsigned long int,unsigned_integer);
210       } else if (tm.is_short) {
211         res = gs_parse_get_or_create(unsigned short int,unsigned_integer);
212       } else {
213         res = gs_parse_get_or_create(unsigned int,unsigned_integer);
214       }
215
216     } else if (!strcmp(base_type, "char")) {
217       res = gs_parse_get_or_create(unsigned char,unsigned_integer);
218
219     } else { /* impossible, gcc parses this shit before us */
220       abort(); 
221     }
222     
223   } else if (!strcmp(base_type, "float")) {
224     /* no modificator allowed by gcc */
225     res = gs_parse_get_or_create(float,floating_point);
226
227   } else { /* signed integer elemental */
228     if (!strcmp(base_type,"int")) {
229       if (tm.is_long == 2) {
230         res = gs_parse_get_or_create(signed long long int,signed_integer);
231       } else if (tm.is_long) {
232         res = gs_parse_get_or_create(signed long int,signed_integer);
233       } else if (tm.is_short) {
234         res = gs_parse_get_or_create(signed short int,signed_integer);
235       } else {
236         res = gs_parse_get_or_create(int,unsigned_integer);
237       }
238
239     } else if (!strcmp(base_type, "char")) {
240       res = gs_parse_get_or_create(char,unsigned_integer);
241
242     } else { /* impossible */
243       abort(); 
244     }
245
246   } 
247
248   if (tm.is_ref) {
249     fprintf(stderr,
250             "Cannot handle references yet (need annotations), sorry. Definition was:\n%s\n",
251             definition);
252     abort();
253     /* Should build ref on the current res (beware of int****) */
254   }
255
256   /**** look for the symbols of this type ****/
257   expect_a_colon = 0;
258   for(          /* no initialization */                 ; 
259
260       ((gs_parse_tok_num != GS_PARSE_TOKEN_EMPTY) &&
261        (gs_parse_tok_num != GS_PARSE_TOKEN_SEMI_COLON)) ; 
262
263       gs_parse_tok_num = gs_parse_lex_n_dump()          ) {   
264
265     if(expect_a_colon) {
266       if(gs_parse_tok_num == GS_PARSE_TOKEN_COLON) {
267         expect_a_colon = 0;
268         continue;
269       } else {
270         fprintf(stderr,
271                 "Unparsable symbol: Expected a comma (','), got '%s' instead. Definition was:\n%s\n",
272                 gs_parse_text, definition);
273         abort();
274       }
275     } else if(gs_parse_tok_num == GS_PARSE_TOKEN_COLON) {
276       fprintf(stderr,
277               "Unparsable symbol: Unexpected comma (','). Definition was:\n%s\n",
278               definition);
279       abort();
280     }
281
282     if(gs_parse_tok_num == GS_PARSE_TOKEN_STAR) {
283       starred = 1;
284     }
285
286     /* found a symbol name. Build the type and push it to dynar */
287     if(gs_parse_tok_num == GS_PARSE_TOKEN_WORD) {
288       if (starred) {
289         /* FIXME: Build a ref or array on the base type */
290         fprintf(stderr,
291                 "Cannot handle references yet (need annotations), sorry. Definition was:\n%s\n",
292                 definition);
293         abort();
294       }
295       DEBUG1("Encountered the variable (field?) %s",gs_parse_text);
296
297       TRY(gras_dynar_push(*dynar, &gs_type_copy(base_type)));
298       starred = 0;
299       expect_a_colon = 1;
300       continue;
301     } 
302
303     fprintf(stderr,
304             "Unparasable symbol: Maybe a def struct in a def struct or so. The definition was:\n%s\n",
305             definition);
306     abort();
307   }
308
309   DEBUG0("End of this statement");
310   return no_error;
311 }
312
313 static gras_type_t *parse_struct(gras_type_bag_t        *bag,
314                                  const char             *definition) {
315
316   gras_error_t errcode;
317   char buffname[32];
318   static int anonymous_struct=0;
319
320   gras_dynar_t *fields;
321
322   gras_type_t *field;
323   int i;
324
325   gras_type_t *struct_type;
326
327   errcode=gras_dynar_new(&fields,sizeof(gras_type_t*),NULL);
328   if (errcode != no_error) 
329     return NULL;
330   /* FIXME: the dynar content leaks because there is no gs_type_free. 
331      But that's not a problem because each member are the same element since there is no gs_type_copy ;)
332   */
333
334   /* Create the struct descriptor */
335   if (gs_parse_tok_num == GS_PARSE_TOKEN_WORD) {
336     struct_type = gs_type_new_struct(bag,NULL, gs_parse_text);
337     DEBUG1("Parse the struct '%s'", gs_parse_text);
338     gs_parse_tok_num = gs_parse_lex_n_dump();
339   } else {
340     sprintf(buffname,"anonymous struct %d",anonymous_struct++); 
341     DEBUG1("Parse the anonymous struct nb %d", anonymous_struct);
342     struct_type = gs_type_new_struct(bag,NULL,buffname);
343   }
344
345   if (gs_parse_tok_num != GS_PARSE_TOKEN_LP) {
346     fprintf(stderr,
347             "Unparasable symbol: I looked for a struct definition, but got %s instead of '{'. The definition was:\n%s\n",
348             gs_parse_text,definition);
349     abort();
350   }
351
352   /* Parse the fields */
353   for (errcode=parse_statement(bag,definition,&fields);
354        errcode == no_error                            ;
355        errcode=parse_statement(bag,definition,&fields)) {
356     
357     DEBUG1("This statement contained %d fields",gras_dynar_length(fields));
358     gras_dynar_foreach(fields,i, field) {
359       char fname[128];
360       static int field_count=0;
361       sprintf(fname,"%d",field_count++);
362       DEBUG0("Append a field");      
363       gs_type_struct_append_field(struct_type,fname,field);
364     }
365   }
366   if (errcode != mismatch_error)
367     return NULL; /* FIXME: LEAK! */
368
369   /* terminates */
370   if (gs_parse_tok_num != GS_PARSE_TOKEN_RP) {
371     fprintf(stderr,
372             "Unparasable symbol: Expected '}' at the end of struct definition, got '%s'. The definition was:\n%s\n",
373             gs_parse_text,definition);
374     abort();
375   } 
376
377   gs_parse_tok_num = gs_parse_lex_n_dump();
378
379   gras_dynar_free(fields);
380   return struct_type;
381 }
382
383 static gras_type_t * parse_typedef(gras_type_bag_t      *bag,
384                                    const char           *definition) {
385
386   type_modifier_t tm;
387
388   gras_type_t *struct_desc=NULL;
389   gras_type_t *typedef_desc=NULL;
390
391   memset(&tm,0,sizeof(tm));
392
393   /* get the aliased type */
394   parse_type_modifier(&tm);
395
396   if (tm.is_struct) {
397     struct_desc = parse_struct(bag,definition);
398   }
399
400   parse_type_modifier(&tm);
401
402   if (tm.is_ref) {
403     fprintf(stderr,
404             "Cannot handle reference without annotation. Definition was:\n%s\n",
405             definition);
406     abort();
407   }    
408
409   /* get the aliasing name */
410   if (gs_parse_tok_num != GS_PARSE_TOKEN_WORD) {
411     fprintf(stderr,
412             "Unparsable typedef: Expected the alias name, and got '%s'.\n%s\n",
413             gs_parse_text,definition);
414     abort();
415   }
416   
417   /* (FIXME: should) build the alias */
418   fprintf(stderr, "Cannot handle typedef yet (need love from grassouillet), sorry. Definition was: \n%s\n",definition);
419   abort();
420
421   //  res=gs_type_new_typedef(bag, NULL, strdup(gs_parse_text) );
422   
423   return typedef_desc;
424 }
425
426 /* main function */
427 gras_type_t *
428 _gs_type_parse(gras_type_bag_t  *bag,
429                const char       *definition) {
430
431   gras_type_t * res=NULL;
432
433   /* init */ 
434   DEBUG1("_gs_type_parse(%s)",definition);
435   gs_parse_pointer_string_init(definition);
436
437   /* Do I have a typedef, or a raw struct ?*/
438   gs_parse_tok_num = gs_parse_lex_n_dump();
439   
440   if ((gs_parse_tok_num == GS_PARSE_TOKEN_WORD) && (!strcmp(gs_parse_text,"struct"))) {
441     gs_parse_tok_num = gs_parse_lex_n_dump();
442     res = parse_struct(bag,definition);
443       
444   } else if ((gs_parse_tok_num == GS_PARSE_TOKEN_WORD) && (!strcmp(gs_parse_text,"typedef"))) {
445     gs_parse_tok_num = gs_parse_lex_n_dump();
446     res = parse_typedef(bag,definition);
447
448   } else {
449     fprintf(stderr,"Failed to parse the following symbol (not a struct neither a typedef) :\n%s\n",definition);    
450     abort();
451   }
452
453   gs_parse_pointer_string_close();
454   DEBUG1("end of _gs_type_parse(%s)",definition);
455
456   return res;
457 }
458
459