OSDN Git Service

* tree.def (SET_TYPE): Remove.
[pf3gnuchains/gcc-fork.git] / gcc / tree-browser.c
1 /* Tree browser.
2    Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
3    Contributed by Sebastian Pop <s.pop@laposte.net>
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING.  If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.  */
21
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "errors.h"
27 #include "tree.h"
28 #include "tree-inline.h"
29 #include "diagnostic.h"
30 #include "hashtab.h"
31
32
33 #define TB_OUT_FILE stdout
34 #define TB_IN_FILE stdin
35 #define TB_NIY fprintf (TB_OUT_FILE, "Sorry this command is not yet implemented.\n")
36 #define TB_WF fprintf (TB_OUT_FILE, "Warning, this command failed.\n")
37
38
39 /* Structures for handling Tree Browser's commands.  */
40 #define DEFTBCODE(COMMAND, STRING, HELP)   COMMAND,
41 enum TB_Comm_code {
42 #include "tree-browser.def"
43   TB_UNUSED_COMMAND
44 };
45 #undef DEFTBCODE
46 typedef enum TB_Comm_code TB_CODE;
47
48 struct tb_command {
49   const char *help_msg;
50   const char *comm_text;
51   size_t comm_len;
52   TB_CODE comm_code;
53 };
54
55 #define DEFTBCODE(code, str, help) { help, str, sizeof(str) - 1, code },
56 #ifdef HOST_EBCDIC
57 static struct tb_command tb_commands[] =
58 #else
59 static const struct tb_command tb_commands[] =
60 #endif
61 {
62 #include "tree-browser.def"
63 };
64 #undef DEFTBCODE
65
66 #define TB_COMMAND_LEN(N) (tb_commands[N].comm_len)
67 #define TB_COMMAND_TEXT(N) (tb_commands[N].comm_text)
68 #define TB_COMMAND_CODE(N) (tb_commands[N].comm_code)
69 #define TB_COMMAND_HELP(N) (tb_commands[N].help_msg)
70
71
72 /* Next structure is for parsing TREE_CODEs.  */
73 struct tb_tree_code {
74   enum tree_code code;
75   const char *code_string;
76   size_t code_string_len;
77 };
78
79 #define DEFTREECODE(SYM, STRING, TYPE, NARGS) { SYM, STRING, sizeof (STRING) - 1 },
80 #ifdef HOST_EBCDIC
81 static struct tb_tree_code tb_tree_codes[] =
82 #else
83 static const struct tb_tree_code tb_tree_codes[] =
84 #endif
85 {
86 #include "tree.def"
87 };
88 #undef DEFTREECODE
89
90 #define TB_TREE_CODE(N) (tb_tree_codes[N].code)
91 #define TB_TREE_CODE_TEXT(N) (tb_tree_codes[N].code_string)
92 #define TB_TREE_CODE_LEN(N) (tb_tree_codes[N].code_string_len)
93
94
95 /* Function declarations.  */
96
97 static long TB_getline (char **, long *, FILE *);
98 static TB_CODE TB_get_command (char *);
99 static enum tree_code TB_get_tree_code (char *);
100 static tree find_node_with_code (tree *, int *, void *);
101 static tree store_child_info (tree *, int *, void *);
102 static void TB_update_up (tree);
103 static tree TB_current_chain_node (tree);
104 static tree TB_prev_expr (tree);
105 static tree TB_next_expr (tree);
106 static tree TB_up_expr (tree);
107 static tree TB_first_in_bind (tree);
108 static tree TB_last_in_bind (tree);
109 static int  TB_parent_eq (const void *, const void *);
110 static tree TB_history_prev (void);
111
112 /* FIXME: To be declared in a .h file.  */
113 void browse_tree (tree);
114
115 /* Static variables.  */
116 static htab_t TB_up_ht;
117 static tree TB_history_stack = NULL_TREE;
118 static int TB_verbose = 1;
119
120
121 /* Entry point in the Tree Browser.  */
122
123 void
124 browse_tree (tree begin)
125 {
126   tree head;
127   TB_CODE tbc = TB_UNUSED_COMMAND;
128   ssize_t rd;
129   char *input = NULL;
130   long input_size = 0;
131
132   fprintf (TB_OUT_FILE, "\nTree Browser\n");
133
134 #define TB_SET_HEAD(N) do {                                           \
135   TB_history_stack = tree_cons (NULL_TREE, (N), TB_history_stack);    \
136   head = N;                                                           \
137   if (TB_verbose)                                                     \
138     if (head)                                                         \
139       {                                                               \
140         print_generic_expr (TB_OUT_FILE, head, 0);                    \
141         fprintf (TB_OUT_FILE, "\n");                                  \
142       }                                                               \
143 } while (0)
144
145   TB_SET_HEAD (begin);
146
147   /* Store in a hashtable information about previous and upper statements.  */
148   {
149     TB_up_ht = htab_create (1023, htab_hash_pointer, &TB_parent_eq, NULL);
150     TB_update_up (head);
151   }
152
153   while (24)
154     {
155       fprintf (TB_OUT_FILE, "TB> ");
156       rd = TB_getline (&input, &input_size, TB_IN_FILE);
157
158       if (rd == -1)
159         /* EOF.  */
160         goto ret;
161
162       if (rd != 1)
163         /* Get a new command.  Otherwise the user just pressed enter, and thus
164            she expects the last command to be reexecuted.  */
165         tbc = TB_get_command (input);
166
167       switch (tbc)
168         {
169         case TB_UPDATE_UP:
170           TB_update_up (head);
171           break;
172
173         case TB_MAX:
174           if (head && (INTEGRAL_TYPE_P (head)
175                        || TREE_CODE (head) == REAL_TYPE))
176             TB_SET_HEAD (TYPE_MAX_VALUE (head));
177           else
178             TB_WF;
179           break;
180
181         case TB_MIN:
182           if (head && (INTEGRAL_TYPE_P (head)
183                        || TREE_CODE (head) == REAL_TYPE))
184             TB_SET_HEAD (TYPE_MIN_VALUE (head));
185           else
186             TB_WF;
187           break;
188
189         case TB_ELT:
190           if (head && TREE_CODE (head) == TREE_VEC)
191             {
192               /* This command takes another argument: the element number:
193                  for example "elt 1".  */
194               TB_NIY;
195             }
196           else if (head && TREE_CODE (head) == VECTOR_CST)
197             {
198               /* This command takes another argument: the element number:
199                  for example "elt 1".  */
200               TB_NIY;
201             }
202           else
203             TB_WF;
204           break;
205
206         case TB_VALUE:
207           if (head && TREE_CODE (head) == TREE_LIST)
208             TB_SET_HEAD (TREE_VALUE (head));
209           else
210             TB_WF;
211           break;
212
213         case TB_PURPOSE:
214           if (head && TREE_CODE (head) == TREE_LIST)
215             TB_SET_HEAD (TREE_PURPOSE (head));
216           else
217             TB_WF;
218           break;
219
220         case TB_IMAG:
221           if (head && TREE_CODE (head) == COMPLEX_CST)
222             TB_SET_HEAD (TREE_IMAGPART (head));
223           else
224             TB_WF;
225           break;
226
227         case TB_REAL:
228           if (head && TREE_CODE (head) == COMPLEX_CST)
229             TB_SET_HEAD (TREE_REALPART (head));
230           else
231             TB_WF;
232           break;
233
234         case TB_BLOCK:
235           if (head && TREE_CODE (head) == BIND_EXPR)
236             TB_SET_HEAD (TREE_OPERAND (head, 2));
237           else
238             TB_WF;
239           break;
240
241         case TB_SUBBLOCKS:
242           if (head && TREE_CODE (head) == BLOCK)
243             TB_SET_HEAD (BLOCK_SUBBLOCKS (head));
244           else
245             TB_WF;
246           break;
247
248         case TB_SUPERCONTEXT:
249           if (head && TREE_CODE (head) == BLOCK)
250             TB_SET_HEAD (BLOCK_SUPERCONTEXT (head));
251           else
252             TB_WF;
253           break;
254
255         case TB_VARS:
256           if (head && TREE_CODE (head) == BLOCK)
257             TB_SET_HEAD (BLOCK_VARS (head));
258           else if (head && TREE_CODE (head) == BIND_EXPR)
259             TB_SET_HEAD (TREE_OPERAND (head, 0));
260           else
261             TB_WF;
262           break;
263
264         case TB_REFERENCE_TO_THIS:
265           if (head && TYPE_P (head))
266             TB_SET_HEAD (TYPE_REFERENCE_TO (head));
267           else
268             TB_WF;
269           break;
270
271         case TB_POINTER_TO_THIS:
272           if (head && TYPE_P (head))
273             TB_SET_HEAD (TYPE_POINTER_TO (head));
274           else
275             TB_WF;
276           break;
277
278         case TB_BASETYPE:
279           if (head && TREE_CODE (head) == OFFSET_TYPE)
280             TB_SET_HEAD (TYPE_OFFSET_BASETYPE (head));
281           else
282             TB_WF;
283           break;
284
285         case TB_ARG_TYPES:
286           if (head && (TREE_CODE (head) == FUNCTION_TYPE
287                        || TREE_CODE (head) == METHOD_TYPE))
288             TB_SET_HEAD (TYPE_ARG_TYPES (head));
289           else
290             TB_WF;
291           break;
292
293         case TB_METHOD_BASE_TYPE:
294           if (head && (TREE_CODE (head) == FUNCTION_TYPE
295                        || TREE_CODE (head) == METHOD_TYPE)
296               && TYPE_METHOD_BASETYPE (head))
297             TB_SET_HEAD (TYPE_METHOD_BASETYPE (head));
298           else
299             TB_WF;
300           break;
301
302         case TB_FIELDS:
303           if (head && (TREE_CODE (head) == RECORD_TYPE
304                        || TREE_CODE (head) == UNION_TYPE
305                        || TREE_CODE (head) == QUAL_UNION_TYPE))
306             TB_SET_HEAD (TYPE_FIELDS (head));
307           else
308             TB_WF;
309           break;
310
311         case TB_DOMAIN:
312           if (head && TREE_CODE (head) == ARRAY_TYPE)
313             TB_SET_HEAD (TYPE_DOMAIN (head));
314           else
315             TB_WF;
316           break;
317
318         case TB_VALUES:
319           if (head && TREE_CODE (head) == ENUMERAL_TYPE)
320             TB_SET_HEAD (TYPE_VALUES (head));
321           else
322             TB_WF;
323           break;
324
325         case TB_ARG_TYPE_AS_WRITTEN:
326           if (head && TREE_CODE (head) == PARM_DECL)
327             TB_SET_HEAD (DECL_ARG_TYPE_AS_WRITTEN (head));
328           else
329             TB_WF;
330           break;
331
332         case TB_ARG_TYPE:
333           if (head && TREE_CODE (head) == PARM_DECL)
334             TB_SET_HEAD (DECL_ARG_TYPE (head));
335           else
336             TB_WF;
337           break;
338
339         case TB_INITIAL:
340           if (head && DECL_P (head))
341             TB_SET_HEAD (DECL_INITIAL (head));
342           else
343             TB_WF;
344           break;
345
346         case TB_RESULT:
347           if (head && DECL_P (head))
348             TB_SET_HEAD (DECL_RESULT_FLD (head));
349           else
350             TB_WF;
351           break;
352
353         case TB_ARGUMENTS:
354           if (head && DECL_P (head))
355             TB_SET_HEAD (DECL_ARGUMENTS (head));
356           else
357             TB_WF;
358           break;
359
360         case TB_ABSTRACT_ORIGIN:
361           if (head && DECL_P (head))
362             TB_SET_HEAD (DECL_ABSTRACT_ORIGIN (head));
363           else if (head && TREE_CODE (head) == BLOCK)
364             TB_SET_HEAD (BLOCK_ABSTRACT_ORIGIN (head));
365           else
366             TB_WF;
367           break;
368
369         case TB_ATTRIBUTES:
370           if (head && DECL_P (head))
371             TB_SET_HEAD (DECL_ATTRIBUTES (head));
372           else if (head && TYPE_P (head))
373             TB_SET_HEAD (TYPE_ATTRIBUTES (head));
374           else
375             TB_WF;
376           break;
377
378         case TB_CONTEXT:
379           if (head && DECL_P (head))
380             TB_SET_HEAD (DECL_CONTEXT (head));
381           else if (head && TYPE_P (head)
382                    && TYPE_CONTEXT (head))
383             TB_SET_HEAD (TYPE_CONTEXT (head));
384           else
385             TB_WF;
386           break;
387
388         case TB_OFFSET:
389           if (head && TREE_CODE (head) == FIELD_DECL)
390             TB_SET_HEAD (DECL_FIELD_OFFSET (head));
391           else
392             TB_WF;
393           break;
394
395         case TB_BIT_OFFSET:
396           if (head && TREE_CODE (head) == FIELD_DECL)
397             TB_SET_HEAD (DECL_FIELD_BIT_OFFSET (head));
398           else
399             TB_WF;
400           break;
401
402         case TB_UNIT_SIZE:
403           if (head && DECL_P (head))
404             TB_SET_HEAD (DECL_SIZE_UNIT (head));
405           else if (head && TYPE_P (head))
406             TB_SET_HEAD (TYPE_SIZE_UNIT (head));
407           else
408             TB_WF;
409           break;
410
411         case TB_SIZE:
412           if (head && DECL_P (head))
413             TB_SET_HEAD (DECL_SIZE (head));
414           else if (head && TYPE_P (head))
415             TB_SET_HEAD (TYPE_SIZE (head));
416           else
417             TB_WF;
418           break;
419
420         case TB_TYPE:
421           if (head && TREE_TYPE (head))
422             TB_SET_HEAD (TREE_TYPE (head));
423           else
424             TB_WF;
425           break;
426
427         case TB_DECL_SAVED_TREE:
428           if (head && TREE_CODE (head) == FUNCTION_DECL
429               && DECL_SAVED_TREE (head))
430             TB_SET_HEAD (DECL_SAVED_TREE (head));
431           else
432             TB_WF;
433           break;
434
435         case TB_BODY:
436           if (head && TREE_CODE (head) == BIND_EXPR)
437             TB_SET_HEAD (TREE_OPERAND (head, 1));
438           else
439             TB_WF;
440           break;
441
442         case TB_CHILD_0:
443           if (head && EXPR_P (head) && TREE_OPERAND (head, 0))
444             TB_SET_HEAD (TREE_OPERAND (head, 0));
445           else
446             TB_WF;
447           break;
448
449         case TB_CHILD_1:
450           if (head && EXPR_P (head) && TREE_OPERAND (head, 1))
451             TB_SET_HEAD (TREE_OPERAND (head, 1));
452           else
453             TB_WF;
454           break;
455
456         case TB_CHILD_2:
457           if (head && EXPR_P (head) && TREE_OPERAND (head, 2))
458             TB_SET_HEAD (TREE_OPERAND (head, 2));
459           else
460             TB_WF;
461           break;
462
463         case TB_CHILD_3:
464           if (head && EXPR_P (head) && TREE_OPERAND (head, 3))
465             TB_SET_HEAD (TREE_OPERAND (head, 3));
466           else
467             TB_WF;
468           break;
469
470         case TB_PRINT:
471           if (head)
472             debug_tree (head);
473           else
474             TB_WF;
475           break;
476
477         case TB_PRETTY_PRINT:
478           if (head)
479             {
480               print_generic_stmt (TB_OUT_FILE, head, 0);
481               fprintf (TB_OUT_FILE, "\n");
482             }
483           else
484             TB_WF;
485           break;
486
487         case TB_SEARCH_NAME:
488
489           break;
490
491         case TB_SEARCH_CODE:
492           {
493             enum tree_code code;
494             char *arg_text;
495
496             arg_text = strchr (input, ' ');
497             if (arg_text == NULL)
498               {
499                 fprintf (TB_OUT_FILE, "First argument is missing.  This isn't a valid search command.  \n");
500                 break;
501               }
502             code = TB_get_tree_code (arg_text + 1);
503
504             /* Search in the subtree a node with the given code.  */
505             {
506               tree res;
507
508               res = walk_tree (&head, find_node_with_code, &code, NULL);
509               if (res == NULL_TREE)
510                 {
511                   fprintf (TB_OUT_FILE, "There's no node with this code (reachable via the walk_tree function from this node).\n");
512                 }
513               else
514                 {
515                   fprintf (TB_OUT_FILE, "Achoo!  I got this node in the tree.\n");
516                   TB_SET_HEAD (res);
517                 }
518             }
519             break;
520           }
521
522 #define TB_MOVE_HEAD(FCT) do {       \
523   if (head)                          \
524     {                                \
525       tree t;                        \
526       t = FCT (head);                \
527       if (t)                         \
528         TB_SET_HEAD (t);             \
529       else                           \
530         TB_WF;                       \
531     }                                \
532   else                               \
533     TB_WF;                           \
534 } while (0)
535
536         case TB_FIRST:
537           TB_MOVE_HEAD (TB_first_in_bind);
538           break;
539
540         case TB_LAST:
541           TB_MOVE_HEAD (TB_last_in_bind);
542           break;
543
544         case TB_UP:
545           TB_MOVE_HEAD (TB_up_expr);
546           break;
547
548         case TB_PREV:
549           TB_MOVE_HEAD (TB_prev_expr);
550           break;
551
552         case TB_NEXT:
553           TB_MOVE_HEAD (TB_next_expr);
554           break;
555
556         case TB_HPREV:
557           /* This command is a little bit special, since it deals with history
558              stack.  For this reason it should keep the "head = ..." statement
559              and not use TB_MOVE_HEAD.  */
560           if (head)
561             {
562               tree t;
563               t = TB_history_prev ();
564               if (t)
565                 {
566                   head = t;
567                   if (TB_verbose)
568                     {
569                       print_generic_expr (TB_OUT_FILE, head, 0);
570                       fprintf (TB_OUT_FILE, "\n");
571                     }
572                 }
573               else
574                 TB_WF;
575             }
576           else
577             TB_WF;
578           break;
579
580         case TB_CHAIN:
581           /* Don't go further if it's the last node in this chain.  */
582           if (head && TREE_CODE (head) == BLOCK)
583             TB_SET_HEAD (BLOCK_CHAIN (head));
584           else if (head && TREE_CHAIN (head))
585             TB_SET_HEAD (TREE_CHAIN (head));
586           else
587             TB_WF;
588           break;
589
590         case TB_FUN:
591           /* Go up to the current function declaration.  */
592           TB_SET_HEAD (current_function_decl);
593           fprintf (TB_OUT_FILE, "Current function declaration.\n");
594           break;
595
596         case TB_HELP:
597           /* Display a help message.  */
598           {
599             int i;
600             fprintf (TB_OUT_FILE, "Possible commands are:\n\n");
601             for (i = 0; i < TB_UNUSED_COMMAND; i++)
602               {
603                 fprintf (TB_OUT_FILE, "%20s  -  %s\n", TB_COMMAND_TEXT (i), TB_COMMAND_HELP (i));
604               }
605           }
606           break;
607
608         case TB_VERBOSE:
609           if (TB_verbose == 0)
610             {
611               TB_verbose = 1;
612               fprintf (TB_OUT_FILE, "Verbose on.\n");
613             }
614           else
615             {
616               TB_verbose = 0;
617               fprintf (TB_OUT_FILE, "Verbose off.\n");
618             }
619           break;
620
621         case TB_EXIT:
622         case TB_QUIT:
623           /* Just exit from this function.  */
624           goto ret;
625
626         default:
627           TB_NIY;
628         }
629     }
630
631  ret:;
632   htab_delete (TB_up_ht);
633   return;
634 }
635
636
637 /* Search the first node in this BIND_EXPR.  */
638
639 static tree
640 TB_first_in_bind (tree node)
641 {
642   tree t;
643
644   if (node == NULL_TREE)
645     return NULL_TREE;
646
647   while ((t = TB_prev_expr (node)))
648     node = t;
649
650   return node;
651 }
652
653 /* Search the last node in this BIND_EXPR.  */
654
655 static tree
656 TB_last_in_bind (tree node)
657 {
658   tree t;
659
660   if (node == NULL_TREE)
661     return NULL_TREE;
662
663   while ((t = TB_next_expr (node)))
664     node = t;
665
666   return node;
667 }
668
669 /* Search the parent expression for this node.  */
670
671 static tree
672 TB_up_expr (tree node)
673 {
674   tree res;
675   if (node == NULL_TREE)
676     return NULL_TREE;
677
678   res = (tree) htab_find (TB_up_ht, node);
679   return res;
680 }
681
682 /* Search the previous expression in this BIND_EXPR.  */
683
684 static tree
685 TB_prev_expr (tree node)
686 {
687   node = TB_current_chain_node (node);
688
689   if (node == NULL_TREE)
690     return NULL_TREE;
691
692   node = TB_up_expr (node);
693   if (node && TREE_CODE (node) == COMPOUND_EXPR)
694     return node;
695   else
696     return NULL_TREE;
697 }
698
699 /* Search the next expression in this BIND_EXPR.  */
700
701 static tree
702 TB_next_expr (tree node)
703 {
704   node = TB_current_chain_node (node);
705
706   if (node == NULL_TREE)
707     return NULL_TREE;
708
709   node = TREE_OPERAND (node, 1);
710   return node;
711 }
712
713 static tree
714 TB_current_chain_node (tree node)
715 {
716   if (node == NULL_TREE)
717     return NULL_TREE;
718
719   if (TREE_CODE (node) == COMPOUND_EXPR)
720     return node;
721
722   node = TB_up_expr (node);
723   if (node)
724     {
725       if (TREE_CODE (node) == COMPOUND_EXPR)
726         return node;
727
728       node = TB_up_expr (node);
729       if (TREE_CODE (node) == COMPOUND_EXPR)
730         return node;
731     }
732
733   return NULL_TREE;
734 }
735
736 /* For each node store in its children nodes that the current node is their
737    parent.  This function is used by walk_tree.  */
738
739 static tree
740 store_child_info (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
741                   void *data ATTRIBUTE_UNUSED)
742 {
743   tree node;
744   void **slot;
745
746   node = *tp;
747
748   /* 'node' is the parent of 'TREE_OPERAND (node, *)'.  */
749   if (EXPRESSION_CLASS_P (node))
750     {
751
752 #define STORE_CHILD(N) do {                                                \
753   tree op = TREE_OPERAND (node, N);                                        \
754   slot = htab_find_slot (TB_up_ht, op, INSERT);                               \
755   *slot = (void *) node;                                                   \
756 } while (0)
757
758       switch (TREE_CODE_LENGTH (TREE_CODE (node)))
759         {
760         case 4:
761           STORE_CHILD (0);
762           STORE_CHILD (1);
763           STORE_CHILD (2);
764           STORE_CHILD (3);
765           break;
766
767         case 3:
768           STORE_CHILD (0);
769           STORE_CHILD (1);
770           STORE_CHILD (2);
771           break;
772
773         case 2:
774           STORE_CHILD (0);
775           STORE_CHILD (1);
776           break;
777
778         case 1:
779           STORE_CHILD (0);
780           break;
781
782         case 0:
783         default:
784           /* No children: nothing to do.  */
785           break;
786         }
787 #undef STORE_CHILD
788     }
789
790   /* Never stop walk_tree.  */
791   return NULL_TREE;
792 }
793
794 /* Function used in TB_up_ht.  */
795
796 static int
797 TB_parent_eq (const void *p1, const void *p2)
798 {
799   tree node, parent;
800   node = (tree) p2;
801   parent = (tree) p1;
802
803   if (p1 == NULL || p2 == NULL)
804     return 0;
805
806   if (EXPRESSION_CLASS_P (parent))
807     {
808
809 #define TEST_CHILD(N) do {               \
810   if (node == TREE_OPERAND (parent, N))  \
811     return 1;                            \
812 } while (0)
813
814     switch (TREE_CODE_LENGTH (TREE_CODE (parent)))
815       {
816       case 4:
817         TEST_CHILD (0);
818         TEST_CHILD (1);
819         TEST_CHILD (2);
820         TEST_CHILD (3);
821         break;
822
823       case 3:
824         TEST_CHILD (0);
825         TEST_CHILD (1);
826         TEST_CHILD (2);
827         break;
828
829       case 2:
830         TEST_CHILD (0);
831         TEST_CHILD (1);
832         break;
833
834       case 1:
835         TEST_CHILD (0);
836         break;
837
838       case 0:
839       default:
840         /* No children: nothing to do.  */
841         break;
842       }
843 #undef TEST_CHILD
844     }
845
846   return 0;
847 }
848
849 /* Update information about upper expressions in the hash table.  */
850
851 static void
852 TB_update_up (tree node)
853 {
854   while (node)
855     {
856       walk_tree (&node, store_child_info, NULL, NULL);
857
858       /* Walk function's body.  */
859       if (TREE_CODE (node) == FUNCTION_DECL)
860         if (DECL_SAVED_TREE (node))
861           walk_tree (&DECL_SAVED_TREE (node), store_child_info, NULL, NULL);
862
863       /* Walk rest of the chain.  */
864       node = TREE_CHAIN (node);
865     }
866   fprintf (TB_OUT_FILE, "Up/prev expressions updated.\n");
867 }
868
869 /* Parse the input string for determining the command the user asked for.  */
870
871 static TB_CODE
872 TB_get_command (char *input)
873 {
874   unsigned int mn, size_tok;
875   int comp;
876   char *space;
877
878   space = strchr (input, ' ');
879   if (space != NULL)
880     size_tok = strlen (input) - strlen (space);
881   else
882     size_tok = strlen (input) - 1;
883
884   for (mn = 0; mn < TB_UNUSED_COMMAND; mn++)
885     {
886       if (size_tok != TB_COMMAND_LEN (mn))
887         continue;
888
889       comp = memcmp (input, TB_COMMAND_TEXT (mn), TB_COMMAND_LEN (mn));
890       if (comp == 0)
891         /* Here we just determined the command.  If this command takes
892            an argument, then the argument is determined later.  */
893         return TB_COMMAND_CODE (mn);
894     }
895
896   /* Not a valid command.  */
897   return TB_UNUSED_COMMAND;
898 }
899
900 /* Parse the input string for determining the tree code.  */
901
902 static enum tree_code
903 TB_get_tree_code (char *input)
904 {
905   unsigned int mn, size_tok;
906   int comp;
907   char *space;
908
909   space = strchr (input, ' ');
910   if (space != NULL)
911     size_tok = strlen (input) - strlen (space);
912   else
913     size_tok = strlen (input) - 1;
914
915   for (mn = 0; mn < LAST_AND_UNUSED_TREE_CODE; mn++)
916     {
917       if (size_tok != TB_TREE_CODE_LEN (mn))
918         continue;
919
920       comp = memcmp (input, TB_TREE_CODE_TEXT (mn), TB_TREE_CODE_LEN (mn));
921       if (comp == 0)
922         {
923           fprintf (TB_OUT_FILE, "%s\n", TB_TREE_CODE_TEXT (mn));
924           return TB_TREE_CODE (mn);
925         }
926     }
927
928   /* This isn't a valid code.  */
929   return LAST_AND_UNUSED_TREE_CODE;
930 }
931
932 /* Find a node with a given code.  This function is used as an argument to
933    walk_tree.  */
934
935 static tree
936 find_node_with_code (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
937                      void *data)
938 {
939   enum tree_code *code;
940   code = (enum tree_code *) data;
941   if (*code == TREE_CODE (*tp))
942     return *tp;
943
944   return NULL_TREE;
945 }
946
947 /* Returns a pointer to the last visited node.  */
948
949 static tree
950 TB_history_prev (void)
951 {
952   if (TB_history_stack)
953     {
954       TB_history_stack = TREE_CHAIN (TB_history_stack);
955       if (TB_history_stack)
956         return TREE_VALUE (TB_history_stack);
957     }
958   return NULL_TREE;
959 }
960
961 /* Read up to (and including) a '\n' from STREAM into *LINEPTR
962    (and null-terminate it). *LINEPTR is a pointer returned from malloc
963    (or NULL), pointing to *N characters of space.  It is realloc'd as
964    necessary.  Returns the number of characters read (not including the
965    null terminator), or -1 on error or EOF.
966    This function comes from sed (and is supposed to be a portable version
967    of getline).  */
968
969 static long
970 TB_getline (char **lineptr, long *n, FILE *stream)
971 {
972   char *line, *p;
973   long size, copy;
974
975   if (lineptr == NULL || n == NULL)
976     {
977       errno = EINVAL;
978       return -1;
979     }
980
981   if (ferror (stream))
982     return -1;
983
984   /* Make sure we have a line buffer to start with.  */
985   if (*lineptr == NULL || *n < 2) /* !seen and no buf yet need 2 chars.  */
986     {
987 #ifndef MAX_CANON
988 #define MAX_CANON       256
989 #endif
990       line = (char *) xrealloc (*lineptr, MAX_CANON);
991       if (line == NULL)
992         return -1;
993       *lineptr = line;
994       *n = MAX_CANON;
995     }
996
997   line = *lineptr;
998   size = *n;
999
1000   copy = size;
1001   p = line;
1002
1003   while (1)
1004     {
1005       long len;
1006
1007       while (--copy > 0)
1008         {
1009           register int c = getc (stream);
1010           if (c == EOF)
1011             goto lose;
1012           else if ((*p++ = c) == '\n')
1013             goto win;
1014         }
1015
1016       /* Need to enlarge the line buffer.  */
1017       len = p - line;
1018       size *= 2;
1019       line = (char *) xrealloc (line, size);
1020       if (line == NULL)
1021         goto lose;
1022       *lineptr = line;
1023       *n = size;
1024       p = line + len;
1025       copy = size - len;
1026     }
1027
1028  lose:
1029   if (p == *lineptr)
1030     return -1;
1031
1032   /* Return a partial line since we got an error in the middle.  */
1033  win:
1034 #if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) || defined(MSDOS)
1035   if (p - 2 >= *lineptr && p[-2] == '\r')
1036     p[-2] = p[-1], --p;
1037 #endif
1038   *p = '\0';
1039   return p - *lineptr;
1040 }