3 /* gs/parse.c -- automatic parsing of data structures */
5 /* Authors: Arnaud Legrand, Martin Quinson */
7 #include "gs/gs_private.h"
8 #include "gs/parse.yy.h"
10 GRAS_LOG_NEW_DEFAULT_SUBCATEGORY(NDR_parse,NDR);
12 typedef struct s_type_modifier{
24 extern char *gs_parse_text;
27 static void parse_type_modifier(type_modifier_t *type_modifier);
28 static void print_type_modifier(type_modifier_t type_modifier);
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);
39 static void parse_type_modifier(type_modifier_t *type_modifier) {
41 if (gs_parse_tok_num == GS_PARSE_TOKEN_STAR) {
42 DEBUG0("This is a reference");
43 type_modifier->is_ref++;
45 } else if (!strcmp(gs_parse_text,"unsigned")) {
46 DEBUG0("This is an unsigned");
47 type_modifier->is_unsigned = 1;
49 } else if (!strcmp(gs_parse_text,"short")) {
50 DEBUG0("This is short");
51 type_modifier->is_short = 1;
53 } else if (!strcmp(gs_parse_text,"long")) {
54 DEBUG0("This is long");
55 type_modifier->is_long++; /* "long long" needs love */
57 } else if (!strcmp(gs_parse_text,"struct")) {
58 DEBUG0("This is a struct");
59 type_modifier->is_struct = 1;
61 } else if (!strcmp(gs_parse_text,"union")) {
62 DEBUG0("This is an union");
63 type_modifier->is_union = 1;
65 } else if (!strcmp(gs_parse_text,"enum")) {
66 DEBUG0("This is an enum");
67 type_modifier->is_enum = 1;
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))
81 static void print_type_modifier(type_modifier_t tm) {
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) ");
88 if(tm.is_struct) printf("(struct) ");
89 if(tm.is_enum) printf("(enum) ");
90 if(tm.is_union) printf("(union) ");
92 for (i=0 ; i<tm.is_ref ; i++) printf("(ref) ");
95 /* FIXME: Missing function. Do not free the dynar... */
96 #define gs_type_copy(a) a
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;
104 char *base_type = NULL;
110 int expect_a_colon = 0;
112 gras_dynar_reset(*dynar);
113 memset(&tm,0,sizeof(tm));
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 */
119 DEBUG0("Parse a new statement.");
122 if(gs_parse_tok_num != GS_PARSE_TOKEN_WORD) {
124 "Unparsable symbol: found a typeless statement (got '%s' instead). Definition was:\n%s\n",
125 gs_parse_text, definition);
129 /**** get the type modifier of this statement ****/
130 parse_type_modifier(&tm);
132 /* FIXME: This does not detect recursive definitions at all
133 if (tm.is_union || tm.is_enum || tm.is_struct) {
135 "Cannot handle recursive type definition yet. Definition was:\n%s\n",
140 /**** get the base type, giving "short a" the needed love ****/
145 (tm.is_short || tm.is_long || tm.is_unsigned) &&
147 strcmp(gs_parse_text,"char") &&
148 strcmp(gs_parse_text,"float") &&
149 strcmp(gs_parse_text,"double") &&
150 strcmp(gs_parse_text,"int") ) {
152 /* bastard user, they omited "int" ! */
153 base_type=strdup("int");
154 DEBUG0("the base type is 'int', which were omited");
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();
161 /**** build the base type for latter use ****/
164 "Cannot handle union yet (need annotation to get the callback), sorry. Definition was:\n%s\n",
169 sprintf(buffname,"union %s",base_type);
170 res = bag->bag_ops->get_type_by_name(bag, NULL, buffname);
172 res = gs_type_new_union(bag,NULL,buffname);
176 } else if (tm.is_enum) {
178 "Cannot handle enum yet (need grassouillet's love), sorry. Definition was:\n%s\n",
182 sprintf(buffname,"enum %s",base_type);
183 res = bag->bag_ops->get_type_by_name(bag, NULL, bufname);
185 res = gs_type_new_enum(bag,connection,buffname);
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);
193 res = gs_type_new_struct(bag,NULL,buffname);
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)) \
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);
213 res = gs_parse_get_or_create(unsigned int,unsigned_integer);
216 } else if (!strcmp(base_type, "char")) {
217 res = gs_parse_get_or_create(unsigned char,unsigned_integer);
219 } else { /* impossible, gcc parses this shit before us */
223 } else if (!strcmp(base_type, "float")) {
224 /* no modificator allowed by gcc */
225 res = gs_parse_get_or_create(float,floating_point);
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);
236 res = gs_parse_get_or_create(int,unsigned_integer);
239 } else if (!strcmp(base_type, "char")) {
240 res = gs_parse_get_or_create(char,unsigned_integer);
242 } else { /* impossible */
250 "Cannot handle references yet (need annotations), sorry. Definition was:\n%s\n",
253 /* Should build ref on the current res (beware of int****) */
256 /**** look for the symbols of this type ****/
258 for( /* no initialization */ ;
260 ((gs_parse_tok_num != GS_PARSE_TOKEN_EMPTY) &&
261 (gs_parse_tok_num != GS_PARSE_TOKEN_SEMI_COLON)) ;
263 gs_parse_tok_num = gs_parse_lex_n_dump() ) {
266 if(gs_parse_tok_num == GS_PARSE_TOKEN_COLON) {
271 "Unparsable symbol: Expected a comma (','), got '%s' instead. Definition was:\n%s\n",
272 gs_parse_text, definition);
275 } else if(gs_parse_tok_num == GS_PARSE_TOKEN_COLON) {
277 "Unparsable symbol: Unexpected comma (','). Definition was:\n%s\n",
282 if(gs_parse_tok_num == GS_PARSE_TOKEN_STAR) {
286 /* found a symbol name. Build the type and push it to dynar */
287 if(gs_parse_tok_num == GS_PARSE_TOKEN_WORD) {
289 /* FIXME: Build a ref or array on the base type */
291 "Cannot handle references yet (need annotations), sorry. Definition was:\n%s\n",
295 DEBUG1("Encountered the variable (field?) %s",gs_parse_text);
297 TRY(gras_dynar_push(*dynar, &gs_type_copy(base_type)));
304 "Unparasable symbol: Maybe a def struct in a def struct or so. The definition was:\n%s\n",
309 DEBUG0("End of this statement");
313 static gras_type_t *parse_struct(gras_type_bag_t *bag,
314 const char *definition) {
316 gras_error_t errcode;
318 static int anonymous_struct=0;
320 gras_dynar_t *fields;
325 gras_type_t *struct_type;
327 errcode=gras_dynar_new(&fields,sizeof(gras_type_t*),NULL);
328 if (errcode != no_error)
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 ;)
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();
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);
345 if (gs_parse_tok_num != GS_PARSE_TOKEN_LP) {
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);
352 /* Parse the fields */
353 for (errcode=parse_statement(bag,definition,&fields);
354 errcode == no_error ;
355 errcode=parse_statement(bag,definition,&fields)) {
357 DEBUG1("This statement contained %d fields",gras_dynar_length(fields));
358 gras_dynar_foreach(fields,i, field) {
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);
366 if (errcode != mismatch_error)
367 return NULL; /* FIXME: LEAK! */
370 if (gs_parse_tok_num != GS_PARSE_TOKEN_RP) {
372 "Unparasable symbol: Expected '}' at the end of struct definition, got '%s'. The definition was:\n%s\n",
373 gs_parse_text,definition);
377 gs_parse_tok_num = gs_parse_lex_n_dump();
379 gras_dynar_free(fields);
383 static gras_type_t * parse_typedef(gras_type_bag_t *bag,
384 const char *definition) {
388 gras_type_t *struct_desc=NULL;
389 gras_type_t *typedef_desc=NULL;
391 memset(&tm,0,sizeof(tm));
393 /* get the aliased type */
394 parse_type_modifier(&tm);
397 struct_desc = parse_struct(bag,definition);
400 parse_type_modifier(&tm);
404 "Cannot handle reference without annotation. Definition was:\n%s\n",
409 /* get the aliasing name */
410 if (gs_parse_tok_num != GS_PARSE_TOKEN_WORD) {
412 "Unparsable typedef: Expected the alias name, and got '%s'.\n%s\n",
413 gs_parse_text,definition);
417 /* (FIXME: should) build the alias */
418 fprintf(stderr, "Cannot handle typedef yet (need love from grassouillet), sorry. Definition was: \n%s\n",definition);
421 // res=gs_type_new_typedef(bag, NULL, strdup(gs_parse_text) );
428 _gs_type_parse(gras_type_bag_t *bag,
429 const char *definition) {
431 gras_type_t * res=NULL;
434 DEBUG1("_gs_type_parse(%s)",definition);
435 gs_parse_pointer_string_init(definition);
437 /* Do I have a typedef, or a raw struct ?*/
438 gs_parse_tok_num = gs_parse_lex_n_dump();
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);
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);
449 fprintf(stderr,"Failed to parse the following symbol (not a struct neither a typedef) :\n%s\n",definition);
453 gs_parse_pointer_string_close();
454 DEBUG1("end of _gs_type_parse(%s)",definition);