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