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