Evaluate structure and union member dereferences (turn them into plain derefences
[smatch.git] / show-parse.c
blobe0618963741f3e0ea81a9b1d41314a0d8d443561
1 /*
2 * sparse/show-parse.c
4 * Copyright (C) 2003 Linus Torvalds, all rights reserved.
6 * Print out results of parsing for debugging and testing.
7 */
8 #include <stdarg.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <ctype.h>
13 #include <unistd.h>
14 #include <fcntl.h>
16 #include "lib.h"
17 #include "token.h"
18 #include "parse.h"
19 #include "symbol.h"
20 #include "scope.h"
21 #include "expression.h"
24 * Symbol type printout. The type system is by far the most
25 * complicated part of C - everything else is trivial.
27 const char *modifier_string(unsigned long mod)
29 static char buffer[100];
30 char *p = buffer;
31 const char *res,**ptr, *names[] = {
32 "auto", "register", "static", "extern",
33 "const", "volatile", "[signed]", "[unsigned]",
34 "[char]", "[short]", "[long]", "[long]",
35 "[typdef]", "[structof]", "[unionof]", "[enum]",
36 "[typeof]", "[attribute]",
37 NULL
39 ptr = names;
40 while ((res = *ptr++) != NULL) {
41 if (mod & 1) {
42 char c;
43 while ((c = *res++) != '\0')
44 *p++ = c;
45 *p++ = ' ';
47 mod >>= 1;
49 *p = 0;
50 return buffer;
53 void show_struct_member(struct symbol *sym, void *data, int flags)
55 if (flags & ITERATE_FIRST)
56 printf(" { ");
57 printf("%s:%d:%d at offset %ld", show_token(sym->token), sym->bit_size, sym->alignment, sym->offset);
58 if (flags & ITERATE_LAST)
59 printf(" } ");
60 else
61 printf(", ");
64 static void show_one_symbol(struct symbol *sym, void *sep, int flags)
66 show_symbol(sym);
67 if (!(flags & ITERATE_LAST))
68 printf("%s", (const char *)sep);
71 void show_symbol_list(struct symbol_list *list, const char *sep)
73 symbol_iterate(list, show_one_symbol, (void *)sep);
76 void show_type_list(struct symbol *sym)
78 while (sym) {
79 show_symbol(sym);
80 sym = sym->next;
84 void show_type(struct symbol *sym)
86 int i;
87 static struct ctype_name {
88 struct symbol *sym;
89 char *name;
90 } typenames[] = {
91 { & char_ctype, "char" },
92 { &uchar_ctype, "unsigned char" },
93 { & short_ctype, "short" },
94 { &ushort_ctype, "unsigned short" },
95 { & int_ctype, "int" },
96 { &uint_ctype, "unsigned int" },
97 { & long_ctype, "long" },
98 { &ulong_ctype, "unsigned long" },
99 { & llong_ctype, "long long" },
100 { &ullong_ctype, "unsigned long long" },
102 { &void_ctype, "void" },
103 { &bool_ctype, "bool" },
104 { &string_ctype, "string" },
106 { &float_ctype, "float" },
107 { &double_ctype, "double" },
108 { &ldouble_ctype,"long double" },
111 if (!sym)
112 return;
114 for (i = 0; i < sizeof(typenames)/sizeof(typenames[0]); i++) {
115 if (typenames[i].sym == sym) {
116 printf("%s", typenames[i].name);
117 return;
121 printf("%s", modifier_string(sym->ctype.modifiers));
122 switch (sym->type) {
123 case SYM_PTR:
124 printf("*");
125 show_type(sym->ctype.base_type);
126 return;
128 case SYM_FN:
129 printf("<fn>(");
130 show_type(sym->ctype.base_type);
131 printf(")");
132 return;
134 case SYM_ARRAY:
135 printf("<array>(");
136 show_type(sym->ctype.base_type);
137 printf(")");
138 return;
140 case SYM_STRUCT:
141 printf("struct %s", show_token(sym->token));
142 return;
144 case SYM_UNION:
145 printf("union %s", show_token(sym->token));
146 return;
148 case SYM_ENUM:
149 printf("enum %s", show_token(sym->token));
150 return;
152 case SYM_NODE: {
153 struct symbol *type = sym->ctype.base_type;
154 if (!type)
155 printf("notype");
156 else
157 show_type(type);
158 printf(": %s", show_token(sym->token));
159 return;
162 default:
163 printf("strange type %d '%s' of type ", sym->type, show_token(sym->token));
164 show_type(sym->ctype.base_type);
165 return;
169 void show_symbol(struct symbol *sym)
171 struct symbol *type;
173 if (sym->type != SYM_NODE)
174 *(int *)0 = 0;
175 show_type(sym);
176 type = sym->ctype.base_type;
177 if (!type)
178 return;
181 * Show actual implementation information
183 switch (type->type) {
184 case SYM_STRUCT:
185 symbol_iterate(type->symbol_list, show_struct_member, NULL);
186 return;
188 case SYM_UNION:
189 symbol_iterate(type->symbol_list, show_struct_member, NULL);
190 return;
192 case SYM_FN:
193 printf("(");
194 show_symbol_list(type->arguments, ", ");
195 if (type->variadic)
196 printf(", ...");
197 printf(")\n");
198 show_statement(type->stmt);
199 return;
201 case SYM_ARRAY:
202 printf("[%d]\n", type->array_size);
203 return;
205 default:
206 break;
211 * Print out a statement
213 void show_statement(struct statement *stmt)
215 if (!stmt)
216 return;
217 switch (stmt->type) {
218 case STMT_RETURN:
219 printf("\treturn ");
220 show_expression(stmt->expression);
221 break;
222 case STMT_COMPOUND:
223 printf("{\n");
224 if (stmt->syms) {
225 printf("\t");
226 show_symbol_list(stmt->syms, "\n\t");
227 printf("\n\n");
229 show_statement_list(stmt->stmts, ";\n");
230 printf("\n}\n\n");
231 break;
232 case STMT_EXPRESSION:
233 printf("\t");
234 show_expression(stmt->expression);
235 return;
236 case STMT_IF:
237 printf("\tif (");
238 show_expression(stmt->if_conditional);
239 printf(")\n");
240 show_statement(stmt->if_true);
241 if (stmt->if_false) {
242 printf("\nelse\n");
243 show_statement(stmt->if_false);
245 break;
246 case STMT_SWITCH:
247 printf("\tswitch (");
248 show_expression(stmt->switch_expression);
249 printf(")\n");
250 show_statement(stmt->switch_statement);
251 break;
253 case STMT_CASE:
254 if (!stmt->case_expression)
255 printf("default");
256 else {
257 printf("case ");
258 show_expression(stmt->case_expression);
259 if (stmt->case_to) {
260 printf(" ... ");
261 show_expression(stmt->case_to);
264 printf(":");
265 show_statement(stmt->case_statement);
266 break;
268 case STMT_BREAK:
269 printf("\tbreak");
270 break;
272 case STMT_ITERATOR: {
273 struct statement *pre_statement = stmt->iterator_pre_statement;
274 struct expression *pre_condition = stmt->iterator_pre_condition;
275 struct statement *statement = stmt->iterator_statement;
276 struct statement *post_statement = stmt->iterator_post_statement;
277 struct expression *post_condition = stmt->iterator_post_condition;
280 * THIS IS ONLY APPROXIMATE!
282 * Real iterators are more generic than
283 * any of for/while/do-while, and can't
284 * be printed out as C without goto's
286 if (post_statement || !post_condition) {
287 printf("\tfor ( ");
288 show_statement(pre_statement);
289 printf(" ; ");
290 show_expression(pre_condition);
291 printf(" ; ");
292 show_statement(post_statement);
293 printf(" )\n");
294 show_statement(statement);
295 } else if (pre_condition) {
296 if (pre_statement) {
297 show_statement(pre_statement);
298 printf(";\n");
300 printf("\twhile (");
301 show_expression(pre_condition);
302 printf(")\n");
303 show_statement(statement);
304 } else {
305 if (pre_statement) {
306 show_statement(pre_statement);
307 printf(";\n");
309 printf("\tdo\n");
310 show_statement(statement);
311 printf("\twhile (");
312 show_expression(post_condition);
313 printf(")");
315 break;
318 default:
319 printf("WTF");
323 static void show_one_statement(struct statement *stmt, void *sep, int flags)
325 show_statement(stmt);
326 if (!(flags & ITERATE_LAST))
327 printf("%s", (const char *)sep);
330 void show_statement_list(struct statement_list *stmt, const char *sep)
332 statement_iterate(stmt, show_one_statement, (void *)sep);
335 static void show_size(struct symbol *sym)
337 if (sym)
338 printf("%d:%d", sym->bit_size, sym->alignment);
342 * Print out an expression
344 void show_expression(struct expression *expr)
346 if (!expr)
347 return;
349 printf("< (");
350 show_size(expr->ctype);
351 show_type(expr->ctype);
352 printf(") ");
353 switch (expr->type) {
354 case EXPR_BINOP:
355 show_expression(expr->left);
356 printf(" %s ", show_special(expr->op));
357 show_expression(expr->right);
358 break;
359 case EXPR_PREOP:
360 printf("%s<", show_special(expr->op));
361 show_expression(expr->unop);
362 printf(">");
363 break;
364 case EXPR_POSTOP:
365 show_expression(expr->unop);
366 printf(" %s ", show_special(expr->op));
367 break;
368 case EXPR_CONSTANT:
369 printf("%s", show_token(expr->token));
370 break;
371 case EXPR_SYMBOL:
372 if (!expr->symbol) {
373 warn(expr->token, "undefined symbol '%s'", show_token(expr->token));
374 printf("<nosymbol>");
375 break;
377 printf("<%s:", show_token(expr->symbol->token));
378 show_type(expr->symbol->ctype.base_type);
379 printf(">");
380 break;
381 case EXPR_DEREF:
382 show_expression(expr->deref);
383 printf("%s", show_special(expr->op));
384 printf("%s", show_token(expr->member));
385 break;
386 case EXPR_CAST:
387 printf("<cast>(");
388 show_type(expr->cast_type);
389 printf(")");
390 show_expression(expr->cast_expression);
391 break;
392 case EXPR_VALUE:
393 printf("(%lld)", expr->value);
394 break;
395 case EXPR_SIZEOF:
396 printf("sizeof(");
397 if (expr->cast_type)
398 show_type(expr->cast_type);
399 else
400 show_expression(expr->cast_expression);
401 printf(")");
402 break;
404 default:
405 printf("WTF");
407 printf(" >");