- implemented decimal floating pointer numbers in lexer
[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_array_type_post(const array_type_t *type)
146 {
147         fputc('[', out);
148         if(type->is_static) {
149                 fputs("static ", out);
150         }
151         print_type_qualifiers(type->type.qualifiers);
152         if(type->size != NULL) {
153                 print_expression(type->size);
154         }
155         fputc(']', out);
156 }
157
158 static void print_type_enum(const enum_type_t *type)
159 {
160         print_type_qualifiers(type->type.qualifiers);
161         if(type->symbol != NULL) {
162                 fprintf(out, "enum %s", type->symbol->string);
163         } else {
164                 fprintf(out, "enum {\n");
165
166                 declaration_t *entry = type->entries_begin;
167                 for( ; entry != type->entries_end->next; entry = entry->next) {
168                         fprintf(out, "\t%s", entry->symbol->string);
169                         if(entry->initializer != NULL) {
170                                 fprintf(out, " = ");
171                                 print_expression(entry->initializer);
172                         }
173                         fprintf(out, ",\n");
174                 }
175
176                 fprintf(out, "} ");
177         }
178 }
179
180 static void intern_print_type_pre(const type_t *type)
181 {
182         switch(type->type) {
183         case TYPE_INVALID:
184                 fputs("invalid", out);
185                 return;
186         case TYPE_ENUM:
187                 print_type_enum((const enum_type_t*) type);
188                 return;
189         case TYPE_ATOMIC:
190                 print_atomic_type((const atomic_type_t*) type);
191                 return;
192         case TYPE_COMPOUND_STRUCT:
193         case TYPE_COMPOUND_UNION:
194                 print_type_qualifiers(type->qualifiers);
195                 if(((const compound_type_t*) type)->symbol != NULL) {
196                         fprintf(out, "%s", ((const compound_type_t*) type)->symbol->string);
197                 }
198                 return;
199         case TYPE_BUILTIN:
200                 fputs(((builtin_type_t*) type)->symbol->string, out);
201                 return;
202         case TYPE_METHOD:
203                 print_method_type_pre((const method_type_t*) type);
204                 return;
205         case TYPE_POINTER:
206                 print_pointer_type_pre((const pointer_type_t*) type);
207                 return;
208         case TYPE_ARRAY:
209                 return;
210         }
211         fputs("unknown", out);
212 }
213
214 static
215 void intern_print_type_post(const type_t *type)
216 {
217         switch(type->type) {
218         case TYPE_METHOD:
219                 print_method_type_post((const method_type_t*) type, NULL);
220                 return;
221         case TYPE_POINTER:
222                 print_pointer_type_post((const pointer_type_t*) type);
223                 return;
224         case TYPE_ARRAY:
225                 print_array_type_post((const array_type_t*) type);
226                 return;
227         case TYPE_INVALID:
228         case TYPE_ATOMIC:
229         case TYPE_ENUM:
230         case TYPE_COMPOUND_STRUCT:
231         case TYPE_COMPOUND_UNION:
232         case TYPE_BUILTIN:
233                 break;
234         }
235 }
236
237 void print_type(const type_t *type)
238 {
239         print_type_ext(type, NULL, NULL);
240 }
241
242 void print_type_ext(const type_t *type, const symbol_t *symbol,
243                     const context_t *context)
244 {
245         if(type == NULL) {
246                 fputs("nil type", out);
247                 return;
248         }
249
250         intern_print_type_pre(type);
251         if(symbol != NULL) {
252                 fputc(' ', out);
253                 fputs(symbol->string, out);
254         }
255         if(type->type == TYPE_METHOD) {
256                 print_method_type_post((const method_type_t*) type, context);
257         } else {
258                 intern_print_type_post(type);
259         }
260 }
261
262 bool type_valid(const type_t *type)
263 {
264         return type->type != TYPE_INVALID;
265 }
266
267 bool is_type_int(const type_t *type)
268 {
269         if(type->type != TYPE_ATOMIC)
270                 return 0;
271
272         atomic_type_t *atomic_type = (atomic_type_t*) type;
273         switch(atomic_type->atype) {
274         case ATOMIC_TYPE_CHAR:
275         case ATOMIC_TYPE_SCHAR:
276         case ATOMIC_TYPE_UCHAR:
277         case ATOMIC_TYPE_SHORT:
278         case ATOMIC_TYPE_USHORT:
279         case ATOMIC_TYPE_INT:
280         case ATOMIC_TYPE_UINT:
281         case ATOMIC_TYPE_LONG:
282         case ATOMIC_TYPE_ULONG:
283         case ATOMIC_TYPE_LONGLONG:
284         case ATOMIC_TYPE_ULONGLONG:
285                 return 1;
286         default:
287                 return 0;
288         }
289 }
290
291 bool is_type_arithmetic(const type_t *type)
292 {
293         if(type->type != TYPE_ATOMIC)
294                 return 0;
295
296         atomic_type_t *atomic_type = (atomic_type_t*) type;
297         switch(atomic_type->atype) {
298         case ATOMIC_TYPE_CHAR:
299         case ATOMIC_TYPE_SCHAR:
300         case ATOMIC_TYPE_UCHAR:
301         case ATOMIC_TYPE_SHORT:
302         case ATOMIC_TYPE_USHORT:
303         case ATOMIC_TYPE_INT:
304         case ATOMIC_TYPE_UINT:
305         case ATOMIC_TYPE_LONG:
306         case ATOMIC_TYPE_ULONG:
307         case ATOMIC_TYPE_LONGLONG:
308         case ATOMIC_TYPE_ULONGLONG:
309         case ATOMIC_TYPE_FLOAT:
310         case ATOMIC_TYPE_DOUBLE:
311         case ATOMIC_TYPE_LONG_DOUBLE:
312 #ifdef PROVIDE_COMPLEX
313         case ATOMIC_TYPE_FLOAT_COMPLEX:
314         case ATOMIC_TYPE_DOUBLE_COMPLEX:
315         case ATOMIC_TYPE_LONG_DOUBLE_COMPLEX:
316 #endif
317 #ifdef PROVIDE_IMAGINARY
318         case ATOMIC_TYPE_FLOAT_IMAGINARY:
319         case ATOMIC_TYPE_DOUBLE_IMAGINARY:
320         case ATOMIC_TYPE_LONG_DOUBLE_IMAGINARY:
321 #endif
322                 return 1;
323         case ATOMIC_TYPE_INVALID:
324         case ATOMIC_TYPE_VOID:
325         case ATOMIC_TYPE_BOOL:
326                 return 0;
327         }
328
329         return 0;
330 }
331
332 bool is_type_scalar(const type_t *type)
333 {
334         if(type->type == TYPE_POINTER)
335                 return 1;
336
337         return is_type_arithmetic(type);
338 }
339
340 static type_t *identify_new_type(type_t *type)
341 {
342         type_t *result = typehash_insert(type);
343         if(result != type) {
344                 obstack_free(type_obst, type);
345         }
346         return result;
347 }
348
349 type_t *make_atomic_type(atomic_type_type_t type, unsigned qualifiers)
350 {
351         atomic_type_t *atomic_type
352                 = obstack_alloc(type_obst, sizeof(atomic_type[0]));
353         memset(atomic_type, 0, sizeof(atomic_type[0]));
354         atomic_type->type.type       = TYPE_ATOMIC;
355         atomic_type->type.qualifiers = qualifiers;
356         atomic_type->atype           = type;
357
358         return identify_new_type((type_t*) atomic_type);
359 }
360
361 type_t *make_pointer_type(type_t *points_to, unsigned qualifiers)
362 {
363         pointer_type_t *pointer_type
364                 = obstack_alloc(type_obst, sizeof(pointer_type[0]));
365         memset(pointer_type, 0, sizeof(pointer_type[0]));
366         pointer_type->type.type       = TYPE_POINTER;
367         pointer_type->type.qualifiers = qualifiers;
368         pointer_type->points_to       = points_to;
369
370         return identify_new_type((type_t*) pointer_type);
371 }
372
373 static __attribute__((unused))
374 void dbg_type(const type_t *type)
375 {
376         FILE *old_out = out;
377         out = stderr;
378         print_type(type);
379         puts("\n");
380         fflush(stderr);
381         out = old_out;
382 }