improve initializer handling
[cparser] / type.c
1 #include <config.h>
2
3 #include <stdio.h>
4 #include <assert.h>
5 #include "type_t.h"
6 #include "type_hash.h"
7 #include "adt/error.h"
8
9 static struct obstack   _type_obst;
10 struct obstack         *type_obst = &_type_obst;
11 static FILE            *out;
12
13 static void intern_print_type_pre(const type_t *type);
14 static void intern_print_type_post(const type_t *type);
15
16 void init_types(void)
17 {
18         obstack_init(type_obst);
19 }
20
21 void exit_types(void)
22 {
23         obstack_free(type_obst, NULL);
24 }
25
26 void type_set_output(FILE *stream)
27 {
28         out = stream;
29 }
30
31 static
32 void print_type_qualifiers(unsigned qualifiers)
33 {
34         if(qualifiers & TYPE_QUALIFIER_CONST)    fputs("const ",    out);
35         if(qualifiers & TYPE_QUALIFIER_VOLATILE) fputs("volatile ", out);
36         if(qualifiers & TYPE_QUALIFIER_RESTRICT) fputs("restrict ", out);
37         if(qualifiers & TYPE_QUALIFIER_INLINE)   fputs("inline ",   out);
38 }
39
40 static
41 void print_atomic_type(const atomic_type_t *type)
42 {
43         print_type_qualifiers(type->type.qualifiers);
44
45         const char *s;
46         switch(type->atype) {
47         case ATOMIC_TYPE_INVALID:     s = "INVALIDATOMIC";      break;
48         case ATOMIC_TYPE_VOID:        s = "void";               break;
49         case ATOMIC_TYPE_BOOL:        s = "_Bool";              break;
50         case ATOMIC_TYPE_CHAR:        s = "char";               break;
51         case ATOMIC_TYPE_SCHAR:       s = "signed char";        break;
52         case ATOMIC_TYPE_UCHAR:       s = "unsigned char";      break;
53         case ATOMIC_TYPE_INT:         s = "int";                break;
54         case ATOMIC_TYPE_UINT:        s = "unsigned int";       break;
55         case ATOMIC_TYPE_SHORT:       s = "short";              break;
56         case ATOMIC_TYPE_USHORT:      s = "unsigned short";     break;
57         case ATOMIC_TYPE_LONG:        s = "long";               break;
58         case ATOMIC_TYPE_ULONG:       s = "unsigned long";      break;
59         case ATOMIC_TYPE_LONGLONG:    s = "long long";          break;
60         case ATOMIC_TYPE_ULONGLONG:   s = "unsigned long long"; break;
61         case ATOMIC_TYPE_LONG_DOUBLE: s = "long double";        break;
62         case ATOMIC_TYPE_FLOAT:       s = "float";              break;
63         case ATOMIC_TYPE_DOUBLE:      s = "double";             break;
64         default:                      s = "UNKNOWNATOMIC";      break;
65         }
66         fputs(s, out);
67 }
68
69 static
70 void print_method_type_pre(const method_type_t *type)
71 {
72         print_type_qualifiers(type->type.qualifiers);
73
74         intern_print_type_pre(type->result_type);
75
76         /* TODO: don't emit braces if we're the toplevel type... */
77         fputc('(', out);
78 }
79
80 static
81 void print_method_type_post(const method_type_t *type, const context_t *context)
82 {
83         /* TODO: don't emit braces if we're the toplevel type... */
84         intern_print_type_post(type->result_type);
85         fputc(')', out);
86
87         fputc('(', out);
88
89         int                 first     = 1;
90         if(context == NULL) {
91                 method_parameter_t *parameter = type->parameters;
92                 for( ; parameter != NULL; parameter = parameter->next) {
93                         if(first) {
94                                 first = 0;
95                         } else {
96                                 fputs(", ", out);
97                         }
98                         print_type(parameter->type);
99                 }
100         } else {
101                 declaration_t *parameter = context->declarations;
102                 for( ; parameter != NULL; parameter = parameter->next) {
103                         if(first) {
104                                 first = 0;
105                         } else {
106                                 fputs(", ", out);
107                         }
108                         print_type_ext(parameter->type, parameter->symbol,
109                                        &parameter->context);
110                 }
111         }
112         if(type->variadic) {
113                 if(first) {
114                         first = 0;
115                 } else {
116                         fputs(", ", out);
117                 }
118                 fputs("...", out);
119         }
120         if(first && !type->unspecified_parameters) {
121                 fputs("void", out);
122         }
123         fputc(')', out);
124 }
125
126 static
127 void print_pointer_type_pre(const pointer_type_t *type)
128 {
129         intern_print_type_pre(type->points_to);
130         fputs("*", out);
131         print_type_qualifiers(type->type.qualifiers);
132 }
133
134 static void print_pointer_type_post(const pointer_type_t *type)
135 {
136         intern_print_type_post(type->points_to);
137 }
138
139 static void print_array_type_post(const array_type_t *type)
140 {
141         fputc('[', out);
142         if(type->is_static) {
143                 fputs("static ", out);
144         }
145         print_type_qualifiers(type->type.qualifiers);
146         if(type->size != NULL) {
147                 print_expression(type->size);
148         }
149         fputc(']', out);
150 }
151
152 static void print_type_enum(const enum_type_t *type)
153 {
154         print_type_qualifiers(type->type.qualifiers);
155         if(type->symbol != NULL) {
156                 fprintf(out, "enum %s", type->symbol->string);
157         } else {
158                 fprintf(out, "enum {\n");
159
160                 declaration_t *entry = type->entries_begin;
161                 for( ; entry != type->entries_end->next; entry = entry->next) {
162                         fprintf(out, "\t%s", entry->symbol->string);
163                         if(entry->initializer != NULL) {
164                                 fprintf(out, " = ");
165                                 print_initializer(entry->initializer);
166                         }
167                         fprintf(out, ",\n");
168                 }
169
170                 fprintf(out, "} ");
171         }
172 }
173
174 static void intern_print_type_pre(const type_t *type)
175 {
176         switch(type->type) {
177         case TYPE_INVALID:
178                 fputs("invalid", out);
179                 return;
180         case TYPE_ENUM:
181                 print_type_enum((const enum_type_t*) type);
182                 return;
183         case TYPE_ATOMIC:
184                 print_atomic_type((const atomic_type_t*) type);
185                 return;
186         case TYPE_COMPOUND_STRUCT:
187         case TYPE_COMPOUND_UNION:
188                 print_type_qualifiers(type->qualifiers);
189                 if(((const compound_type_t*) type)->symbol != NULL) {
190                         fprintf(out, "%s", ((const compound_type_t*) type)->symbol->string);
191                 }
192                 return;
193         case TYPE_BUILTIN:
194                 fputs(((builtin_type_t*) type)->symbol->string, out);
195                 return;
196         case TYPE_METHOD:
197                 print_method_type_pre((const method_type_t*) type);
198                 return;
199         case TYPE_POINTER:
200                 print_pointer_type_pre((const pointer_type_t*) type);
201                 return;
202         case TYPE_ARRAY:
203                 return;
204         }
205         fputs("unknown", out);
206 }
207
208 static
209 void intern_print_type_post(const type_t *type)
210 {
211         switch(type->type) {
212         case TYPE_METHOD:
213                 print_method_type_post((const method_type_t*) type, NULL);
214                 return;
215         case TYPE_POINTER:
216                 print_pointer_type_post((const pointer_type_t*) type);
217                 return;
218         case TYPE_ARRAY:
219                 print_array_type_post((const array_type_t*) type);
220                 return;
221         case TYPE_INVALID:
222         case TYPE_ATOMIC:
223         case TYPE_ENUM:
224         case TYPE_COMPOUND_STRUCT:
225         case TYPE_COMPOUND_UNION:
226         case TYPE_BUILTIN:
227                 break;
228         }
229 }
230
231 void print_type(const type_t *type)
232 {
233         print_type_ext(type, NULL, NULL);
234 }
235
236 void print_type_ext(const type_t *type, const symbol_t *symbol,
237                     const context_t *context)
238 {
239         if(type == NULL) {
240                 fputs("nil type", out);
241                 return;
242         }
243
244         intern_print_type_pre(type);
245         if(symbol != NULL) {
246                 fputc(' ', out);
247                 fputs(symbol->string, out);
248         }
249         if(type->type == TYPE_METHOD) {
250                 print_method_type_post((const method_type_t*) type, context);
251         } else {
252                 intern_print_type_post(type);
253         }
254 }
255
256 bool type_valid(const type_t *type)
257 {
258         return type->type != TYPE_INVALID;
259 }
260
261 bool is_type_integer(const type_t *type)
262 {
263         if(type->type == TYPE_ENUM)
264                 return 1;
265
266         if(type->type != TYPE_ATOMIC)
267                 return 0;
268
269         atomic_type_t *atomic_type = (atomic_type_t*) type;
270         switch(atomic_type->atype) {
271         case ATOMIC_TYPE_BOOL:
272         case ATOMIC_TYPE_CHAR:
273         case ATOMIC_TYPE_SCHAR:
274         case ATOMIC_TYPE_UCHAR:
275         case ATOMIC_TYPE_SHORT:
276         case ATOMIC_TYPE_USHORT:
277         case ATOMIC_TYPE_INT:
278         case ATOMIC_TYPE_UINT:
279         case ATOMIC_TYPE_LONG:
280         case ATOMIC_TYPE_ULONG:
281         case ATOMIC_TYPE_LONGLONG:
282         case ATOMIC_TYPE_ULONGLONG:
283                 return 1;
284         default:
285                 return 0;
286         }
287 }
288
289 bool is_type_floating(const type_t *type)
290 {
291         if(type->type != TYPE_ATOMIC)
292                 return 0;
293
294         atomic_type_t *atomic_type = (atomic_type_t*) type;
295         switch(atomic_type->atype) {
296         case ATOMIC_TYPE_FLOAT:
297         case ATOMIC_TYPE_DOUBLE:
298         case ATOMIC_TYPE_LONG_DOUBLE:
299 #ifdef PROVIDE_COMPLEX
300         case ATOMIC_TYPE_FLOAT_COMPLEX:
301         case ATOMIC_TYPE_DOUBLE_COMPLEX:
302         case ATOMIC_TYPE_LONG_DOUBLE_COMPLEX:
303 #endif
304 #ifdef PROVIDE_IMAGINARY
305         case ATOMIC_TYPE_FLOAT_IMAGINARY:
306         case ATOMIC_TYPE_DOUBLE_IMAGINARY:
307         case ATOMIC_TYPE_LONG_DOUBLE_IMAGINARY:
308 #endif
309                 return 1;
310         default:
311                 return 0;
312         }
313 }
314
315 bool is_type_arithmetic(const type_t *type)
316 {
317         if(is_type_integer(type) || is_type_floating(type))
318                 return 1;
319
320         return 0;
321 }
322
323 bool is_type_scalar(const type_t *type)
324 {
325         if(type->type == TYPE_POINTER)
326                 return 1;
327
328         return is_type_arithmetic(type);
329 }
330
331 static type_t *identify_new_type(type_t *type)
332 {
333         type_t *result = typehash_insert(type);
334         if(result != type) {
335                 obstack_free(type_obst, type);
336         }
337         return result;
338 }
339
340 type_t *make_atomic_type(atomic_type_type_t type, type_qualifier_t qualifiers)
341 {
342         atomic_type_t *atomic_type
343                 = obstack_alloc(type_obst, sizeof(atomic_type[0]));
344         memset(atomic_type, 0, sizeof(atomic_type[0]));
345         atomic_type->type.type       = TYPE_ATOMIC;
346         atomic_type->type.qualifiers = qualifiers;
347         atomic_type->atype           = type;
348
349         return identify_new_type((type_t*) atomic_type);
350 }
351
352 type_t *make_pointer_type(type_t *points_to, type_qualifier_t qualifiers)
353 {
354         pointer_type_t *pointer_type
355                 = obstack_alloc(type_obst, sizeof(pointer_type[0]));
356         memset(pointer_type, 0, sizeof(pointer_type[0]));
357         pointer_type->type.type       = TYPE_POINTER;
358         pointer_type->type.qualifiers = qualifiers;
359         pointer_type->points_to       = points_to;
360
361         return identify_new_type((type_t*) pointer_type);
362 }
363
364 static __attribute__((unused))
365 void dbg_type(const type_t *type)
366 {
367         FILE *old_out = out;
368         out = stderr;
369         print_type(type);
370         puts("\n");
371         fflush(stderr);
372         out = old_out;
373 }