2015-03-24 Paolo Carlini <paolo.carlini@oracle.com>
[official-gcc.git] / gcc / tree-browser.c
blob70e93e6833d3168744a523bed51f7b4f6a06ac73
1 /* Tree browser.
2 Copyright (C) 2002-2015 Free Software Foundation, Inc.
3 Contributed by Sebastian Pop <s.pop@laposte.net>
5 This file is part of GCC.
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 3, or (at your option) any later
10 version.
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.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "hash-table.h"
25 #include "hash-set.h"
26 #include "machmode.h"
27 #include "vec.h"
28 #include "double-int.h"
29 #include "input.h"
30 #include "alias.h"
31 #include "symtab.h"
32 #include "options.h"
33 #include "wide-int.h"
34 #include "inchash.h"
35 #include "tree.h"
36 #include "tree-pretty-print.h"
37 #include "print-tree.h"
39 #define TB_OUT_FILE stdout
40 #define TB_IN_FILE stdin
41 #define TB_NIY fprintf (TB_OUT_FILE, "Sorry this command is not yet implemented.\n")
42 #define TB_WF fprintf (TB_OUT_FILE, "Warning, this command failed.\n")
44 /* Structures for handling Tree Browser's commands. */
45 #define DEFTBCODE(COMMAND, STRING, HELP) COMMAND,
46 enum TB_Comm_code {
47 #include "tree-browser.def"
48 TB_UNUSED_COMMAND
50 #undef DEFTBCODE
51 typedef enum TB_Comm_code TB_CODE;
53 struct tb_command {
54 const char *help_msg;
55 const char *comm_text;
56 size_t comm_len;
57 TB_CODE comm_code;
60 #define DEFTBCODE(code, str, help) { help, str, sizeof (str) - 1, code },
61 static const struct tb_command tb_commands[] =
63 #include "tree-browser.def"
65 #undef DEFTBCODE
67 #define TB_COMMAND_LEN(N) (tb_commands[N].comm_len)
68 #define TB_COMMAND_TEXT(N) (tb_commands[N].comm_text)
69 #define TB_COMMAND_CODE(N) (tb_commands[N].comm_code)
70 #define TB_COMMAND_HELP(N) (tb_commands[N].help_msg)
73 /* Next structure is for parsing TREE_CODEs. */
74 struct tb_tree_code {
75 enum tree_code code;
76 const char *code_string;
77 size_t code_string_len;
80 #define DEFTREECODE(SYM, STRING, TYPE, NARGS) { SYM, STRING, sizeof (STRING) - 1 },
81 #define END_OF_BASE_TREE_CODES \
82 { LAST_AND_UNUSED_TREE_CODE, "@dummy", sizeof ("@dummy") - 1 },
83 static const struct tb_tree_code tb_tree_codes[] =
85 #include "all-tree.def"
87 #undef DEFTREECODE
88 #undef END_OF_BASE_TREE_CODES
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)
95 /* Function declarations. */
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 tree TB_history_prev (void);
111 /* FIXME: To be declared in a .h file. */
112 void browse_tree (tree);
114 /* Hashtable helpers. */
115 struct tree_upper_hasher : pointer_hash<tree_node>
117 static inline bool equal (const value_type &, const compare_type &);
120 inline bool
121 tree_upper_hasher::equal (const value_type &parent, const compare_type &node)
123 if (parent == NULL || node == NULL)
124 return 0;
126 if (EXPR_P (parent))
128 int n = TREE_OPERAND_LENGTH (parent);
129 int i;
130 for (i = 0; i < n; i++)
131 if (node == TREE_OPERAND (parent, i))
132 return true;
134 return false;
137 /* Static variables. */
138 static hash_table<tree_upper_hasher> *TB_up_ht;
139 static vec<tree, va_gc> *TB_history_stack;
140 static int TB_verbose = 1;
143 /* Entry point in the Tree Browser. */
145 void
146 browse_tree (tree begin)
148 tree head;
149 TB_CODE tbc = TB_UNUSED_COMMAND;
150 ssize_t rd;
151 char *input = NULL;
152 long input_size = 0;
154 fprintf (TB_OUT_FILE, "\nTree Browser\n");
156 #define TB_SET_HEAD(N) do { \
157 vec_safe_push (TB_history_stack, N); \
158 head = N; \
159 if (TB_verbose) \
160 if (head) \
162 print_generic_expr (TB_OUT_FILE, head, 0); \
163 fprintf (TB_OUT_FILE, "\n"); \
165 } while (0)
167 TB_SET_HEAD (begin);
169 /* Store in a hashtable information about previous and upper statements. */
171 TB_up_ht = new hash_table<tree_upper_hasher> (1023);
172 TB_update_up (head);
175 while (24)
177 fprintf (TB_OUT_FILE, "TB> ");
178 rd = TB_getline (&input, &input_size, TB_IN_FILE);
180 if (rd == -1)
181 /* EOF. */
182 goto ret;
184 if (rd != 1)
185 /* Get a new command. Otherwise the user just pressed enter, and thus
186 she expects the last command to be reexecuted. */
187 tbc = TB_get_command (input);
189 switch (tbc)
191 case TB_UPDATE_UP:
192 TB_update_up (head);
193 break;
195 case TB_MAX:
196 if (head && (INTEGRAL_TYPE_P (head)
197 || TREE_CODE (head) == REAL_TYPE
198 || TREE_CODE (head) == FIXED_POINT_TYPE))
199 TB_SET_HEAD (TYPE_MAX_VALUE (head));
200 else
201 TB_WF;
202 break;
204 case TB_MIN:
205 if (head && (INTEGRAL_TYPE_P (head)
206 || TREE_CODE (head) == REAL_TYPE
207 || TREE_CODE (head) == FIXED_POINT_TYPE))
208 TB_SET_HEAD (TYPE_MIN_VALUE (head));
209 else
210 TB_WF;
211 break;
213 case TB_ELT:
214 if (head && TREE_CODE (head) == TREE_VEC)
216 /* This command takes another argument: the element number:
217 for example "elt 1". */
218 TB_NIY;
220 else if (head && TREE_CODE (head) == VECTOR_CST)
222 /* This command takes another argument: the element number:
223 for example "elt 1". */
224 TB_NIY;
226 else
227 TB_WF;
228 break;
230 case TB_VALUE:
231 if (head && TREE_CODE (head) == TREE_LIST)
232 TB_SET_HEAD (TREE_VALUE (head));
233 else
234 TB_WF;
235 break;
237 case TB_PURPOSE:
238 if (head && TREE_CODE (head) == TREE_LIST)
239 TB_SET_HEAD (TREE_PURPOSE (head));
240 else
241 TB_WF;
242 break;
244 case TB_IMAG:
245 if (head && TREE_CODE (head) == COMPLEX_CST)
246 TB_SET_HEAD (TREE_IMAGPART (head));
247 else
248 TB_WF;
249 break;
251 case TB_REAL:
252 if (head && TREE_CODE (head) == COMPLEX_CST)
253 TB_SET_HEAD (TREE_REALPART (head));
254 else
255 TB_WF;
256 break;
258 case TB_BLOCK:
259 if (head && TREE_CODE (head) == BIND_EXPR)
260 TB_SET_HEAD (TREE_OPERAND (head, 2));
261 else
262 TB_WF;
263 break;
265 case TB_SUBBLOCKS:
266 if (head && TREE_CODE (head) == BLOCK)
267 TB_SET_HEAD (BLOCK_SUBBLOCKS (head));
268 else
269 TB_WF;
270 break;
272 case TB_SUPERCONTEXT:
273 if (head && TREE_CODE (head) == BLOCK)
274 TB_SET_HEAD (BLOCK_SUPERCONTEXT (head));
275 else
276 TB_WF;
277 break;
279 case TB_VARS:
280 if (head && TREE_CODE (head) == BLOCK)
281 TB_SET_HEAD (BLOCK_VARS (head));
282 else if (head && TREE_CODE (head) == BIND_EXPR)
283 TB_SET_HEAD (TREE_OPERAND (head, 0));
284 else
285 TB_WF;
286 break;
288 case TB_REFERENCE_TO_THIS:
289 if (head && TYPE_P (head))
290 TB_SET_HEAD (TYPE_REFERENCE_TO (head));
291 else
292 TB_WF;
293 break;
295 case TB_POINTER_TO_THIS:
296 if (head && TYPE_P (head))
297 TB_SET_HEAD (TYPE_POINTER_TO (head));
298 else
299 TB_WF;
300 break;
302 case TB_BASETYPE:
303 if (head && TREE_CODE (head) == OFFSET_TYPE)
304 TB_SET_HEAD (TYPE_OFFSET_BASETYPE (head));
305 else
306 TB_WF;
307 break;
309 case TB_ARG_TYPES:
310 if (head && (TREE_CODE (head) == FUNCTION_TYPE
311 || TREE_CODE (head) == METHOD_TYPE))
312 TB_SET_HEAD (TYPE_ARG_TYPES (head));
313 else
314 TB_WF;
315 break;
317 case TB_METHOD_BASE_TYPE:
318 if (head && (TREE_CODE (head) == FUNCTION_TYPE
319 || TREE_CODE (head) == METHOD_TYPE)
320 && TYPE_METHOD_BASETYPE (head))
321 TB_SET_HEAD (TYPE_METHOD_BASETYPE (head));
322 else
323 TB_WF;
324 break;
326 case TB_FIELDS:
327 if (head && (TREE_CODE (head) == RECORD_TYPE
328 || TREE_CODE (head) == UNION_TYPE
329 || TREE_CODE (head) == QUAL_UNION_TYPE))
330 TB_SET_HEAD (TYPE_FIELDS (head));
331 else
332 TB_WF;
333 break;
335 case TB_DOMAIN:
336 if (head && TREE_CODE (head) == ARRAY_TYPE)
337 TB_SET_HEAD (TYPE_DOMAIN (head));
338 else
339 TB_WF;
340 break;
342 case TB_VALUES:
343 if (head && TREE_CODE (head) == ENUMERAL_TYPE)
344 TB_SET_HEAD (TYPE_VALUES (head));
345 else
346 TB_WF;
347 break;
349 case TB_ARG_TYPE:
350 if (head && TREE_CODE (head) == PARM_DECL)
351 TB_SET_HEAD (DECL_ARG_TYPE (head));
352 else
353 TB_WF;
354 break;
356 case TB_INITIAL:
357 if (head && DECL_P (head))
358 TB_SET_HEAD (DECL_INITIAL (head));
359 else
360 TB_WF;
361 break;
363 case TB_RESULT:
364 if (head && DECL_P (head))
365 TB_SET_HEAD (DECL_RESULT_FLD (head));
366 else
367 TB_WF;
368 break;
370 case TB_ARGUMENTS:
371 if (head && DECL_P (head))
372 TB_SET_HEAD (DECL_ARGUMENTS (head));
373 else
374 TB_WF;
375 break;
377 case TB_ABSTRACT_ORIGIN:
378 if (head && DECL_P (head))
379 TB_SET_HEAD (DECL_ABSTRACT_ORIGIN (head));
380 else if (head && TREE_CODE (head) == BLOCK)
381 TB_SET_HEAD (BLOCK_ABSTRACT_ORIGIN (head));
382 else
383 TB_WF;
384 break;
386 case TB_ATTRIBUTES:
387 if (head && DECL_P (head))
388 TB_SET_HEAD (DECL_ATTRIBUTES (head));
389 else if (head && TYPE_P (head))
390 TB_SET_HEAD (TYPE_ATTRIBUTES (head));
391 else
392 TB_WF;
393 break;
395 case TB_CONTEXT:
396 if (head && DECL_P (head))
397 TB_SET_HEAD (DECL_CONTEXT (head));
398 else if (head && TYPE_P (head)
399 && TYPE_CONTEXT (head))
400 TB_SET_HEAD (TYPE_CONTEXT (head));
401 else
402 TB_WF;
403 break;
405 case TB_OFFSET:
406 if (head && TREE_CODE (head) == FIELD_DECL)
407 TB_SET_HEAD (DECL_FIELD_OFFSET (head));
408 else
409 TB_WF;
410 break;
412 case TB_BIT_OFFSET:
413 if (head && TREE_CODE (head) == FIELD_DECL)
414 TB_SET_HEAD (DECL_FIELD_BIT_OFFSET (head));
415 else
416 TB_WF;
417 break;
419 case TB_UNIT_SIZE:
420 if (head && DECL_P (head))
421 TB_SET_HEAD (DECL_SIZE_UNIT (head));
422 else if (head && TYPE_P (head))
423 TB_SET_HEAD (TYPE_SIZE_UNIT (head));
424 else
425 TB_WF;
426 break;
428 case TB_SIZE:
429 if (head && DECL_P (head))
430 TB_SET_HEAD (DECL_SIZE (head));
431 else if (head && TYPE_P (head))
432 TB_SET_HEAD (TYPE_SIZE (head));
433 else
434 TB_WF;
435 break;
437 case TB_TYPE:
438 if (head && TREE_TYPE (head))
439 TB_SET_HEAD (TREE_TYPE (head));
440 else
441 TB_WF;
442 break;
444 case TB_DECL_SAVED_TREE:
445 if (head && TREE_CODE (head) == FUNCTION_DECL
446 && DECL_SAVED_TREE (head))
447 TB_SET_HEAD (DECL_SAVED_TREE (head));
448 else
449 TB_WF;
450 break;
452 case TB_BODY:
453 if (head && TREE_CODE (head) == BIND_EXPR)
454 TB_SET_HEAD (TREE_OPERAND (head, 1));
455 else
456 TB_WF;
457 break;
459 case TB_CHILD_0:
460 if (head && EXPR_P (head) && TREE_OPERAND (head, 0))
461 TB_SET_HEAD (TREE_OPERAND (head, 0));
462 else
463 TB_WF;
464 break;
466 case TB_CHILD_1:
467 if (head && EXPR_P (head) && TREE_OPERAND (head, 1))
468 TB_SET_HEAD (TREE_OPERAND (head, 1));
469 else
470 TB_WF;
471 break;
473 case TB_CHILD_2:
474 if (head && EXPR_P (head) && TREE_OPERAND (head, 2))
475 TB_SET_HEAD (TREE_OPERAND (head, 2));
476 else
477 TB_WF;
478 break;
480 case TB_CHILD_3:
481 if (head && EXPR_P (head) && TREE_OPERAND (head, 3))
482 TB_SET_HEAD (TREE_OPERAND (head, 3));
483 else
484 TB_WF;
485 break;
487 case TB_PRINT:
488 if (head)
489 debug_tree (head);
490 else
491 TB_WF;
492 break;
494 case TB_PRETTY_PRINT:
495 if (head)
497 print_generic_stmt (TB_OUT_FILE, head, 0);
498 fprintf (TB_OUT_FILE, "\n");
500 else
501 TB_WF;
502 break;
504 case TB_SEARCH_NAME:
506 break;
508 case TB_SEARCH_CODE:
510 enum tree_code code;
511 char *arg_text;
513 arg_text = strchr (input, ' ');
514 if (arg_text == NULL)
516 fprintf (TB_OUT_FILE, "First argument is missing. This isn't a valid search command. \n");
517 break;
519 code = TB_get_tree_code (arg_text + 1);
521 /* Search in the subtree a node with the given code. */
523 tree res;
525 res = walk_tree (&head, find_node_with_code, &code, NULL);
526 if (res == NULL_TREE)
528 fprintf (TB_OUT_FILE, "There's no node with this code (reachable via the walk_tree function from this node).\n");
530 else
532 fprintf (TB_OUT_FILE, "Achoo! I got this node in the tree.\n");
533 TB_SET_HEAD (res);
536 break;
539 #define TB_MOVE_HEAD(FCT) do { \
540 if (head) \
542 tree t; \
543 t = FCT (head); \
544 if (t) \
545 TB_SET_HEAD (t); \
546 else \
547 TB_WF; \
549 else \
550 TB_WF; \
551 } while (0)
553 case TB_FIRST:
554 TB_MOVE_HEAD (TB_first_in_bind);
555 break;
557 case TB_LAST:
558 TB_MOVE_HEAD (TB_last_in_bind);
559 break;
561 case TB_UP:
562 TB_MOVE_HEAD (TB_up_expr);
563 break;
565 case TB_PREV:
566 TB_MOVE_HEAD (TB_prev_expr);
567 break;
569 case TB_NEXT:
570 TB_MOVE_HEAD (TB_next_expr);
571 break;
573 case TB_HPREV:
574 /* This command is a little bit special, since it deals with history
575 stack. For this reason it should keep the "head = ..." statement
576 and not use TB_MOVE_HEAD. */
577 if (head)
579 tree t;
580 t = TB_history_prev ();
581 if (t)
583 head = t;
584 if (TB_verbose)
586 print_generic_expr (TB_OUT_FILE, head, 0);
587 fprintf (TB_OUT_FILE, "\n");
590 else
591 TB_WF;
593 else
594 TB_WF;
595 break;
597 case TB_CHAIN:
598 /* Don't go further if it's the last node in this chain. */
599 if (head && TREE_CODE (head) == BLOCK)
600 TB_SET_HEAD (BLOCK_CHAIN (head));
601 else if (head && TREE_CHAIN (head))
602 TB_SET_HEAD (TREE_CHAIN (head));
603 else
604 TB_WF;
605 break;
607 case TB_FUN:
608 /* Go up to the current function declaration. */
609 TB_SET_HEAD (current_function_decl);
610 fprintf (TB_OUT_FILE, "Current function declaration.\n");
611 break;
613 case TB_HELP:
614 /* Display a help message. */
616 int i;
617 fprintf (TB_OUT_FILE, "Possible commands are:\n\n");
618 for (i = 0; i < TB_UNUSED_COMMAND; i++)
620 fprintf (TB_OUT_FILE, "%20s - %s\n", TB_COMMAND_TEXT (i), TB_COMMAND_HELP (i));
623 break;
625 case TB_VERBOSE:
626 if (TB_verbose == 0)
628 TB_verbose = 1;
629 fprintf (TB_OUT_FILE, "Verbose on.\n");
631 else
633 TB_verbose = 0;
634 fprintf (TB_OUT_FILE, "Verbose off.\n");
636 break;
638 case TB_EXIT:
639 case TB_QUIT:
640 /* Just exit from this function. */
641 goto ret;
643 default:
644 TB_NIY;
648 ret:;
649 delete TB_up_ht;
650 TB_up_ht = NULL;
651 return;
655 /* Search the first node in this BIND_EXPR. */
657 static tree
658 TB_first_in_bind (tree node)
660 tree t;
662 if (node == NULL_TREE)
663 return NULL_TREE;
665 while ((t = TB_prev_expr (node)))
666 node = t;
668 return node;
671 /* Search the last node in this BIND_EXPR. */
673 static tree
674 TB_last_in_bind (tree node)
676 tree t;
678 if (node == NULL_TREE)
679 return NULL_TREE;
681 while ((t = TB_next_expr (node)))
682 node = t;
684 return node;
687 /* Search the parent expression for this node. */
689 static tree
690 TB_up_expr (tree node)
692 tree res;
693 if (node == NULL_TREE)
694 return NULL_TREE;
696 res = TB_up_ht->find (node);
697 return res;
700 /* Search the previous expression in this BIND_EXPR. */
702 static tree
703 TB_prev_expr (tree node)
705 node = TB_current_chain_node (node);
707 if (node == NULL_TREE)
708 return NULL_TREE;
710 node = TB_up_expr (node);
711 if (node && TREE_CODE (node) == COMPOUND_EXPR)
712 return node;
713 else
714 return NULL_TREE;
717 /* Search the next expression in this BIND_EXPR. */
719 static tree
720 TB_next_expr (tree node)
722 node = TB_current_chain_node (node);
724 if (node == NULL_TREE)
725 return NULL_TREE;
727 node = TREE_OPERAND (node, 1);
728 return node;
731 static tree
732 TB_current_chain_node (tree node)
734 if (node == NULL_TREE)
735 return NULL_TREE;
737 if (TREE_CODE (node) == COMPOUND_EXPR)
738 return node;
740 node = TB_up_expr (node);
741 if (node)
743 if (TREE_CODE (node) == COMPOUND_EXPR)
744 return node;
746 node = TB_up_expr (node);
747 if (TREE_CODE (node) == COMPOUND_EXPR)
748 return node;
751 return NULL_TREE;
754 /* For each node store in its children nodes that the current node is their
755 parent. This function is used by walk_tree. */
757 static tree
758 store_child_info (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
759 void *data ATTRIBUTE_UNUSED)
761 tree node;
762 tree_node **slot;
764 node = *tp;
766 /* 'node' is the parent of 'TREE_OPERAND (node, *)'. */
767 if (EXPR_P (node))
769 int n = TREE_OPERAND_LENGTH (node);
770 int i;
771 for (i = 0; i < n; i++)
773 tree op = TREE_OPERAND (node, i);
774 slot = TB_up_ht->find_slot (op, INSERT);
775 *slot = node;
779 /* Never stop walk_tree. */
780 return NULL_TREE;
783 /* Update information about upper expressions in the hash table. */
785 static void
786 TB_update_up (tree node)
788 while (node)
790 walk_tree (&node, store_child_info, NULL, NULL);
792 /* Walk function's body. */
793 if (TREE_CODE (node) == FUNCTION_DECL)
794 if (DECL_SAVED_TREE (node))
795 walk_tree (&DECL_SAVED_TREE (node), store_child_info, NULL, NULL);
797 /* Walk rest of the chain. */
798 node = TREE_CHAIN (node);
800 fprintf (TB_OUT_FILE, "Up/prev expressions updated.\n");
803 /* Parse the input string for determining the command the user asked for. */
805 static TB_CODE
806 TB_get_command (char *input)
808 unsigned int mn, size_tok;
809 int comp;
810 char *space;
812 space = strchr (input, ' ');
813 if (space != NULL)
814 size_tok = strlen (input) - strlen (space);
815 else
816 size_tok = strlen (input) - 1;
818 for (mn = 0; mn < TB_UNUSED_COMMAND; mn++)
820 if (size_tok != TB_COMMAND_LEN (mn))
821 continue;
823 comp = memcmp (input, TB_COMMAND_TEXT (mn), TB_COMMAND_LEN (mn));
824 if (comp == 0)
825 /* Here we just determined the command. If this command takes
826 an argument, then the argument is determined later. */
827 return TB_COMMAND_CODE (mn);
830 /* Not a valid command. */
831 return TB_UNUSED_COMMAND;
834 /* Parse the input string for determining the tree code. */
836 static enum tree_code
837 TB_get_tree_code (char *input)
839 unsigned int mn, size_tok;
840 int comp;
841 char *space;
843 space = strchr (input, ' ');
844 if (space != NULL)
845 size_tok = strlen (input) - strlen (space);
846 else
847 size_tok = strlen (input) - 1;
849 for (mn = 0; mn < LAST_AND_UNUSED_TREE_CODE; mn++)
851 if (size_tok != TB_TREE_CODE_LEN (mn))
852 continue;
854 comp = memcmp (input, TB_TREE_CODE_TEXT (mn), TB_TREE_CODE_LEN (mn));
855 if (comp == 0)
857 fprintf (TB_OUT_FILE, "%s\n", TB_TREE_CODE_TEXT (mn));
858 return TB_TREE_CODE (mn);
862 /* This isn't a valid code. */
863 return LAST_AND_UNUSED_TREE_CODE;
866 /* Find a node with a given code. This function is used as an argument to
867 walk_tree. */
869 static tree
870 find_node_with_code (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
871 void *data)
873 enum tree_code *code;
874 code = (enum tree_code *) data;
875 if (*code == TREE_CODE (*tp))
876 return *tp;
878 return NULL_TREE;
881 /* Returns a pointer to the last visited node. */
883 static tree
884 TB_history_prev (void)
886 if (!vec_safe_is_empty (TB_history_stack))
888 tree last = TB_history_stack->last ();
889 TB_history_stack->pop ();
890 return last;
892 return NULL_TREE;
895 /* Read up to (and including) a '\n' from STREAM into *LINEPTR
896 (and null-terminate it). *LINEPTR is a pointer returned from malloc
897 (or NULL), pointing to *N characters of space. It is realloc'd as
898 necessary. Returns the number of characters read (not including the
899 null terminator), or -1 on error or EOF.
900 This function comes from sed (and is supposed to be a portable version
901 of getline). */
903 static long
904 TB_getline (char **lineptr, long *n, FILE *stream)
906 char *line, *p;
907 long size, copy;
909 if (lineptr == NULL || n == NULL)
911 errno = EINVAL;
912 return -1;
915 if (ferror (stream))
916 return -1;
918 /* Make sure we have a line buffer to start with. */
919 if (*lineptr == NULL || *n < 2) /* !seen and no buf yet need 2 chars. */
921 #ifndef MAX_CANON
922 #define MAX_CANON 256
923 #endif
924 line = (char *) xrealloc (*lineptr, MAX_CANON);
925 if (line == NULL)
926 return -1;
927 *lineptr = line;
928 *n = MAX_CANON;
931 line = *lineptr;
932 size = *n;
934 copy = size;
935 p = line;
937 while (1)
939 long len;
941 while (--copy > 0)
943 register int c = getc (stream);
944 if (c == EOF)
945 goto lose;
946 else if ((*p++ = c) == '\n')
947 goto win;
950 /* Need to enlarge the line buffer. */
951 len = p - line;
952 size *= 2;
953 line = (char *) xrealloc (line, size);
954 if (line == NULL)
955 goto lose;
956 *lineptr = line;
957 *n = size;
958 p = line + len;
959 copy = size - len;
962 lose:
963 if (p == *lineptr)
964 return -1;
966 /* Return a partial line since we got an error in the middle. */
967 win:
968 #if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) || defined(MSDOS)
969 if (p - 2 >= *lineptr && p[-2] == '\r')
970 p[-2] = p[-1], --p;
971 #endif
972 *p = '\0';
973 return p - *lineptr;