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