1 /* Tree browser.
2    Copyright (C) 2002, 2003, 2004, 2007, 2008, 2010
3    Free Software Foundation, Inc.
4    Contributed by Sebastian Pop <s.pop@laposte.net>
5 
6 This file is part of GCC.
7 
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
12 
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3.  If not see
20 <http://www.gnu.org/licenses/>.  */
21 
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tree.h"
26 #include "tree-pretty-print.h"
27 
28 #define TB_OUT_FILE stdout
29 #define TB_IN_FILE stdin
30 #define TB_NIY fprintf (TB_OUT_FILE, "Sorry this command is not yet implemented.\n")
31 #define TB_WF fprintf (TB_OUT_FILE, "Warning, this command failed.\n")
32 
33 /* Structures for handling Tree Browser's commands.  */
34 #define DEFTBCODE(COMMAND, STRING, HELP)   COMMAND,
35 enum TB_Comm_code {
36 #include "tree-browser.def"
37   TB_UNUSED_COMMAND
38 };
39 #undef DEFTBCODE
40 typedef enum TB_Comm_code TB_CODE;
41 
42 struct tb_command {
43   const char *help_msg;
44   const char *comm_text;
45   size_t comm_len;
46   TB_CODE comm_code;
47 };
48 
49 #define DEFTBCODE(code, str, help) { help, str, sizeof(str) - 1, code },
50 static const struct tb_command tb_commands[] =
51 {
52 #include "tree-browser.def"
53 };
54 #undef DEFTBCODE
55 
56 #define TB_COMMAND_LEN(N) (tb_commands[N].comm_len)
57 #define TB_COMMAND_TEXT(N) (tb_commands[N].comm_text)
58 #define TB_COMMAND_CODE(N) (tb_commands[N].comm_code)
59 #define TB_COMMAND_HELP(N) (tb_commands[N].help_msg)
60 
61 
62 /* Next structure is for parsing TREE_CODEs.  */
63 struct tb_tree_code {
64   enum tree_code code;
65   const char *code_string;
66   size_t code_string_len;
67 };
68 
69 #define DEFTREECODE(SYM, STRING, TYPE, NARGS) { SYM, STRING, sizeof (STRING) - 1 },
70 #define END_OF_BASE_TREE_CODES \
71   { LAST_AND_UNUSED_TREE_CODE, "@dummy", sizeof ("@dummy") - 1 },
72 static const struct tb_tree_code tb_tree_codes[] =
73 {
74 #include "all-tree.def"
75 };
76 #undef DEFTREECODE
77 #undef END_OF_BASE_TREE_CODES
78 
79 #define TB_TREE_CODE(N) (tb_tree_codes[N].code)
80 #define TB_TREE_CODE_TEXT(N) (tb_tree_codes[N].code_string)
81 #define TB_TREE_CODE_LEN(N) (tb_tree_codes[N].code_string_len)
82 
83 
84 /* Function declarations.  */
85 
86 static long TB_getline (char **, long *, FILE *);
87 static TB_CODE TB_get_command (char *);
88 static enum tree_code TB_get_tree_code (char *);
89 static tree find_node_with_code (tree *, int *, void *);
90 static tree store_child_info (tree *, int *, void *);
91 static void TB_update_up (tree);
92 static tree TB_current_chain_node (tree);
93 static tree TB_prev_expr (tree);
94 static tree TB_next_expr (tree);
95 static tree TB_up_expr (tree);
96 static tree TB_first_in_bind (tree);
97 static tree TB_last_in_bind (tree);
98 static int  TB_parent_eq (const void *, const void *);
99 static tree TB_history_prev (void);
100 
101 /* FIXME: To be declared in a .h file.  */
102 void browse_tree (tree);
103 
104 /* Static variables.  */
105 static htab_t TB_up_ht;
106 static VEC(tree,gc) *TB_history_stack;
107 static int TB_verbose = 1;
108 
109 
110 /* Entry point in the Tree Browser.  */
111 
112 void
113 browse_tree (tree begin)
114 {
115   tree head;
116   TB_CODE tbc = TB_UNUSED_COMMAND;
117   ssize_t rd;
118   char *input = NULL;
119   long input_size = 0;
120 
121   fprintf (TB_OUT_FILE, "\nTree Browser\n");
122 
123 #define TB_SET_HEAD(N) do {                                           \
124   VEC_safe_push (tree, gc, TB_history_stack, N);                      \
125   head = N;                                                           \
126   if (TB_verbose)                                                     \
127     if (head)                                                         \
128       {                                                               \
129 	print_generic_expr (TB_OUT_FILE, head, 0);                    \
130 	fprintf (TB_OUT_FILE, "\n");                                  \
131       }                                                               \
132 } while (0)
133 
134   TB_SET_HEAD (begin);
135 
136   /* Store in a hashtable information about previous and upper statements.  */
137   {
138     TB_up_ht = htab_create (1023, htab_hash_pointer, &TB_parent_eq, NULL);
139     TB_update_up (head);
140   }
141 
142   while (24)
143     {
144       fprintf (TB_OUT_FILE, "TB> ");
145       rd = TB_getline (&input, &input_size, TB_IN_FILE);
146 
147       if (rd == -1)
148 	/* EOF.  */
149 	goto ret;
150 
151       if (rd != 1)
152 	/* Get a new command.  Otherwise the user just pressed enter, and thus
153 	   she expects the last command to be reexecuted.  */
154 	tbc = TB_get_command (input);
155 
156       switch (tbc)
157 	{
158 	case TB_UPDATE_UP:
159 	  TB_update_up (head);
160 	  break;
161 
162 	case TB_MAX:
163 	  if (head && (INTEGRAL_TYPE_P (head)
164 		       || TREE_CODE (head) == REAL_TYPE
165 		       || TREE_CODE (head) == FIXED_POINT_TYPE))
166 	    TB_SET_HEAD (TYPE_MAX_VALUE (head));
167 	  else
168 	    TB_WF;
169 	  break;
170 
171 	case TB_MIN:
172 	  if (head && (INTEGRAL_TYPE_P (head)
173 		       || TREE_CODE (head) == REAL_TYPE
174 		       || TREE_CODE (head) == FIXED_POINT_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 (EXPR_P (node))
734     {
735       int n = TREE_OPERAND_LENGTH (node);
736       int i;
737       for (i = 0; i < n; i++)
738 	{
739 	  tree op = TREE_OPERAND (node, i);
740 	  slot = htab_find_slot (TB_up_ht, op, INSERT);
741 	  *slot = (void *) node;
742 	}
743     }
744 
745   /* Never stop walk_tree.  */
746   return NULL_TREE;
747 }
748 
749 /* Function used in TB_up_ht.  */
750 
751 static int
752 TB_parent_eq (const void *p1, const void *p2)
753 {
754   const_tree const node = (const_tree)p2;
755   const_tree const parent = (const_tree) p1;
756 
757   if (p1 == NULL || p2 == NULL)
758     return 0;
759 
760   if (EXPR_P (parent))
761     {
762       int n = TREE_OPERAND_LENGTH (parent);
763       int i;
764       for (i = 0; i < n; i++)
765 	if (node == TREE_OPERAND (parent, i))
766 	  return 1;
767     }
768   return 0;
769 }
770 
771 /* Update information about upper expressions in the hash table.  */
772 
773 static void
774 TB_update_up (tree node)
775 {
776   while (node)
777     {
778       walk_tree (&node, store_child_info, NULL, NULL);
779 
780       /* Walk function's body.  */
781       if (TREE_CODE (node) == FUNCTION_DECL)
782         if (DECL_SAVED_TREE (node))
783           walk_tree (&DECL_SAVED_TREE (node), store_child_info, NULL, NULL);
784 
785       /* Walk rest of the chain.  */
786       node = TREE_CHAIN (node);
787     }
788   fprintf (TB_OUT_FILE, "Up/prev expressions updated.\n");
789 }
790 
791 /* Parse the input string for determining the command the user asked for.  */
792 
793 static TB_CODE
794 TB_get_command (char *input)
795 {
796   unsigned int mn, size_tok;
797   int comp;
798   char *space;
799 
800   space = strchr (input, ' ');
801   if (space != NULL)
802     size_tok = strlen (input) - strlen (space);
803   else
804     size_tok = strlen (input) - 1;
805 
806   for (mn = 0; mn < TB_UNUSED_COMMAND; mn++)
807     {
808       if (size_tok != TB_COMMAND_LEN (mn))
809 	continue;
810 
811       comp = memcmp (input, TB_COMMAND_TEXT (mn), TB_COMMAND_LEN (mn));
812       if (comp == 0)
813 	/* Here we just determined the command.  If this command takes
814 	   an argument, then the argument is determined later.  */
815 	return TB_COMMAND_CODE (mn);
816     }
817 
818   /* Not a valid command.  */
819   return TB_UNUSED_COMMAND;
820 }
821 
822 /* Parse the input string for determining the tree code.  */
823 
824 static enum tree_code
825 TB_get_tree_code (char *input)
826 {
827   unsigned int mn, size_tok;
828   int comp;
829   char *space;
830 
831   space = strchr (input, ' ');
832   if (space != NULL)
833     size_tok = strlen (input) - strlen (space);
834   else
835     size_tok = strlen (input) - 1;
836 
837   for (mn = 0; mn < LAST_AND_UNUSED_TREE_CODE; mn++)
838     {
839       if (size_tok != TB_TREE_CODE_LEN (mn))
840 	continue;
841 
842       comp = memcmp (input, TB_TREE_CODE_TEXT (mn), TB_TREE_CODE_LEN (mn));
843       if (comp == 0)
844 	{
845 	  fprintf (TB_OUT_FILE, "%s\n", TB_TREE_CODE_TEXT (mn));
846 	  return TB_TREE_CODE (mn);
847 	}
848     }
849 
850   /* This isn't a valid code.  */
851   return LAST_AND_UNUSED_TREE_CODE;
852 }
853 
854 /* Find a node with a given code.  This function is used as an argument to
855    walk_tree.  */
856 
857 static tree
858 find_node_with_code (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
859 		     void *data)
860 {
861   enum tree_code *code;
862   code = (enum tree_code *) data;
863   if (*code == TREE_CODE (*tp))
864     return *tp;
865 
866   return NULL_TREE;
867 }
868 
869 /* Returns a pointer to the last visited node.  */
870 
871 static tree
872 TB_history_prev (void)
873 {
874   if (!VEC_empty (tree, TB_history_stack))
875     {
876       tree last = VEC_last (tree, TB_history_stack);
877       VEC_pop (tree, TB_history_stack);
878       return last;
879     }
880   return NULL_TREE;
881 }
882 
883 /* Read up to (and including) a '\n' from STREAM into *LINEPTR
884    (and null-terminate it). *LINEPTR is a pointer returned from malloc
885    (or NULL), pointing to *N characters of space.  It is realloc'd as
886    necessary.  Returns the number of characters read (not including the
887    null terminator), or -1 on error or EOF.
888    This function comes from sed (and is supposed to be a portable version
889    of getline).  */
890 
891 static long
892 TB_getline (char **lineptr, long *n, FILE *stream)
893 {
894   char *line, *p;
895   long size, copy;
896 
897   if (lineptr == NULL || n == NULL)
898     {
899       errno = EINVAL;
900       return -1;
901     }
902 
903   if (ferror (stream))
904     return -1;
905 
906   /* Make sure we have a line buffer to start with.  */
907   if (*lineptr == NULL || *n < 2) /* !seen and no buf yet need 2 chars.  */
908     {
909 #ifndef MAX_CANON
910 #define MAX_CANON       256
911 #endif
912       line = (char *) xrealloc (*lineptr, MAX_CANON);
913       if (line == NULL)
914         return -1;
915       *lineptr = line;
916       *n = MAX_CANON;
917     }
918 
919   line = *lineptr;
920   size = *n;
921 
922   copy = size;
923   p = line;
924 
925   while (1)
926     {
927       long len;
928 
929       while (--copy > 0)
930         {
931           register int c = getc (stream);
932           if (c == EOF)
933             goto lose;
934           else if ((*p++ = c) == '\n')
935             goto win;
936         }
937 
938       /* Need to enlarge the line buffer.  */
939       len = p - line;
940       size *= 2;
941       line = (char *) xrealloc (line, size);
942       if (line == NULL)
943         goto lose;
944       *lineptr = line;
945       *n = size;
946       p = line + len;
947       copy = size - len;
948     }
949 
950  lose:
951   if (p == *lineptr)
952     return -1;
953 
954   /* Return a partial line since we got an error in the middle.  */
955  win:
956 #if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) || defined(MSDOS)
957   if (p - 2 >= *lineptr && p[-2] == '\r')
958     p[-2] = p[-1], --p;
959 #endif
960   *p = '\0';
961   return p - *lineptr;
962 }
963