OSDN Git Service

96a2548b5712ffc6224fdfeceb729d223a765e27
[pf3gnuchains/gcc-fork.git] / gcc / c-dump.c
1 /* Tree-dumping functionality for intermediate representation.
2    Copyright (C) 1999, 2000 Free Software Foundation, Inc.
3    Written by Mark Mitchell <mark@codesourcery.com>
4
5 This file is part of GNU CC.
6
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING.  If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22 #include "config.h"
23 #include "system.h"
24 #include "tree.h"
25 #include "c-common.h"
26 #include "splay-tree.h"
27 #include "diagnostic.h"
28 #include "toplev.h"
29 #include "c-dump.h"
30
31 /* A callback function used dump language-specific parts of tree
32    nodes.  Returns non-zero if it does not want the usual dumping of
33    the second argument.  */
34
35 dump_tree_fn lang_dump_tree;
36
37 static unsigned int queue PARAMS ((dump_info_p, tree, int));
38 static void dump_index PARAMS ((dump_info_p, unsigned int));
39 static void dequeue_and_dump PARAMS ((dump_info_p));
40 static void dump_new_line PARAMS ((dump_info_p));
41 static void dump_maybe_newline PARAMS ((dump_info_p));
42 static void dump_string_field PARAMS ((dump_info_p, const char *, const char *));
43 static void dump_node PARAMS ((tree, FILE *));
44
45 /* Add T to the end of the queue of nodes to dump.  Returns the index
46    assigned to T.  */
47
48 static unsigned int
49 queue (di, t, flags)
50      dump_info_p di;
51      tree t;
52      int flags;
53 {
54   dump_queue_p dq;
55   dump_node_info_p dni;
56   unsigned int index;
57
58   /* Assign the next available index to T.  */
59   index = ++di->index;
60
61   /* Obtain a new queue node.  */
62   if (di->free_list)
63     {
64       dq = di->free_list;
65       di->free_list = dq->next;
66     }
67   else
68     dq = (dump_queue_p) xmalloc (sizeof (struct dump_queue));
69
70   /* Create a new entry in the splay-tree.  */
71   dni = (dump_node_info_p) xmalloc (sizeof (struct dump_node_info));
72   dni->index = index;
73   dni->binfo_p = ((flags & DUMP_BINFO) != 0);
74   dq->node = splay_tree_insert (di->nodes, (splay_tree_key) t, 
75                                 (splay_tree_value) dni);
76
77   /* Add it to the end of the queue.  */
78   dq->next = 0;
79   if (!di->queue_end)
80     di->queue = dq;
81   else
82     di->queue_end->next = dq;
83   di->queue_end = dq;
84
85   /* Return the index.  */
86   return index;
87 }
88
89 static void
90 dump_index (di, index)
91      dump_info_p di;
92      unsigned int index;
93 {
94   fprintf (di->stream, "@%-6u ", index);
95   di->column += 8;
96 }
97
98 /* If T has not already been output, queue it for subsequent output.
99    FIELD is a string to print before printing the index.  Then, the
100    index of T is printed.  */
101
102 void
103 queue_and_dump_index (di, field, t, flags)
104      dump_info_p di;
105      const char *field;
106      tree t;
107      int flags;
108 {
109   unsigned int index;
110   splay_tree_node n;
111
112   /* If there's no node, just return.  This makes for fewer checks in
113      our callers.  */
114   if (!t)
115     return;
116
117   /* See if we've already queued or dumped this node.  */
118   n = splay_tree_lookup (di->nodes, (splay_tree_key) t);
119   if (n)
120     index = ((dump_node_info_p) n->value)->index;
121   else
122     /* If we haven't, add it to the queue.  */
123     index = queue (di, t, flags);
124
125   /* Print the index of the node.  */
126   dump_maybe_newline (di);
127   fprintf (di->stream, "%-4s: ", field);
128   di->column += 6;
129   dump_index (di, index);
130 }
131
132 /* Dump the type of T.  */
133
134 void
135 queue_and_dump_type (di, t)
136      dump_info_p di;
137      tree t;
138 {
139   queue_and_dump_index (di, "type", TREE_TYPE (t), DUMP_NONE);
140 }
141
142 /* Insert a new line in the dump output, and indent to an appropriate
143    place to start printing more fields.  */
144
145 static void
146 dump_new_line (di)
147      dump_info_p di;
148 {
149   fprintf (di->stream, "\n%25s", "");
150   di->column = 25;
151 }
152
153 /* If necessary, insert a new line.  */
154
155 static void
156 dump_maybe_newline (di)
157      dump_info_p di;
158 {
159   /* See if we need a new line.  */
160   if (di->column > 53)
161     dump_new_line (di);
162   /* See if we need any padding.  */
163   else if ((di->column - 25) % 14 != 0)
164     {
165       fprintf (di->stream, "%*s", 14 - ((di->column - 25) % 14), "");
166       di->column += 14 - (di->column - 25) % 14;
167     }
168 }
169
170 /* Dump I using FIELD to identity it.  */
171
172 void
173 dump_int (di, field, i)
174      dump_info_p di;
175      const char *field;
176      int i;
177 {
178   dump_maybe_newline (di);
179   fprintf (di->stream, "%-4s: %-7d ", field, i);
180   di->column += 14;
181 }
182
183 /* Dump the string S.  */
184
185 void
186 dump_string (di, string)
187      dump_info_p di;
188      const char *string;
189 {
190   dump_maybe_newline (di);
191   fprintf (di->stream, "%-13s ", string);
192   if (strlen (string) > 13)
193     di->column += strlen (string) + 1;
194   else
195     di->column += 14;
196 }
197
198 /* Dump the string field S.  */
199
200 static void
201 dump_string_field (di, field, string)
202      dump_info_p di;
203      const char *field;
204      const char *string;
205 {
206   dump_maybe_newline (di);
207   fprintf (di->stream, "%-4s: %-7s ", field, string);
208   if (strlen (string) > 7)
209     di->column += 6 + strlen (string) + 1;
210   else
211     di->column += 14;
212 }
213
214 /* Dump information common to statements from STMT.  */
215
216 void
217 dump_stmt (di, t)
218      dump_info_p di;
219      tree t;
220 {
221   dump_int (di, "line", STMT_LINENO (t));
222 }
223
224 /* Dump the next statement after STMT.  */
225
226 void
227 dump_next_stmt (di, t)
228      dump_info_p di;
229      tree t;
230 {
231   dump_child ("next", TREE_CHAIN (t));
232 }
233
234 /* Dump the next node in the queue.  */
235
236 static void 
237 dequeue_and_dump (di)
238      dump_info_p di;
239 {
240   dump_queue_p dq;
241   splay_tree_node stn;
242   dump_node_info_p dni;
243   tree t;
244   unsigned int index;
245   enum tree_code code;
246   char code_class;
247   const char* code_name;
248
249   /* Get the next node from the queue.  */
250   dq = di->queue;
251   stn = dq->node;
252   t = (tree) stn->key;
253   dni = (dump_node_info_p) stn->value;
254   index = dni->index;
255
256   /* Remove the node from the queue, and put it on the free list.  */
257   di->queue = dq->next;
258   if (!di->queue)
259     di->queue_end = 0;
260   dq->next = di->free_list;
261   di->free_list = dq;
262
263   /* Print the node index.  */
264   dump_index (di, index);
265   /* And the type of node this is.  */
266   if (dni->binfo_p)
267     code_name = "binfo";
268   else
269     code_name = tree_code_name[(int) TREE_CODE (t)];
270   fprintf (di->stream, "%-16s ", code_name);
271   di->column = 25;
272
273   /* Figure out what kind of node this is.  */
274   code = TREE_CODE (t);
275   code_class = TREE_CODE_CLASS (code);
276
277   /* Although BINFOs are TREE_VECs, we dump them specially so as to be
278      more informative.  */
279   if (dni->binfo_p)
280     {
281       if (TREE_VIA_PUBLIC (t))
282         dump_string (di, "pub");
283       else if (TREE_VIA_PROTECTED (t))
284         dump_string (di, "prot");
285       else if (TREE_VIA_PRIVATE (t))
286         dump_string (di, "priv");
287       if (TREE_VIA_VIRTUAL (t))
288         dump_string (di, "virt");
289             
290       dump_child ("type", BINFO_TYPE (t));
291       dump_child ("base", BINFO_BASETYPES (t));
292
293       goto done;
294     }
295
296   /* We can knock off a bunch of expression nodes in exactly the same
297      way.  */
298   if (IS_EXPR_CODE_CLASS (code_class))
299     {
300       /* If we're dumping children, dump them now.  */
301       queue_and_dump_type (di, t);
302
303       switch (code_class)
304         {
305         case '1':
306           dump_child ("op 0", TREE_OPERAND (t, 0));
307           break;
308               
309         case '2':
310         case '<':
311           dump_child ("op 0", TREE_OPERAND (t, 0));
312           dump_child ("op 1", TREE_OPERAND (t, 1));
313           break;
314               
315         case 'e':
316           /* These nodes are handled explicitly below.  */
317           break;
318               
319         default:
320           abort();
321         }
322     }
323   else if (DECL_P (t))
324     {
325       /* All declarations have names.  */
326       if (DECL_NAME (t))
327         dump_child ("name", DECL_NAME (t));
328       if (DECL_ASSEMBLER_NAME (t) 
329           && DECL_ASSEMBLER_NAME (t) != DECL_NAME (t))
330         dump_child ("mngl", DECL_ASSEMBLER_NAME (t));
331       /* And types.  */
332       queue_and_dump_type (di, t);
333       dump_child ("scpe", DECL_CONTEXT (t));
334       /* And a source position.  */
335       if (DECL_SOURCE_FILE (t))
336         {
337           const char *filename = strrchr (DECL_SOURCE_FILE (t), '/');
338           if (!filename)
339             filename = DECL_SOURCE_FILE (t);
340           else
341             /* Skip the slash.  */
342             ++filename;
343
344           dump_maybe_newline (di);
345           fprintf (di->stream, "srcp: %s:%-6d ", filename, 
346                    DECL_SOURCE_LINE (t));
347           di->column += 6 + strlen (filename) + 8;
348         }
349       /* And any declaration can be compiler-generated.  */
350       if (DECL_ARTIFICIAL (t))
351         dump_string (di, "artificial");
352       if (TREE_CHAIN (t))
353         dump_child ("chan", TREE_CHAIN (t));
354     }
355   else if (code_class == 't')
356     {
357       /* All types have qualifiers.  */
358       int quals = C_TYPE_QUALS (t);
359       if (quals != TYPE_UNQUALIFIED)
360         {
361           fprintf (di->stream, "qual: %c%c%c     ",
362                    (quals & TYPE_QUAL_CONST) ? 'c' : ' ',
363                    (quals & TYPE_QUAL_VOLATILE) ? 'v' : ' ',
364                    (quals & TYPE_QUAL_RESTRICT) ? 'r' : ' ');
365           di->column += 14;
366         }
367
368       /* All types have associated declarations.  */
369       dump_child ("name", TYPE_NAME (t));
370
371       /* All types have a main variant.  */
372       if (TYPE_MAIN_VARIANT (t) != t)
373         dump_child ("unql", TYPE_MAIN_VARIANT (t));
374       
375       /* And sizes.  */
376       dump_child ("size", TYPE_SIZE (t));
377
378       /* All types have alignments.  */
379       dump_int (di, "algn", TYPE_ALIGN (t));
380     }
381   else if (code_class == 'c')
382     /* All constants can have types.  */
383     queue_and_dump_type (di, t);
384
385   /* Give the language-specific code a chance to print something.  If
386      it's completely taken care of things, don't bother printing
387      anything more ourselves.  */
388   if (lang_dump_tree && (*lang_dump_tree) (di, t))
389     goto done;
390
391   /* Now handle the various kinds of nodes.  */
392   switch (code)
393     {
394       int i;
395
396     case IDENTIFIER_NODE:
397       dump_string_field (di, "strg", IDENTIFIER_POINTER (t));
398       dump_int (di, "lngt", IDENTIFIER_LENGTH (t));
399       break;
400
401     case TREE_LIST:
402       dump_child ("purp", TREE_PURPOSE (t));
403       dump_child ("valu", TREE_VALUE (t));
404       dump_child ("chan", TREE_CHAIN (t));
405       break;
406
407     case TREE_VEC:
408       dump_int (di, "lngt", TREE_VEC_LENGTH (t));
409       for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
410         {
411           char buffer[32];
412           sprintf (buffer, "%u", i);
413           dump_child (buffer, TREE_VEC_ELT (t, i));
414         }
415       break;
416
417     case INTEGER_TYPE:
418     case ENUMERAL_TYPE:
419       dump_int (di, "prec", TYPE_PRECISION (t));
420       if (TREE_UNSIGNED (t))
421         dump_string (di, "unsigned");
422       dump_child ("min", TYPE_MIN_VALUE (t));
423       dump_child ("max", TYPE_MAX_VALUE (t));
424
425       if (code == ENUMERAL_TYPE)
426         dump_child ("csts", TYPE_VALUES (t));
427       break;
428
429     case REAL_TYPE:
430       dump_int (di, "prec", TYPE_PRECISION (t));
431       break;
432
433     case POINTER_TYPE:
434       dump_child ("ptd", TREE_TYPE (t));
435       break;
436
437     case REFERENCE_TYPE:
438       dump_child ("refd", TREE_TYPE (t));
439       break;
440
441     case METHOD_TYPE:
442       dump_child ("clas", TYPE_METHOD_BASETYPE (t));
443       /* Fall through.  */
444
445     case FUNCTION_TYPE:
446       dump_child ("retn", TREE_TYPE (t));
447       dump_child ("prms", TYPE_ARG_TYPES (t));
448       break;
449
450     case ARRAY_TYPE:
451       dump_child ("elts", TREE_TYPE (t));
452       dump_child ("domn", TYPE_DOMAIN (t));
453       break;
454
455     case RECORD_TYPE:
456     case UNION_TYPE:
457       if (TREE_CODE (t) == RECORD_TYPE)
458         dump_string (di, "struct");
459       else
460         dump_string (di, "union");
461       
462       dump_child ("flds", TYPE_FIELDS (t));
463       dump_child ("fncs", TYPE_METHODS (t));
464       queue_and_dump_index (di, "binf", TYPE_BINFO (t), 
465                             DUMP_BINFO);
466       break;
467
468     case CONST_DECL:
469       dump_child ("cnst", DECL_INITIAL (t));
470       break;
471
472     case VAR_DECL:
473     case PARM_DECL:
474     case FIELD_DECL:
475     case RESULT_DECL:
476       if (TREE_CODE (t) == PARM_DECL)
477         dump_child ("argt", DECL_ARG_TYPE (t));
478       else
479         dump_child ("init", DECL_INITIAL (t));
480       dump_child ("size", DECL_SIZE (t));
481       dump_int (di, "algn", DECL_ALIGN (t));
482
483       if (TREE_CODE (t) == FIELD_DECL)
484         {
485           if (DECL_C_BIT_FIELD (t))
486             dump_string (di, "bitfield");
487           if (DECL_FIELD_OFFSET (t))
488             dump_child ("bpos", bit_position (t));
489         }
490       else if (TREE_CODE (t) == VAR_DECL 
491                || TREE_CODE (t) == PARM_DECL)
492         {
493           dump_int (di, "used", TREE_USED (t));
494           if (DECL_REGISTER (t))
495             dump_string (di, "register");
496         }
497       break;
498
499     case FUNCTION_DECL:
500       dump_child ("args", DECL_ARGUMENTS (t));
501       if (DECL_EXTERNAL (t))
502         dump_string (di, "undefined");
503       if (TREE_PUBLIC (t))
504         dump_string (di, "extern");
505       else
506         dump_string (di, "static");
507       if (DECL_LANG_SPECIFIC (t))
508         dump_child ("body", DECL_SAVED_TREE (t));
509       break;
510
511     case ASM_STMT:
512       dump_stmt (di, t);
513       if (ASM_VOLATILE_P (t))
514         dump_string (di, "volatile");
515       dump_child ("strg", ASM_STRING (t));
516       dump_child ("outs", ASM_OUTPUTS (t));
517       dump_child ("ins", ASM_INPUTS (t));
518       dump_child ("clbr", ASM_CLOBBERS (t));
519       dump_next_stmt (di, t);
520       break;
521
522     case BREAK_STMT:
523     case CONTINUE_STMT:
524       dump_stmt (di, t);
525       dump_next_stmt (di, t);
526       break;
527
528     case CASE_LABEL:
529       /* Note that a case label is not like other statments; there is
530          no way to get the line-number of a case label.  */
531       dump_child ("low", CASE_LOW (t));
532       dump_child ("high", CASE_HIGH (t));
533       dump_next_stmt (di, t);
534       break;
535
536     case COMPOUND_STMT:
537       dump_stmt (di, t);
538       dump_child ("body", COMPOUND_BODY (t));
539       dump_next_stmt (di, t);
540       break;
541
542     case DECL_STMT:
543       dump_stmt (di, t);
544       dump_child ("decl", DECL_STMT_DECL (t));
545       dump_next_stmt (di, t);
546       break;
547       
548     case DO_STMT:
549       dump_stmt (di, t);
550       dump_child ("body", DO_BODY (t));
551       dump_child ("cond", DO_COND (t));
552       dump_next_stmt (di, t);
553       break;
554
555     case EXPR_STMT:
556       dump_stmt (di, t);
557       dump_child ("expr", EXPR_STMT_EXPR (t));
558       dump_next_stmt (di, t);
559       break;
560
561     case FOR_STMT:
562       dump_stmt (di, t);
563       dump_child ("init", FOR_INIT_STMT (t));
564       dump_child ("cond", FOR_COND (t));
565       dump_child ("expr", FOR_EXPR (t));
566       dump_child ("body", FOR_BODY (t));
567       dump_next_stmt (di, t);
568       break;
569
570     case GOTO_STMT:
571       dump_stmt (di, t);
572       dump_child ("dest", GOTO_DESTINATION (t));
573       dump_next_stmt (di, t);
574       break;
575
576     case IF_STMT:
577       dump_stmt (di, t);
578       dump_child ("cond", IF_COND (t));
579       dump_child ("then", THEN_CLAUSE (t));
580       dump_child ("else", ELSE_CLAUSE (t));
581       dump_next_stmt (di, t);
582       break;
583
584     case LABEL_STMT:
585       dump_stmt (di, t);
586       dump_child ("labl", LABEL_STMT_LABEL (t));
587       dump_next_stmt (di, t);
588       break;
589
590     case RETURN_STMT:
591       dump_stmt (di, t);
592       dump_child ("expr", RETURN_EXPR (t));
593       dump_next_stmt (di, t);
594       break;
595
596     case SWITCH_STMT:
597       dump_stmt (di, t);
598       dump_child ("cond", SWITCH_COND (t));
599       dump_child ("body", SWITCH_BODY (t));
600       dump_next_stmt (di, t);
601       break;
602
603     case WHILE_STMT:
604       dump_stmt (di, t);
605       dump_child ("cond", WHILE_COND (t));
606       dump_child ("body", WHILE_BODY (t));
607       dump_next_stmt (di, t);
608       break;
609
610     case SCOPE_STMT:
611       dump_stmt (di, t);
612       if (SCOPE_BEGIN_P (t))
613         dump_string (di, "begn");
614       else
615         dump_string (di, "end");
616       if (SCOPE_NULLIFIED_P (t))
617         dump_string (di, "null");
618       if (!SCOPE_NO_CLEANUPS_P (t))
619         dump_string (di, "clnp");
620       dump_next_stmt (di, t);
621       break;
622
623     case INTEGER_CST:
624       if (TREE_INT_CST_HIGH (t))
625         dump_int (di, "high", TREE_INT_CST_HIGH (t));
626       dump_int (di, "low", TREE_INT_CST_LOW (t));
627       break;
628
629     case STRING_CST:
630       fprintf (di->stream, "strg: %-7s ", TREE_STRING_POINTER (t));
631       dump_int (di, "lngt", TREE_STRING_LENGTH (t));
632       break;
633
634     case TRUTH_NOT_EXPR:
635     case ADDR_EXPR:
636     case INDIRECT_REF:
637     case CLEANUP_POINT_EXPR:
638     case SAVE_EXPR:
639       /* These nodes are unary, but do not have code class `1'.  */
640       dump_child ("op 0", TREE_OPERAND (t, 0));
641       break;
642
643     case TRUTH_ANDIF_EXPR:
644     case TRUTH_ORIF_EXPR:
645     case INIT_EXPR:
646     case MODIFY_EXPR:
647     case COMPONENT_REF:
648     case COMPOUND_EXPR:
649     case ARRAY_REF:
650     case PREDECREMENT_EXPR:
651     case PREINCREMENT_EXPR:
652     case POSTDECREMENT_EXPR:
653     case POSTINCREMENT_EXPR:
654       /* These nodes are binary, but do not have code class `2'.  */
655       dump_child ("op 0", TREE_OPERAND (t, 0));
656       dump_child ("op 1", TREE_OPERAND (t, 1));
657       break;
658
659     case COND_EXPR:
660       dump_child ("op 0", TREE_OPERAND (t, 0));
661       dump_child ("op 1", TREE_OPERAND (t, 1));
662       dump_child ("op 2", TREE_OPERAND (t, 2));
663       break;
664
665     case CALL_EXPR:
666       dump_child ("fn", TREE_OPERAND (t, 0));
667       dump_child ("args", TREE_OPERAND (t, 1));
668       break;
669
670     case CONSTRUCTOR:
671       dump_child ("elts", TREE_OPERAND (t, 1));
672       break;
673
674     case STMT_EXPR:
675       dump_child ("stmt", STMT_EXPR_STMT (t));
676       break;
677
678     case BIND_EXPR:
679       dump_child ("vars", TREE_OPERAND (t, 0));
680       dump_child ("body", TREE_OPERAND (t, 1));
681       break;
682
683     case LOOP_EXPR:
684       dump_child ("body", TREE_OPERAND (t, 0));
685       break;
686
687     case EXIT_EXPR:
688       dump_child ("cond", TREE_OPERAND (t, 0));
689       break;
690
691     case TARGET_EXPR:
692       dump_child ("decl", TREE_OPERAND (t, 0));
693       dump_child ("init", TREE_OPERAND (t, 1));
694       dump_child ("clnp", TREE_OPERAND (t, 2));
695       /* There really are two possible places the initializer can be.
696          After RTL expansion, the second operand is moved to the
697          position of the fourth operand, and the second operand
698          becomes NULL.  */
699       dump_child ("init", TREE_OPERAND (t, 3));
700       break;
701       
702     case EXPR_WITH_FILE_LOCATION:
703       dump_child ("expr", EXPR_WFL_NODE (t));
704       break;
705
706     default:
707       /* There are no additional fields to print.  */
708       break;
709     }
710
711  done:
712   /* Terminate the line.  */
713   fprintf (di->stream, "\n");
714 }
715
716 /* Dump T, and all its children, on STREAM.  */
717
718 static void
719 dump_node (t, stream)
720      tree t;
721      FILE *stream;
722 {
723   struct dump_info di;
724   dump_queue_p dq;
725   dump_queue_p next_dq;
726
727   /* Initialize the dump-information structure.  */
728   di.stream = stream;
729   di.index = 0;
730   di.column = 0;
731   di.queue = 0;
732   di.queue_end = 0;
733   di.free_list = 0;
734   di.nodes = splay_tree_new (splay_tree_compare_pointers, 0, 
735                              (splay_tree_delete_value_fn) &free);
736
737   /* Queue up the first node.  */
738   queue (&di, t, DUMP_NONE);
739
740   /* Until the queue is empty, keep dumping nodes.  */
741   while (di.queue)
742     dequeue_and_dump (&di);
743
744   /* Now, clean up.  */
745   for (dq = di.free_list; dq; dq = next_dq)
746     {
747       next_dq = dq->next;
748       free (dq);
749     }
750   splay_tree_delete (di.nodes);
751 }
752
753 /* Dump T, and all its children, to FILE.  */
754
755 void
756 dump_node_to_file (t, file)
757      tree t;
758      const char *file;
759 {
760   FILE *f;
761
762   f = fopen (file, "w");
763   if (!f)
764     error ("could not open dump file `%s'", file);
765   else
766     {
767       dump_node (t, f);
768       fclose (f);
769     }
770 }