improvements for handling of function parameters
[cparser] / type.c
1 #include <config.h>
2
3 #include "type_t.h"
4 #include "adt/error.h"
5
6 static struct obstack  _type_obst;
7 struct obstack        *type_obst = &_type_obst;
8 static FILE           *out;
9
10 static void intern_print_type_pre(const type_t *type);
11 static void intern_print_type_post(const type_t *type);
12
13 void init_types()
14 {
15         obstack_init(type_obst);
16 }
17
18 void exit_types()
19 {
20         obstack_free(type_obst, NULL);
21 }
22
23 void type_set_output(FILE *stream)
24 {
25         out = stream;
26 }
27
28 static
29 void print_type_qualifiers(unsigned qualifiers)
30 {
31         if(qualifiers & TYPE_QUALIFIER_CONST) {
32                 fputs("const ", out);
33         }
34         if(qualifiers & TYPE_QUALIFIER_VOLATILE) {
35                 fputs("volatile ", out);
36         }
37         if(qualifiers & TYPE_QUALIFIER_RESTRICT) {
38                 fputs("restrict ", out);
39         }
40         if(qualifiers & TYPE_QUALIFIER_INLINE) {
41                 fputs("inline ", out);
42         }
43 }
44
45 static
46 void print_atomic_type(const atomic_type_t *type)
47 {
48         print_type_qualifiers(type->type.qualifiers);
49
50         switch(type->atype) {
51         case ATOMIC_TYPE_INVALID:     fputs("INVALIDATOMIC", out); return;
52         case ATOMIC_TYPE_VOID:        fputs("void", out); return;
53         case ATOMIC_TYPE_BOOL:        fputs("bool", out); return;
54         case ATOMIC_TYPE_CHAR:        fputs("char", out); return;
55         case ATOMIC_TYPE_SCHAR:       fputs("signed char", out); return;
56         case ATOMIC_TYPE_UCHAR:       fputs("unsigned char", out); return;
57         case ATOMIC_TYPE_INT:         fputs("int", out); return;
58         case ATOMIC_TYPE_UINT:        fputs("unsigned int", out); return;
59         case ATOMIC_TYPE_SHORT:       fputs("short", out); return;
60         case ATOMIC_TYPE_USHORT:      fputs("unsigned short", out); return;
61         case ATOMIC_TYPE_LONG:        fputs("long", out); return;
62         case ATOMIC_TYPE_ULONG:       fputs("unsigned long", out); return;
63         case ATOMIC_TYPE_LONGLONG:    fputs("long long", out); return;
64         case ATOMIC_TYPE_ULONGLONG:   fputs("unsigned long long", out); return;
65         case ATOMIC_TYPE_LONG_DOUBLE: fputs("long double", out); return;
66         case ATOMIC_TYPE_FLOAT:       fputs("float", out); return;
67         case ATOMIC_TYPE_DOUBLE:      fputs("double", out); return;
68         }
69         fputs("UNKNOWNATOMIC", out);
70 }
71
72 static
73 void print_method_type_pre(const method_type_t *type)
74 {
75         print_type_qualifiers(type->type.qualifiers);
76
77         intern_print_type_pre(type->result_type);
78
79         /* TODO: don't emit braces if we're the toplevel type... */
80         fputc('(', out);
81 }
82
83 static
84 void print_method_type_post(const method_type_t *type)
85 {
86         /* TODO: don't emit braces if we're the toplevel type... */
87         intern_print_type_post(type->result_type);
88         fputc(')', out);
89
90         fputc('(', out);
91
92         declaration_t *parameter = type->parameters;
93         int            first     = 1;
94         for( ; parameter != NULL; parameter = parameter->next) {
95                 if(first) {
96                         first = 0;
97                 } else {
98                         fputs(", ", out);
99                 }
100                 print_type(parameter->type, parameter->symbol);
101         }
102         if(type->variadic) {
103                 if(first) {
104                         first = 0;
105                 } else {
106                         fputs(", ", out);
107                 }
108                 fputs("...", out);
109         }
110         if(first && !type->unspecified_parameters) {
111                 fputs("void", out);
112         }
113         fputc(')', out);
114 }
115
116 static
117 void print_pointer_type_pre(const pointer_type_t *type)
118 {
119         intern_print_type_pre(type->points_to);
120         fputs("*", out);
121         print_type_qualifiers(type->type.qualifiers);
122 }
123
124 static
125 void print_pointer_type_post(const pointer_type_t *type)
126 {
127         intern_print_type_post(type->points_to);
128 }
129
130 static
131 void print_type_enum(const enum_type_t *type)
132 {
133         print_type_qualifiers(type->type.qualifiers);
134         if(type->symbol != NULL) {
135                 fprintf(out, "enum %s", type->symbol->string);
136         } else {
137                 fprintf(out, "enum {\n");
138
139                 enum_entry_t *entry = type->entries;
140                 for( ; entry != NULL; entry = entry->next) {
141                         fprintf(out, "\t%s", entry->symbol->string);
142                         if(entry->value != NULL) {
143                                 fprintf(out, " = ");
144                                 print_expression(entry->value);
145                         }
146                         fprintf(out, ",\n");
147                 }
148
149                 fprintf(out, "} ");
150         }
151 }
152
153 static
154 void intern_print_type_pre(const type_t *type)
155 {
156         switch(type->type) {
157         case TYPE_INVALID:
158                 fputs("invalid", out);
159                 return;
160         case TYPE_ENUM:
161                 print_type_enum((const enum_type_t*) type);
162                 return;
163         case TYPE_ATOMIC:
164                 print_atomic_type((const atomic_type_t*) type);
165                 return;
166         case TYPE_COMPOUND_STRUCT:
167         case TYPE_COMPOUND_UNION:
168                 print_type_qualifiers(type->qualifiers);
169                 if(((const compound_type_t*) type)->symbol != NULL) {
170                         fprintf(out, "%s", ((const compound_type_t*) type)->symbol->string);
171                 }
172                 return;
173         case TYPE_BUILTIN:
174                 fputs(((builtin_type_t*) type)->symbol->string, out);
175                 return;
176         case TYPE_METHOD:
177                 print_method_type_pre((const method_type_t*) type);
178                 return;
179         case TYPE_POINTER:
180                 print_pointer_type_pre((const pointer_type_t*) type);
181                 return;
182         }
183         fputs("unknown", out);
184 }
185
186 static
187 void intern_print_type_post(const type_t *type)
188 {
189         switch(type->type) {
190         case TYPE_METHOD:
191                 print_method_type_post((const method_type_t*) type);
192                 return;
193         case TYPE_POINTER:
194                 print_pointer_type_post((const pointer_type_t*) type);
195                 return;
196         case TYPE_INVALID:
197         case TYPE_ATOMIC:
198         case TYPE_ENUM:
199         case TYPE_COMPOUND_STRUCT:
200         case TYPE_COMPOUND_UNION:
201         case TYPE_BUILTIN:
202                 break;
203         }
204 }
205
206 void print_type(const type_t *type, const symbol_t *symbol)
207 {
208         if(type == NULL) {
209                 fputs("nil type", out);
210                 return;
211         }
212
213         intern_print_type_pre(type);
214         if(symbol != NULL) {
215                 fputc(' ', out);
216                 fputs(symbol->string, out);
217         }
218         intern_print_type_post(type);
219 }
220
221 int type_valid(const type_t *type)
222 {
223         return type->type != TYPE_INVALID;
224 }
225
226 int is_type_int(const type_t *type)
227 {
228         if(type->type != TYPE_ATOMIC)
229                 return 0;
230
231         atomic_type_t *atomic_type = (atomic_type_t*) type;
232         switch(atomic_type->atype) {
233         case ATOMIC_TYPE_CHAR:
234         case ATOMIC_TYPE_SCHAR:
235         case ATOMIC_TYPE_UCHAR:
236         case ATOMIC_TYPE_SHORT:
237         case ATOMIC_TYPE_USHORT:
238         case ATOMIC_TYPE_INT:
239         case ATOMIC_TYPE_UINT:
240         case ATOMIC_TYPE_LONG:
241         case ATOMIC_TYPE_ULONG:
242         case ATOMIC_TYPE_LONGLONG:
243         case ATOMIC_TYPE_ULONGLONG:
244                 return 1;
245         default:
246                 return 0;
247         }
248 }
249
250 static __attribute__((unused))
251 void dbg_type(const type_t *type)
252 {
253         FILE *old_out = out;
254         out = stderr;
255         print_type(type, NULL);
256         puts("\n");
257         fflush(stderr);
258         out = old_out;
259 }