OSDN Git Service

* tree.def (documentation): Remove mention of class 'b'.
[pf3gnuchains/gcc-fork.git] / gcc / tree-browser.c
1 /* Tree browser.
2    Copyright (C) 2002, 2003 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 && TREE_CODE_CLASS (TREE_CODE (head)) == 't')
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 && TREE_CODE_CLASS (TREE_CODE (head)) == 't')
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                        || TREE_CODE (head) == SET_TYPE))
314             TB_SET_HEAD (TYPE_DOMAIN (head));
315           else
316             TB_WF;
317           break;
318
319         case TB_VALUES:
320           if (head && TREE_CODE (head) == ENUMERAL_TYPE)
321             TB_SET_HEAD (TYPE_VALUES (head));
322           else
323             TB_WF;
324           break;
325
326         case TB_ARG_TYPE_AS_WRITTEN:
327           if (head && TREE_CODE (head) == PARM_DECL)
328             TB_SET_HEAD (DECL_ARG_TYPE_AS_WRITTEN (head));
329           else
330             TB_WF;
331           break;
332
333         case TB_ARG_TYPE:
334           if (head && TREE_CODE (head) == PARM_DECL)
335             TB_SET_HEAD (DECL_ARG_TYPE (head));
336           else
337             TB_WF;
338           break;
339
340         case TB_INITIAL:
341           if (head && TREE_CODE_CLASS (TREE_CODE (head)) == 'd')
342             TB_SET_HEAD (DECL_INITIAL (head));
343           else
344             TB_WF;
345           break;
346
347         case TB_RESULT:
348           if (head && TREE_CODE_CLASS (TREE_CODE (head)) == 'd')
349             TB_SET_HEAD (DECL_RESULT_FLD (head));
350           else
351             TB_WF;
352           break;
353
354         case TB_ARGUMENTS:
355           if (head && TREE_CODE_CLASS (TREE_CODE (head)) == 'd')
356             TB_SET_HEAD (DECL_ARGUMENTS (head));
357           else
358             TB_WF;
359           break;
360
361         case TB_ABSTRACT_ORIGIN:
362           if (head && TREE_CODE_CLASS (TREE_CODE (head)) == 'd')
363             TB_SET_HEAD (DECL_ABSTRACT_ORIGIN (head));
364           else if (head && TREE_CODE (head) == BLOCK)
365             TB_SET_HEAD (BLOCK_ABSTRACT_ORIGIN (head));
366           else
367             TB_WF;
368           break;
369
370         case TB_ATTRIBUTES:
371           if (head && TREE_CODE_CLASS (TREE_CODE (head)) == 'd')
372             TB_SET_HEAD (DECL_ATTRIBUTES (head));
373           else if (head && TREE_CODE_CLASS (TREE_CODE (head)) == 't')
374             TB_SET_HEAD (TYPE_ATTRIBUTES (head));
375           else
376             TB_WF;
377           break;
378
379         case TB_CONTEXT:
380           if (head && TREE_CODE_CLASS (TREE_CODE (head)) == 'd')
381             TB_SET_HEAD (DECL_CONTEXT (head));
382           else if (head && TREE_CODE_CLASS (TREE_CODE (head)) == 't'
383                    && TYPE_CONTEXT (head))
384             TB_SET_HEAD (TYPE_CONTEXT (head));
385           else
386             TB_WF;
387           break;
388
389         case TB_OFFSET:
390           if (head && TREE_CODE (head) == FIELD_DECL)
391             TB_SET_HEAD (DECL_FIELD_OFFSET (head));
392           else
393             TB_WF;
394           break;
395
396         case TB_BIT_OFFSET:
397           if (head && TREE_CODE (head) == FIELD_DECL)
398             TB_SET_HEAD (DECL_FIELD_BIT_OFFSET (head));
399           else
400             TB_WF;
401           break;
402
403         case TB_UNIT_SIZE:
404           if (head && TREE_CODE_CLASS (TREE_CODE (head)) == 'd')
405             TB_SET_HEAD (DECL_SIZE_UNIT (head));
406           else if (head && TREE_CODE_CLASS (TREE_CODE (head)) == 't')
407             TB_SET_HEAD (TYPE_SIZE_UNIT (head));
408           else
409             TB_WF;
410           break;
411
412         case TB_SIZE:
413           if (head && TREE_CODE_CLASS (TREE_CODE (head)) == 'd')
414             TB_SET_HEAD (DECL_SIZE (head));
415           else if (head && TREE_CODE_CLASS (TREE_CODE (head)) == 't')
416             TB_SET_HEAD (TYPE_SIZE (head));
417           else
418             TB_WF;
419           break;
420
421         case TB_TYPE:
422           if (head && TREE_TYPE (head))
423             TB_SET_HEAD (TREE_TYPE (head));
424           else
425             TB_WF;
426           break;
427
428         case TB_DECL_SAVED_TREE:
429           if (head && TREE_CODE (head) == FUNCTION_DECL
430               && DECL_SAVED_TREE (head))
431             TB_SET_HEAD (DECL_SAVED_TREE (head));
432           else
433             TB_WF;
434           break;
435
436         case TB_BODY:
437           if (head && TREE_CODE (head) == BIND_EXPR)
438             TB_SET_HEAD (TREE_OPERAND (head, 1));
439           else
440             TB_WF;
441           break;
442
443         case TB_CHILD_0:
444           if (head && IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (head)))
445               && TREE_OPERAND (head, 0))
446             TB_SET_HEAD (TREE_OPERAND (head, 0));
447           else
448             TB_WF;
449           break;
450
451         case TB_CHILD_1:
452           if (head && IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (head)))
453               && TREE_OPERAND (head, 1))
454             TB_SET_HEAD (TREE_OPERAND (head, 1));
455           else
456             TB_WF;
457           break;
458
459         case TB_CHILD_2:
460           if (head && IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (head)))
461               && TREE_OPERAND (head, 2))
462             TB_SET_HEAD (TREE_OPERAND (head, 2));
463           else
464             TB_WF;
465           break;
466
467         case TB_CHILD_3:
468           if (head && IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (head)))
469               && TREE_OPERAND (head, 3))
470             TB_SET_HEAD (TREE_OPERAND (head, 3));
471           else
472             TB_WF;
473           break;
474
475         case TB_PRINT:
476           if (head)
477             debug_tree (head);
478           else
479             TB_WF;
480           break;
481
482         case TB_PRETTY_PRINT:
483           if (head)
484             {
485               print_generic_stmt (TB_OUT_FILE, head, 0);
486               fprintf (TB_OUT_FILE, "\n");
487             }
488           else
489             TB_WF;
490           break;
491
492         case TB_SEARCH_NAME:
493
494           break;
495
496         case TB_SEARCH_CODE:
497           {
498             enum tree_code code;
499             char *arg_text;
500
501             arg_text = strchr (input, ' ');
502             if (arg_text == NULL)
503               {
504                 fprintf (TB_OUT_FILE, "First argument is missing.  This isn't a valid search command.  \n");
505                 break;
506               }
507             code = TB_get_tree_code (arg_text + 1);
508
509             /* Search in the subtree a node with the given code.  */
510             {
511               tree res;
512
513               res = walk_tree (&head, find_node_with_code, &code, NULL);
514               if (res == NULL_TREE)
515                 {
516                   fprintf (TB_OUT_FILE, "There's no node with this code (reachable via the walk_tree function from this node).\n");
517                 }
518               else
519                 {
520                   fprintf (TB_OUT_FILE, "Achoo!  I got this node in the tree.\n");
521                   TB_SET_HEAD (res);
522                 }
523             }
524             break;
525           }
526
527 #define TB_MOVE_HEAD(FCT) do {       \
528   if (head)                          \
529     {                                \
530       tree t;                        \
531       t = FCT (head);                \
532       if (t)                         \
533         TB_SET_HEAD (t);             \
534       else                           \
535         TB_WF;                       \
536     }                                \
537   else                               \
538     TB_WF;                           \
539 } while (0)
540
541         case TB_FIRST:
542           TB_MOVE_HEAD (TB_first_in_bind);
543           break;
544
545         case TB_LAST:
546           TB_MOVE_HEAD (TB_last_in_bind);
547           break;
548
549         case TB_UP:
550           TB_MOVE_HEAD (TB_up_expr);
551           break;
552
553         case TB_PREV:
554           TB_MOVE_HEAD (TB_prev_expr);
555           break;
556
557         case TB_NEXT:
558           TB_MOVE_HEAD (TB_next_expr);
559           break;
560
561         case TB_HPREV:
562           /* This command is a little bit special, since it deals with history
563              stack.  For this reason it should keep the "head = ..." statement
564              and not use TB_MOVE_HEAD.  */
565           if (head)
566             {
567               tree t;
568               t = TB_history_prev ();
569               if (t)
570                 {
571                   head = t;
572                   if (TB_verbose)
573                     {
574                       print_generic_expr (TB_OUT_FILE, head, 0);
575                       fprintf (TB_OUT_FILE, "\n");
576                     }
577                 }
578               else
579                 TB_WF;
580             }
581           else
582             TB_WF;
583           break;
584
585         case TB_CHAIN:
586           /* Don't go further if it's the last node in this chain.  */
587           if (head && TREE_CODE (head) == BLOCK)
588             TB_SET_HEAD (BLOCK_CHAIN (head));
589           else if (head && TREE_CHAIN (head))
590             TB_SET_HEAD (TREE_CHAIN (head));
591           else
592             TB_WF;
593           break;
594
595         case TB_FUN:
596           /* Go up to the current function declaration.  */
597           TB_SET_HEAD (current_function_decl);
598           fprintf (TB_OUT_FILE, "Current function declaration.\n");
599           break;
600
601         case TB_HELP:
602           /* Display a help message.  */
603           {
604             int i;
605             fprintf (TB_OUT_FILE, "Possible commands are:\n\n");
606             for (i = 0; i < TB_UNUSED_COMMAND; i++)
607               {
608                 fprintf (TB_OUT_FILE, "%20s  -  %s\n", TB_COMMAND_TEXT (i), TB_COMMAND_HELP (i));
609               }
610           }
611           break;
612
613         case TB_VERBOSE:
614           if (TB_verbose == 0)
615             {
616               TB_verbose = 1;
617               fprintf (TB_OUT_FILE, "Verbose on.\n");
618             }
619           else
620             {
621               TB_verbose = 0;
622               fprintf (TB_OUT_FILE, "Verbose off.\n");
623             }
624           break;
625
626         case TB_EXIT:
627         case TB_QUIT:
628           /* Just exit from this function.  */
629           goto ret;
630
631         default:
632           TB_NIY;
633         }
634     }
635
636  ret:;
637   htab_delete (TB_up_ht);
638   return;
639 }
640
641
642 /* Search the first node in this BIND_EXPR.  */
643
644 static tree
645 TB_first_in_bind (tree node)
646 {
647   tree t;
648
649   if (node == NULL_TREE)
650     return NULL_TREE;
651
652   while ((t = TB_prev_expr (node)))
653     node = t;
654
655   return node;
656 }
657
658 /* Search the last node in this BIND_EXPR.  */
659
660 static tree
661 TB_last_in_bind (tree node)
662 {
663   tree t;
664
665   if (node == NULL_TREE)
666     return NULL_TREE;
667
668   while ((t = TB_next_expr (node)))
669     node = t;
670
671   return node;
672 }
673
674 /* Search the parent expression for this node.  */
675
676 static tree
677 TB_up_expr (tree node)
678 {
679   tree res;
680   if (node == NULL_TREE)
681     return NULL_TREE;
682
683   res = (tree) htab_find (TB_up_ht, node);
684   return res;
685 }
686
687 /* Search the previous expression in this BIND_EXPR.  */
688
689 static tree
690 TB_prev_expr (tree node)
691 {
692   node = TB_current_chain_node (node);
693
694   if (node == NULL_TREE)
695     return NULL_TREE;
696
697   node = TB_up_expr (node);
698   if (node && TREE_CODE (node) == COMPOUND_EXPR)
699     return node;
700   else
701     return NULL_TREE;
702 }
703
704 /* Search the next expression in this BIND_EXPR.  */
705
706 static tree
707 TB_next_expr (tree node)
708 {
709   node = TB_current_chain_node (node);
710
711   if (node == NULL_TREE)
712     return NULL_TREE;
713
714   node = TREE_OPERAND (node, 1);
715   return node;
716 }
717
718 static tree
719 TB_current_chain_node (tree node)
720 {
721   if (node == NULL_TREE)
722     return NULL_TREE;
723
724   if (TREE_CODE (node) == COMPOUND_EXPR)
725     return node;
726
727   node = TB_up_expr (node);
728   if (node)
729     {
730       if (TREE_CODE (node) == COMPOUND_EXPR)
731         return node;
732
733       node = TB_up_expr (node);
734       if (TREE_CODE (node) == COMPOUND_EXPR)
735         return node;
736     }
737
738   return NULL_TREE;
739 }
740
741 /* For each node store in its children nodes that the current node is their
742    parent.  This function is used by walk_tree.  */
743
744 static tree
745 store_child_info (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
746                   void *data ATTRIBUTE_UNUSED)
747 {
748   tree node;
749   void **slot;
750
751   node = *tp;
752
753   /* 'node' is the parent of 'TREE_OPERAND (node, *)'.  */
754   if (TREE_CODE_CLASS (TREE_CODE (node)) == 'e')
755     {
756
757 #define STORE_CHILD(N) do {                                                \
758   tree op = TREE_OPERAND (node, N);                                        \
759   slot = htab_find_slot (TB_up_ht, op, INSERT);                               \
760   *slot = (void *) node;                                                   \
761 } while (0)
762
763       switch (TREE_CODE_LENGTH (TREE_CODE (node)))
764         {
765         case 4:
766           STORE_CHILD (0);
767           STORE_CHILD (1);
768           STORE_CHILD (2);
769           STORE_CHILD (3);
770           break;
771
772         case 3:
773           STORE_CHILD (0);
774           STORE_CHILD (1);
775           STORE_CHILD (2);
776           break;
777
778         case 2:
779           STORE_CHILD (0);
780           STORE_CHILD (1);
781           break;
782
783         case 1:
784           STORE_CHILD (0);
785           break;
786
787         case 0:
788         default:
789           /* No children: nothing to do.  */
790           break;
791         }
792 #undef STORE_CHILD
793     }
794
795   /* Never stop walk_tree.  */
796   return NULL_TREE;
797 }
798
799 /* Function used in TB_up_ht.  */
800
801 static int
802 TB_parent_eq (const void *p1, const void *p2)
803 {
804   tree node, parent;
805   node = (tree) p2;
806   parent = (tree) p1;
807
808   if (p1 == NULL || p2 == NULL)
809     return 0;
810
811   if (TREE_CODE_CLASS(TREE_CODE(parent)) == 'e')
812     {
813
814 #define TEST_CHILD(N) do {               \
815   if (node == TREE_OPERAND (parent, N))  \
816     return 1;                            \
817 } while (0)
818
819     switch (TREE_CODE_LENGTH (TREE_CODE (parent)))
820       {
821       case 4:
822         TEST_CHILD (0);
823         TEST_CHILD (1);
824         TEST_CHILD (2);
825         TEST_CHILD (3);
826         break;
827
828       case 3:
829         TEST_CHILD (0);
830         TEST_CHILD (1);
831         TEST_CHILD (2);
832         break;
833
834       case 2:
835         TEST_CHILD (0);
836         TEST_CHILD (1);
837         break;
838
839       case 1:
840         TEST_CHILD (0);
841         break;
842
843       case 0:
844       default:
845         /* No children: nothing to do.  */
846         break;
847       }
848 #undef TEST_CHILD
849     }
850
851   return 0;
852 }
853
854 /* Update information about upper expressions in the hash table.  */
855
856 static void
857 TB_update_up (tree node)
858 {
859   while (node)
860     {
861       walk_tree (&node, store_child_info, NULL, NULL);
862
863       /* Walk function's body.  */
864       if (TREE_CODE (node) == FUNCTION_DECL)
865         if (DECL_SAVED_TREE (node))
866           walk_tree (&DECL_SAVED_TREE (node), store_child_info, NULL, NULL);
867
868       /* Walk rest of the chain.  */
869       node = TREE_CHAIN (node);
870     }
871   fprintf (TB_OUT_FILE, "Up/prev expressions updated.\n");
872 }
873
874 /* Parse the input string for determining the command the user asked for.  */
875
876 static TB_CODE
877 TB_get_command (char *input)
878 {
879   unsigned int mn, size_tok;
880   int comp;
881   char *space;
882
883   space = strchr (input, ' ');
884   if (space != NULL)
885     size_tok = strlen (input) - strlen (space);
886   else
887     size_tok = strlen (input) - 1;
888
889   for (mn = 0; mn < TB_UNUSED_COMMAND; mn++)
890     {
891       if (size_tok != TB_COMMAND_LEN (mn))
892         continue;
893
894       comp = memcmp (input, TB_COMMAND_TEXT (mn), TB_COMMAND_LEN (mn));
895       if (comp == 0)
896         /* Here we just determined the command.  If this command takes
897            an argument, then the argument is determined later.  */
898         return TB_COMMAND_CODE (mn);
899     }
900
901   /* Not a valid command.  */
902   return TB_UNUSED_COMMAND;
903 }
904
905 /* Parse the input string for determining the tree code.  */
906
907 static enum tree_code
908 TB_get_tree_code (char *input)
909 {
910   unsigned int mn, size_tok;
911   int comp;
912   char *space;
913
914   space = strchr (input, ' ');
915   if (space != NULL)
916     size_tok = strlen (input) - strlen (space);
917   else
918     size_tok = strlen (input) - 1;
919
920   for (mn = 0; mn < LAST_AND_UNUSED_TREE_CODE; mn++)
921     {
922       if (size_tok != TB_TREE_CODE_LEN (mn))
923         continue;
924
925       comp = memcmp (input, TB_TREE_CODE_TEXT (mn), TB_TREE_CODE_LEN (mn));
926       if (comp == 0)
927         {
928           fprintf (TB_OUT_FILE, "%s\n", TB_TREE_CODE_TEXT (mn));
929           return TB_TREE_CODE (mn);
930         }
931     }
932
933   /* This isn't a valid code.  */
934   return LAST_AND_UNUSED_TREE_CODE;
935 }
936
937 /* Find a node with a given code.  This function is used as an argument to
938    walk_tree.  */
939
940 static tree
941 find_node_with_code (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
942                      void *data)
943 {
944   enum tree_code *code;
945   code = (enum tree_code *) data;
946   if (*code == TREE_CODE (*tp))
947     return *tp;
948
949   return NULL_TREE;
950 }
951
952 /* Returns a pointer to the last visited node.  */
953
954 static tree
955 TB_history_prev (void)
956 {
957   if (TB_history_stack)
958     {
959       TB_history_stack = TREE_CHAIN (TB_history_stack);
960       if (TB_history_stack)
961         return TREE_VALUE (TB_history_stack);
962     }
963   return NULL_TREE;
964 }
965
966 /* Read up to (and including) a '\n' from STREAM into *LINEPTR
967    (and null-terminate it). *LINEPTR is a pointer returned from malloc
968    (or NULL), pointing to *N characters of space.  It is realloc'd as
969    necessary.  Returns the number of characters read (not including the
970    null terminator), or -1 on error or EOF.
971    This function comes from sed (and is supposed to be a portable version
972    of getline).  */
973
974 static long
975 TB_getline (char **lineptr, long *n, FILE *stream)
976 {
977   char *line, *p;
978   long size, copy;
979
980   if (lineptr == NULL || n == NULL)
981     {
982       errno = EINVAL;
983       return -1;
984     }
985
986   if (ferror (stream))
987     return -1;
988
989   /* Make sure we have a line buffer to start with.  */
990   if (*lineptr == NULL || *n < 2) /* !seen and no buf yet need 2 chars.  */
991     {
992 #ifndef MAX_CANON
993 #define MAX_CANON       256
994 #endif
995       line = (char *) xrealloc (*lineptr, MAX_CANON);
996       if (line == NULL)
997         return -1;
998       *lineptr = line;
999       *n = MAX_CANON;
1000     }
1001
1002   line = *lineptr;
1003   size = *n;
1004
1005   copy = size;
1006   p = line;
1007
1008   while (1)
1009     {
1010       long len;
1011
1012       while (--copy > 0)
1013         {
1014           register int c = getc (stream);
1015           if (c == EOF)
1016             goto lose;
1017           else if ((*p++ = c) == '\n')
1018             goto win;
1019         }
1020
1021       /* Need to enlarge the line buffer.  */
1022       len = p - line;
1023       size *= 2;
1024       line = (char *) xrealloc (line, size);
1025       if (line == NULL)
1026         goto lose;
1027       *lineptr = line;
1028       *n = size;
1029       p = line + len;
1030       copy = size - len;
1031     }
1032
1033  lose:
1034   if (p == *lineptr)
1035     return -1;
1036
1037   /* Return a partial line since we got an error in the middle.  */
1038  win:
1039 #if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) || defined(MSDOS)
1040   if (p - 2 >= *lineptr && p[-2] == '\r')
1041     p[-2] = p[-1], --p;
1042 #endif
1043   *p = '\0';
1044   return p - *lineptr;
1045 }