chiark / gitweb /
Import upstream sources.
[cparse] / dump.c
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 */