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