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