Commit | Line | Data |
---|---|---|
3cd4b0f8 MW |
1 | #include "cparse.h" |
2 | #include <ctype.h> | |
3 | ||
4 | #define INDENT 2 | |
5 | #define CASEIND 1 | |
6 | #define MARGIN 72 | |
7 | ||
8 | struct dump_state { | |
9 | FILE *fp; | |
10 | int last; | |
11 | int y; | |
12 | const char *path; | |
13 | int line; | |
14 | int locations; | |
15 | }; | |
16 | ||
17 | static int dump_string(dump_state *dump, | |
18 | const char *s, | |
19 | int l, | |
20 | int q); | |
21 | ||
22 | dump_state *dump_new(FILE *fp) { | |
23 | dump_state *dump = xmalloc(sizeof *dump); | |
24 | dump->fp = fp; | |
25 | dump->locations = 1; | |
26 | return dump; | |
27 | } | |
28 | ||
29 | void dump_locations(struct dump_state *dump, int flag) { | |
30 | dump->locations = flag; | |
31 | } | |
32 | ||
33 | static int location(dump_state *dump, const struct location *l, int ind) { | |
34 | int change_path = 0, change_line = 0; | |
35 | ||
36 | if(!dump->path | |
37 | || strcmp(dump->path, l->path)) | |
38 | change_path = 1; | |
39 | else if(dump->line != l->line) | |
40 | change_line = 1; | |
41 | else if(dump->y > MARGIN) | |
42 | change_line = 1; | |
43 | else | |
44 | return 0; | |
45 | if(change_line && l->line > dump->line && l->line - dump->line < 5) { | |
46 | while(dump->line < l->line) { | |
47 | if(fputc('\n', dump->fp) < 0) return -1; | |
48 | ++dump->line; | |
49 | } | |
50 | } else { | |
51 | if(dump->y) | |
52 | if(fputc('\n', dump->fp) < 0) return -1; | |
53 | if(dump->locations) { | |
54 | if(fprintf(dump->fp, "# %d", l->line) < 0) return -1; | |
55 | if(change_path) { | |
56 | if(fputc(' ', dump->fp) < 0) return -1; | |
57 | if(dump_string(dump, l->path, 0, '"')) return -1; | |
58 | } | |
59 | if(fputc('\n', dump->fp) < 0) return -1; | |
60 | } | |
61 | dump->path = l->path; | |
62 | dump->line = l->line; | |
63 | } | |
64 | dump->y = 0; | |
65 | if(fprintf(dump->fp, "%*s", ind, "") < 0) return -1; | |
66 | dump->last = ' '; | |
67 | return 0; | |
68 | } | |
69 | ||
70 | static int word(dump_state *dump, const char *w) { | |
71 | int force_space_before = 1; | |
72 | switch(dump->last) { | |
73 | case '.': | |
74 | case MEMBER: | |
75 | case INCR: | |
76 | case DECR: | |
77 | case '(': | |
78 | case '[': | |
79 | case ' ': | |
80 | case 0: | |
81 | force_space_before = 0; | |
82 | break; | |
83 | } | |
84 | if(force_space_before) { | |
85 | if(fputc(' ', dump->fp) < 0) return -1; | |
86 | ++dump->y; | |
87 | } | |
88 | if(fputs(w, dump->fp) < 0) return -1; | |
89 | dump->y += strlen(w); | |
90 | dump->last = ID; | |
91 | return 0; | |
92 | } | |
93 | ||
94 | static int punc(dump_state *dump, int c) { | |
95 | const char *s = 0; | |
96 | int force_space_before = 1; | |
97 | ||
98 | switch(c) { | |
99 | case SIZEOF: | |
100 | s = "sizeof"; | |
101 | break; | |
102 | case MEMBER: | |
103 | force_space_before = (dump->last == '-'); | |
104 | s = "->"; | |
105 | break; | |
106 | case INCR: | |
107 | force_space_before = (dump->last == '+'); | |
108 | s = "++"; | |
109 | break; | |
110 | case DECR: | |
111 | force_space_before = (dump->last == '-'); | |
112 | s = "--"; | |
113 | break; | |
114 | case SL: | |
115 | s = "<<"; | |
116 | break; | |
117 | case SR: | |
118 | s = ">>"; | |
119 | break; | |
120 | case LE: | |
121 | s = "<="; | |
122 | break; | |
123 | case GE: | |
124 | s = ">="; | |
125 | break; | |
126 | case EQ: | |
127 | s = "=="; | |
128 | break; | |
129 | case NE: | |
130 | s = "!="; | |
131 | break; | |
132 | case AND: | |
133 | s = "&&"; | |
134 | break; | |
135 | case OR: | |
136 | s = "||"; | |
137 | break; | |
138 | case VARARG: | |
139 | s = "..."; | |
140 | break; | |
141 | case MULEQ: | |
142 | s = "*="; | |
143 | break; | |
144 | case DIVEQ: | |
145 | s = "/="; | |
146 | break; | |
147 | case MODEQ: | |
148 | s = "%="; | |
149 | break; | |
150 | case ADDEQ: | |
151 | s = "+="; | |
152 | break; | |
153 | case SUBEQ: | |
154 | s = "-="; | |
155 | break; | |
156 | case SLEQ: | |
157 | s = "<<="; | |
158 | break; | |
159 | case SREQ: | |
160 | s = ">>="; | |
161 | break; | |
162 | case ANDEQ: | |
163 | s = "&="; | |
164 | break; | |
165 | case XOREQ: | |
166 | s = "^="; | |
167 | break; | |
168 | case OREQ: | |
169 | s = "|="; | |
170 | break; | |
171 | case '(': | |
172 | if(dump->last == ',') break; | |
173 | case ')': | |
174 | case '[': | |
175 | case ']': | |
176 | case ',': | |
177 | case ';': | |
178 | case ':': | |
179 | force_space_before = 0; | |
180 | break; | |
181 | } | |
182 | if(force_space_before && dump->last && dump->last != ' ') { | |
183 | if(fputc(' ', dump->fp) < 0) return -1; | |
184 | ++dump->y; | |
185 | } | |
186 | if(s) { | |
187 | if(fputs(s, dump->fp) < 0) return -1; | |
188 | dump->y += strlen(s); | |
189 | } else { | |
190 | if(fputc(c, dump->fp) < 0) return -1; | |
191 | ++dump->y; | |
192 | } | |
193 | switch(c) { | |
194 | case '(': | |
195 | case '[': | |
196 | case ']': | |
197 | dump->last = 0; | |
198 | break; | |
199 | default: | |
200 | dump->last = c; | |
201 | break; | |
202 | } | |
203 | return 0; | |
204 | } | |
205 | ||
206 | struct table { | |
207 | unsigned bit; | |
208 | const char *kw; | |
209 | }; | |
210 | ||
211 | struct masktable { | |
212 | unsigned mask, value; | |
213 | const char *kw; | |
214 | }; | |
215 | ||
216 | static const struct masktable type_specifier_table[] = { | |
217 | { TS__BASIC, TS_VOID, "void" }, | |
218 | { TS__BASIC, TS_CHAR, "char" }, | |
219 | { TS__BASIC, TS_INT, "int" }, | |
220 | { TS__BASIC, TS_FLOAT, "float" }, | |
221 | { TS__BASIC, TS_DOUBLE, "double" }, | |
222 | { TS__BASIC, TS_BOOL, "_Bool" }, | |
223 | { TS__BASIC, TS_STRUCT, "struct" }, | |
224 | { TS__BASIC, TS_UNION, "union" }, | |
225 | { TS__BASIC, TS_ENUM, "enum" }, | |
226 | { TS__BASIC, TS_GCC_VA_LIST, "__builtin_va_list" }, | |
227 | ||
228 | { TS__CI, TS_COMPLEX, "_Complex" }, | |
229 | { TS__CI, TS_IMAGINARY, "_Imaginary" }, | |
230 | ||
231 | { TS__LENGTH, TS_SHORT, "short" }, | |
232 | { TS__LENGTH, TS_LONG, "long" }, | |
233 | { TS__LENGTH, TS_LONGLONG , "long long" }, | |
234 | ||
235 | { TS__SIGN, TS_SIGNED, "signed" }, | |
236 | { TS__SIGN, TS_UNSIGNED, "unsigned" }, | |
237 | ||
238 | { 0, 0, 0 } | |
239 | }; | |
240 | ||
241 | static const struct table storage_class_specifier_table[] = { | |
242 | { SCS_TYPEDEF, "typedef" }, | |
243 | { SCS_EXTERN, "extern" }, | |
244 | { SCS_STATIC, "static" }, | |
245 | { SCS_AUTO, "auto" }, | |
246 | { SCS_REGISTER, "register" }, | |
247 | { 0, 0 } | |
248 | }; | |
249 | ||
250 | static const struct table type_qualifier_table[] = { | |
251 | { TQ_CONST, "const" }, | |
252 | { TQ_VOLATILE, "volatile" }, | |
253 | { TQ_RESTRICT, RESTRICT_KW }, | |
254 | { 0, 0 } | |
255 | }; | |
256 | ||
257 | static const struct table function_specifier_table[] = { | |
258 | { FS_INLINE, "inline" }, | |
259 | { 0, 0 } | |
260 | }; | |
261 | ||
262 | static int dump_on_bit(dump_state *dump, | |
263 | unsigned u, | |
264 | const struct table *t) { | |
265 | int n; | |
266 | for(n = 0; t[n].bit; ++n) | |
267 | if(t[n].bit & u) | |
268 | if(word(dump, t[n].kw)) return -1; | |
269 | return 0; | |
270 | } | |
271 | ||
272 | int dump_declaration_specifiers(dump_state *dump, | |
273 | const struct declaration_specifiers *ds, | |
274 | int ind) { | |
275 | struct declaration *d; | |
276 | struct enumerator *e; | |
277 | int offset; | |
278 | size_t n; | |
279 | ||
280 | if(dump_on_bit(dump, ds->storage_class_specifiers, | |
281 | storage_class_specifier_table)) return -1; | |
282 | if(dump_on_bit(dump, ds->function_specifiers, function_specifier_table)) | |
283 | return -1; | |
284 | if(dump_on_bit(dump, ds->type_qualifiers, type_qualifier_table)) return -1; | |
285 | for(n = 0; type_specifier_table[n].mask; ++n) | |
286 | if((ds->type_specifiers & type_specifier_table[n].mask) | |
287 | == type_specifier_table[n].value) | |
288 | if(word(dump, type_specifier_table[n].kw)) return -1; | |
289 | if(ds->name) | |
290 | if(word(dump, ds->name)) return -1; | |
291 | if(ds->type_specifiers & TS_DEFINITION) { | |
292 | if(punc(dump, '{')) return -1; | |
293 | switch(ds->type_specifiers & TS__BASIC) { | |
294 | case TS_STRUCT: | |
295 | case TS_UNION: | |
296 | for(d = ds->structure; d; d = d->next) | |
297 | if(dump_declaration(dump, d, ind + INDENT)) return -1; | |
298 | break; | |
299 | case TS_ENUM: | |
300 | offset = dump->y; | |
301 | if(ds->enumerators) | |
302 | if(location(dump, &ds->enumerators->where, ind + INDENT)) return -1; | |
303 | for(e = ds->enumerators; e; e = e->next) { | |
304 | if(word(dump, e->name)) return -1; | |
305 | if(e->value) { | |
306 | if(punc(dump, '=')) return -1; | |
307 | if(dump_expression(dump, e->value, ind + 2 * INDENT)) return -1; | |
308 | } | |
309 | if(e->next) { | |
310 | if(punc(dump, ',')) return -1; | |
311 | if(location(dump, &e->next->where, ind + INDENT)) return -1; | |
312 | } | |
313 | } | |
314 | break; | |
315 | } | |
316 | if(punc(dump, '}')) return -1; | |
317 | } | |
318 | return 0; | |
319 | } | |
320 | ||
321 | static int dump_pointer_declarator(dump_state *dump, | |
322 | const struct declarator *d, | |
323 | const struct declarator_type *t, | |
324 | int ind) { | |
325 | if(t && t->type == dt_pointer) { | |
326 | if(dump_pointer_declarator(dump, d, t->next, ind)) return -1; | |
327 | if(punc(dump, '*')) return -1; | |
328 | if(dump_on_bit(dump, t->type_qualifiers, type_qualifier_table)) | |
329 | return -1; | |
330 | } | |
331 | return 0; | |
332 | } | |
333 | ||
334 | static int dump_identifier_list(dump_state *dump, | |
335 | const struct identifier_list *i) { | |
336 | while(i) { | |
337 | if(word(dump, i->id)) return -1; | |
338 | if(i->next) | |
339 | if(punc(dump, ',')) return -1; | |
340 | i = i->next; | |
341 | } | |
342 | return 0; | |
343 | } | |
344 | ||
345 | static int dump_declaration_raw(dump_state *dump, | |
346 | const struct declaration *d, | |
347 | int ind) { | |
348 | struct declarator *dc; | |
349 | ||
350 | if(dump_declaration_specifiers(dump, d->declaration_specifiers, ind)) | |
351 | return -1; | |
352 | for(dc = d->declarator_list; dc; dc = dc->next) { | |
353 | /*if((dc->name || dc->type) && space(dump)) return -1;*/ | |
354 | if(dump_declarator(dump, dc, ind + INDENT)) | |
355 | return -1; | |
356 | if(dc->next) | |
357 | if(punc(dump, ',')) return -1; | |
358 | } | |
359 | return 0; | |
360 | } | |
361 | ||
362 | static int dump_parameter_list(dump_state *dump, | |
363 | const struct declaration *p, | |
364 | int ind) { | |
365 | if(location(dump, &p->where, ind)) return -1; | |
366 | while(p) { | |
367 | if(dump_declaration_raw(dump, p, ind)) return -1; | |
368 | if(p->next) { | |
369 | if(punc(dump, ',')) return -1; | |
370 | if(location(dump, &p->next->where, ind + INDENT)) return -1; | |
371 | } | |
372 | p = p->next; | |
373 | } | |
374 | return 0; | |
375 | } | |
376 | ||
377 | static int dump_declarator_type(dump_state *dump, | |
378 | const struct declarator *d, | |
379 | const struct declarator_type *t, | |
380 | int ind) { | |
381 | const struct declarator_type *u; | |
382 | int offset; | |
383 | ||
384 | /* C declarator syntax really bites */ | |
385 | if(t) { | |
386 | switch(t->type) { | |
387 | case dt_pointer: | |
388 | for(u = t; u && u->type == dt_pointer; u = u->next) | |
389 | ; | |
390 | if(u) { | |
391 | if(punc(dump, '(')) return -1; | |
392 | if(dump_pointer_declarator(dump, d, t, ind + INDENT)) return -1; | |
393 | if(dump_declarator_type(dump, d, 0, ind + INDENT)) return -1; | |
394 | if(punc(dump, ')')) return -1; | |
395 | if(dump_declarator_type(dump, 0, u, ind)) return -1; | |
396 | } else { | |
397 | if(dump_pointer_declarator(dump, d, t, ind)) return -1; | |
398 | if(dump_declarator_type(dump, d, u, ind)) return -1; | |
399 | } | |
400 | break; | |
401 | case dt_array: | |
402 | if(dump_declarator_type(dump, d, t->next, ind)) return -1; | |
403 | if(punc(dump, '[')) return -1; | |
404 | if(dump_on_bit(dump, t->storage_class_specifiers, | |
405 | storage_class_specifier_table)) return -1; | |
406 | if(dump_on_bit(dump, t->type_qualifiers, type_qualifier_table)) | |
407 | return -1; | |
408 | if(t->u.array.flags & AF_STAR) { | |
409 | if(punc(dump, '*')) return -1; | |
410 | } else if(t->u.array.size) | |
411 | if(dump_expression(dump, t->u.array.size, ind + INDENT)) return -1; | |
412 | if(punc(dump, ']')) return -1; | |
413 | break; | |
414 | case dt_old_function: | |
415 | if(dump_declarator_type(dump, d, t->next, ind)) return -1; | |
416 | if(punc(dump, '(')) return -1; | |
417 | if(dump_identifier_list(dump, t->u.old_function.args)) | |
418 | return -1; | |
419 | if(punc(dump, ')')) return -1; | |
420 | break; | |
421 | case dt_function: | |
422 | if(dump_declarator_type(dump, d, t->next, ind)) return -1; | |
423 | if(punc(dump, '(')) return -1; | |
424 | offset = dump->y; | |
425 | if(dump_parameter_list(dump, t->u.function.args, ind + INDENT)) return -1; | |
426 | if(t->u.function.variadic) { | |
427 | if(punc(dump, ',')) return -1; | |
428 | if(punc(dump, VARARG)) return -1; | |
429 | } | |
430 | if(punc(dump, ')')) return -1; | |
431 | break; | |
432 | } | |
433 | } else | |
434 | if(d && d->name && word(dump, d->name)) return -1; | |
435 | return 0; | |
436 | } | |
437 | ||
438 | int dump_declarator(dump_state *dump, | |
439 | const struct declarator *d, | |
440 | int ind) { | |
441 | if(location(dump, &d->where, ind)) return -1; | |
442 | if(dump_declarator_type(dump, d, d->declarator_type, ind)) return -1; | |
443 | if(d->bits) { | |
444 | if(punc(dump, ':')) return -1; | |
445 | if(dump_expression(dump, d->bits, ind + INDENT)) return -1; | |
446 | } | |
447 | if(d->initializer) { | |
448 | if(punc(dump, '=')) return -1; | |
449 | if(dump_initializer(dump, d->initializer, ind + INDENT)) return -1; | |
450 | } | |
451 | return 0; | |
452 | } | |
453 | ||
454 | int dump_declaration(dump_state *dump, | |
455 | const struct declaration *d, | |
456 | int ind) { | |
457 | if(location(dump, &d->where, ind)) return -1; | |
458 | if(dump_declaration_raw(dump, d, ind)) return -1; | |
459 | if(punc(dump, ';')) return -1; | |
460 | return 0; | |
461 | } | |
462 | ||
463 | int dump_translation_unit(dump_state *dump, | |
464 | const struct external_declaration *ed, | |
465 | int ind) { | |
466 | for(; ed; ed = ed->next) | |
467 | switch(ed->type) { | |
468 | case ed_declaration: | |
469 | if(dump_declaration(dump, ed->u.declaration, ind)) return -1; | |
470 | break; | |
471 | case ed_function_definition: | |
472 | if(dump_function_definition(dump, ed->u.function_definition, ind)) | |
473 | return -1; | |
474 | break; | |
475 | } | |
476 | if(fputc('\n', dump->fp) < 0) return -1; | |
477 | dump->y = 0; | |
478 | ++dump->line; | |
479 | return 0; | |
480 | } | |
481 | ||
482 | static int dump_string(dump_state *dump, | |
483 | const char *s, | |
484 | int l, | |
485 | int q) { | |
486 | if(dump->last) | |
487 | if(fputc(' ', dump->fp) < 0) return -1; | |
488 | if(l) | |
489 | if(fputc(l, dump->fp) < 0) return -1; | |
490 | if(fputc(q, dump->fp) < 0) return -1; | |
491 | if(fputs(s, dump->fp) < 0) return -1; | |
492 | if(fputc(q, dump->fp) < 0) return -1; | |
493 | ++dump->y; | |
494 | dump->last = '"'; | |
495 | return 0; | |
496 | } | |
497 | ||
498 | static int dump_expression_list(dump_state *dump, | |
499 | const struct expression_list *l, | |
500 | int ind) { | |
501 | while(l) { | |
502 | if(dump_expression(dump, l->e, ind)) return -1; | |
503 | if(l->next) | |
504 | if(punc(dump, ',')) return -1; | |
505 | l = l->next; | |
506 | } | |
507 | return 0; | |
508 | } | |
509 | ||
510 | static int dump_initializer_list(dump_state *dump, | |
511 | const struct initializer *i, | |
512 | int ind) { | |
513 | int offset; | |
514 | ||
515 | if(punc(dump, '{')) return -1; | |
516 | offset = dump->y; | |
517 | while(i) { | |
518 | if(dump_initializer(dump, i, ind + INDENT)) return -1; | |
519 | if(i->next) | |
520 | if(punc(dump, ',')) return -1; | |
521 | i = i->next; | |
522 | } | |
523 | return punc(dump, '}'); | |
524 | } | |
525 | ||
526 | int dump_initializer(dump_state *dump, | |
527 | const struct initializer *i, | |
528 | int ind) { | |
529 | struct designator *d; | |
530 | ||
531 | if(i->designator) { | |
532 | for(d = i->designator; d; d = d->next) { | |
533 | if(location(dump, &d->where, ind)) return -1; | |
534 | switch(d->type) { | |
535 | case des_expr: | |
536 | if(punc(dump, '[')) return -1; | |
537 | if(dump_expression(dump, d->u.expr, ind + INDENT)) return -1; | |
538 | if(punc(dump, ']')) return -1; | |
539 | break; | |
540 | case des_field: | |
541 | if(i->syntax == des_c99 || d != i->designator) | |
542 | if(punc(dump, '.')) return -1; | |
543 | if(word(dump, d->u.name)) return -1; | |
544 | break; | |
545 | } | |
546 | } | |
547 | switch(i->syntax) { | |
548 | case des_c99: | |
549 | if(punc(dump, '=')) return -1; | |
550 | break; | |
551 | case des_gcc_colon: | |
552 | if(punc(dump, ':')) return -1; | |
553 | break; | |
554 | case des_gcc_raw: | |
555 | break; | |
556 | } | |
557 | } | |
558 | switch(i->type) { | |
559 | case in_expr: return dump_expression(dump, i->u.expr, ind); | |
560 | case in_list: return dump_initializer_list(dump, i->u.list, ind); | |
561 | } | |
562 | abort(); | |
563 | } | |
564 | ||
565 | int dump_expression(dump_state *dump, | |
566 | const struct expression *e, | |
567 | int ind) { | |
568 | switch(e->type) { | |
569 | case ex_paren: | |
570 | if(location(dump, &e->where, ind)) return -1; | |
571 | if(punc(dump, '(')) return -1; | |
572 | if(dump_expression(dump, e->u.unary, ind + INDENT)) return -1; | |
573 | if(punc(dump, ')')) return -1; | |
574 | break; | |
575 | case ex_prefix: | |
576 | if(location(dump, &e->where, ind)) return -1; | |
577 | if(punc(dump, e->operator)) return -1; | |
578 | if(dump_expression(dump, e->u.unary, ind + INDENT)) return -1; | |
579 | break; | |
580 | case ex_binary: | |
581 | if(e->operator != '[') { | |
582 | if(dump_expression(dump, e->u.binary.l, ind)) return -1; | |
583 | if(location(dump, &e->where, ind)) return -1; | |
584 | if(punc(dump, e->operator)) return -1; | |
585 | if(dump_expression(dump, e->u.binary.r, ind + INDENT)) return -1; | |
586 | } else { | |
587 | if(dump_expression(dump, e->u.binary.l, ind)) return -1; | |
588 | if(location(dump, &e->where, ind + INDENT)) return -1; | |
589 | if(punc(dump, '[')) return -1; | |
590 | if(dump_expression(dump, e->u.binary.r, ind + INDENT)) return -1; | |
591 | if(punc(dump, ']')) return -1; | |
592 | } | |
593 | break; | |
594 | case ex_postfix: | |
595 | if(dump_expression(dump, e->u.unary, ind)) return -1; | |
596 | if(location(dump, &e->where, ind)) return -1; | |
597 | if(punc(dump, e->operator)) return -1; | |
598 | break; | |
599 | case ex_id: | |
600 | if(location(dump, &e->where, ind)) return -1; | |
601 | if(word(dump, e->u.name)) return -1; | |
602 | break; | |
603 | case ex_number: | |
604 | if(location(dump, &e->where, ind)) return -1; | |
605 | if(word(dump, e->u.constant)) return -1; | |
606 | break; | |
607 | case ex_char: | |
608 | if(location(dump, &e->where, ind)) return -1; | |
609 | if(dump_string(dump, e->u.constant, 0, '\'')) | |
610 | return -1; | |
611 | break; | |
612 | case ex_string: | |
613 | if(location(dump, &e->where, ind)) return -1; | |
614 | if(dump_string(dump, e->u.constant, 0, '"')) | |
615 | return -1; | |
616 | break; | |
617 | case ex_wchar: | |
618 | if(location(dump, &e->where, ind)) return -1; | |
619 | if(dump_string(dump, e->u.constant, 'L', '\'')) | |
620 | return -1; | |
621 | break; | |
622 | case ex_wstring: | |
623 | if(location(dump, &e->where, ind)) return -1; | |
624 | if(dump_string(dump, e->u.constant, 'L', '"')) | |
625 | return -1; | |
626 | break; | |
627 | case ex_fncall: | |
628 | if(dump_expression(dump, e->u.fncall.fn, ind)) return -1; | |
629 | if(location(dump, &e->where, ind)) return -1; | |
630 | if(punc(dump, '(')) return -1; | |
631 | if(dump_expression_list(dump, e->u.fncall.args, ind + INDENT)) | |
632 | return -1; | |
633 | if(punc(dump, ')')) return -1; | |
634 | break; | |
635 | case ex_gcc_va_arg: | |
636 | if(word(dump, "__builtin_va_arg")) return -1; | |
637 | if(punc(dump, '(')) return -1; | |
638 | if(dump_expression(dump, e->u.gcc_va_arg.arg, ind + INDENT)) | |
639 | return -1; | |
640 | if(punc(dump, ',')) return -1; | |
641 | if(dump_declaration_raw(dump, e->u.gcc_va_arg.type, ind + INDENT)) | |
642 | return -1; | |
643 | if(punc(dump, ')')) return -1; | |
644 | break; | |
645 | case ex_gcc_expect: | |
646 | if(word(dump, "__builtin_expect")) return -1; | |
647 | if(punc(dump, '(')) return -1; | |
648 | if(dump_expression(dump, e->u.binary.l, ind + INDENT)) | |
649 | return -1; | |
650 | if(punc(dump, ',')) return -1; | |
651 | if(dump_expression(dump, e->u.binary.r, ind + INDENT)) | |
652 | return -1; | |
653 | if(punc(dump, ')')) return -1; | |
654 | break; | |
655 | case ex_compound_literal: | |
656 | if(location(dump, &e->where, ind)) return -1; | |
657 | if(punc(dump, '(')) return -1; | |
658 | if(location(dump, &e->u.compound_literal.type->where, ind + INDENT)) | |
659 | return -1; | |
660 | if(dump_declaration_raw(dump, e->u.compound_literal.type, ind + INDENT)) | |
661 | return -1; | |
662 | if(punc(dump, ')')) return -1; | |
663 | if(dump_initializer_list(dump, e->u.compound_literal.value, | |
664 | ind + 2 * INDENT)) | |
665 | return -1; | |
666 | break; | |
667 | case ex_sizeof_type: | |
668 | if(location(dump, &e->where, ind)) return -1; | |
669 | if(word(dump, "sizeof")) return -1; | |
670 | if(punc(dump, '(')) return -1; | |
671 | if(location(dump, &e->u.type->where, ind + INDENT)) return -1; | |
672 | if(dump_declaration_raw(dump, e->u.type, ind + 2 * INDENT)) return -1; | |
673 | if(punc(dump, ')')) return -1; | |
674 | break; | |
675 | case ex_cast: | |
676 | if(location(dump, &e->where, ind)) return -1; | |
677 | if(punc(dump, '(')) return -1; | |
678 | if(location(dump, &e->valuetype->where, ind + INDENT)) return -1; | |
679 | if(dump_declaration_specifiers(dump, e->valuetype->declaration_specifiers, | |
680 | ind)) | |
681 | return -1; | |
682 | if(dump_declarator(dump, e->valuetype, ind + INDENT)) return -1; | |
683 | if(punc(dump, ')')) return -1; | |
684 | if(dump_expression(dump, e->u.cast, ind + 2 * INDENT)) return -1; | |
685 | break; | |
686 | case ex_implicit_conversion: | |
687 | if(dump_expression(dump, e->u.cast, ind)) return -1; | |
688 | break; | |
689 | } | |
690 | return 0; | |
691 | } | |
692 | ||
693 | int dump_function_definition(dump_state *dump, | |
694 | const struct function_definition *fd, | |
695 | int ind) { | |
696 | const struct declaration *d; | |
697 | ||
698 | if(location(dump, &fd->declaration->where, ind)) return -1; | |
699 | if(dump_declaration_raw(dump, fd->declaration, ind)) return -1; | |
700 | for(d = fd->args; d; d = d->next) | |
701 | if(dump_declaration(dump, d, ind + INDENT)) return -1; | |
702 | if(dump_statement(dump, fd->body, ind)) return -1; | |
703 | return 0; | |
704 | } | |
705 | ||
706 | int dump_statement(dump_state *dump, | |
707 | const struct statement *s, | |
708 | int ind) { | |
709 | const struct statement *ss; | |
710 | ||
711 | switch(s->type) { | |
712 | case st_label: | |
713 | if(location(dump, &s->where, 0)) return -1; | |
714 | break; | |
715 | case st_case: | |
716 | case st_default: | |
717 | if(location(dump, &s->where, ind - CASEIND)) return -1; | |
718 | break; | |
719 | default: | |
720 | if(location(dump, &s->where, ind)) return -1; | |
721 | break; | |
722 | } | |
723 | switch(s->type) { | |
724 | case st_label: | |
725 | if(word(dump, s->u.label.label)) return -1; | |
726 | if(punc(dump, ':')) return -1; | |
727 | if(dump_statement(dump, s->u.label.body, ind)) return -1; | |
728 | break; | |
729 | case st_case: | |
730 | if(word(dump, "case")) return -1; | |
731 | if(dump_expression(dump, s->u.case_.value, ind + INDENT)) return -1; | |
732 | if(punc(dump, ':')) return -1; | |
733 | if(dump_statement(dump, s->u.case_.body, ind)) return -1; | |
734 | break; | |
735 | case st_default: | |
736 | if(word(dump, "default")) return -1; | |
737 | if(punc(dump, ':')) return -1; | |
738 | if(dump_statement(dump, s->u.default_, ind)) return -1; | |
739 | break; | |
740 | case st_declaration: | |
741 | if(dump_declaration(dump, s->u.declaration, ind + INDENT)) return -1; | |
742 | break; | |
743 | case st_expression: | |
744 | if(s->u.expression && dump_expression(dump, s->u.expression, ind + INDENT)) | |
745 | return -1; | |
746 | if(punc(dump, ';')) return -1; | |
747 | break; | |
748 | case st_if: | |
749 | if(word(dump, "if")) return -1; | |
750 | if(punc(dump, '(')) return -1; | |
751 | if(dump_expression(dump, s->u.if_.cond, ind + INDENT)) | |
752 | return -1; | |
753 | if(punc(dump, ')')) return -1; | |
754 | if(dump_statement(dump, s->u.if_.true, ind + INDENT)) return -1; | |
755 | if(s->u.if_.false) { | |
756 | if(word(dump, "else")) return -1; | |
757 | if(dump_statement(dump, s->u.if_.false, ind + INDENT)) return -1; | |
758 | } | |
759 | break; | |
760 | case st_switch: | |
761 | if(word(dump, "switch")) return -1; | |
762 | if(punc(dump, '(')) return -1; | |
763 | if(dump_expression(dump, s->u.switch_.cond, ind + INDENT)) | |
764 | return -1; | |
765 | if(punc(dump, ')')) return -1; | |
766 | if(dump_statement(dump, s->u.switch_.body, ind + INDENT)) return -1; | |
767 | break; | |
768 | case st_while: | |
769 | if(word(dump, "while")) return -1; | |
770 | if(punc(dump, '(')) return -1; | |
771 | if(dump_expression(dump, s->u.while_.cond, ind + INDENT)) | |
772 | return -1; | |
773 | if(punc(dump, ')')) return -1; | |
774 | if(dump_statement(dump, s->u.while_.body, ind + INDENT)) return -1; | |
775 | break; | |
776 | case st_do: | |
777 | if(word(dump, "do")) return -1; | |
778 | if(dump_statement(dump, s->u.while_.body, ind + INDENT)) return -1; | |
779 | if(word(dump, "while")) return -1; | |
780 | if(punc(dump, '(')) return -1; | |
781 | if(dump_expression(dump, s->u.while_.cond, ind + INDENT)) | |
782 | return -1; | |
783 | if(punc(dump, ')')) return -1; | |
784 | if(punc(dump, ';')) return -1; | |
785 | break; | |
786 | case st_for: | |
787 | if(word(dump, "for")) return -1; | |
788 | if(punc(dump, '(')) return -1; | |
789 | if(s->u.for_.init && dump_expression(dump, s->u.for_.init, ind + INDENT)) | |
790 | return -1; | |
791 | if(punc(dump, ';')) return -1; | |
792 | if(s->u.for_.cond && dump_expression(dump, s->u.for_.cond, ind + INDENT)) | |
793 | return -1; | |
794 | if(punc(dump, ';')) return -1; | |
795 | if(s->u.for_.iter && dump_expression(dump, s->u.for_.iter, ind + INDENT)) | |
796 | return -1; | |
797 | if(punc(dump, ')')) return -1; | |
798 | if(dump_statement(dump, s->u.for_.body, ind + INDENT)) return -1; | |
799 | break; | |
800 | case st_for_declaration: | |
801 | if(word(dump, "for")) return -1; | |
802 | if(punc(dump, '(')) return -1; | |
803 | if(s->u.for_declaration.init | |
804 | && dump_declaration_raw(dump, s->u.for_declaration.init, ind + INDENT)) | |
805 | return -1; | |
806 | if(punc(dump, ';')) return -1; | |
807 | if(s->u.for_declaration.cond | |
808 | && dump_expression(dump, s->u.for_declaration.cond, ind + INDENT)) | |
809 | return -1; | |
810 | if(punc(dump, ';')) return -1; | |
811 | if(s->u.for_declaration.iter | |
812 | && dump_expression(dump, s->u.for_declaration.iter, ind + INDENT)) | |
813 | return -1; | |
814 | if(punc(dump, ')')) return -1; | |
815 | if(dump_statement(dump, s->u.for_declaration.body, ind + INDENT)) return -1; | |
816 | break; | |
817 | case st_goto: | |
818 | if(word(dump, "goto")) return -1; | |
819 | if(word(dump, s->u.goto_)) return -1; | |
820 | if(punc(dump, ';')) return -1; | |
821 | break; | |
822 | case st_continue: | |
823 | if(word(dump, "continue")) return -1; | |
824 | if(punc(dump, ';')) return -1; | |
825 | break; | |
826 | case st_break: | |
827 | if(word(dump, "break")) return -1; | |
828 | if(punc(dump, ';')) return -1; | |
829 | break; | |
830 | case st_return: | |
831 | if(word(dump, "return")) return -1; | |
832 | if(s->u.expression && dump_expression(dump, s->u.expression, ind + INDENT)) | |
833 | return -1; | |
834 | if(punc(dump, ';')) return -1; | |
835 | break; | |
836 | case st_compound: | |
837 | if(ind == 0) ind = INDENT; /* top level */ | |
838 | if(punc(dump, '{')) return -1; | |
839 | for(ss = s->u.compound.body; ss; ss = ss->next) | |
840 | if(dump_statement(dump, ss, ind)) return -1; | |
841 | if(location(dump, &s->u.compound.endwhere, ind - INDENT)) return -1; | |
842 | if(punc(dump, '}')) return -1; | |
843 | break; | |
844 | } | |
845 | return 0; | |
846 | } | |
847 | ||
848 | /* | |
849 | Local Variablesf: | |
850 | c-basic-offset:2 | |
851 | comment-column:40 | |
852 | End: | |
853 | */ |