OSDN Git Service

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