06c4777d06e178eb3358131fa8b192f97506da29
[deliverable/binutils-gdb.git] / gdb / tui / tui-winsource.c
1 /* TUI display source/assembly window.
2
3 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006, 2007
4 Free Software Foundation, Inc.
5
6 Contributed by Hewlett-Packard Company.
7
8 This file is part of GDB.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 Boston, MA 02110-1301, USA. */
24
25 #include "defs.h"
26 #include <ctype.h>
27 #include "symtab.h"
28 #include "frame.h"
29 #include "breakpoint.h"
30 #include "value.h"
31 #include "source.h"
32
33 #include "tui/tui.h"
34 #include "tui/tui-data.h"
35 #include "tui/tui-stack.h"
36 #include "tui/tui-win.h"
37 #include "tui/tui-wingeneral.h"
38 #include "tui/tui-winsource.h"
39 #include "tui/tui-source.h"
40 #include "tui/tui-disasm.h"
41
42 #include "gdb_string.h"
43 #include "gdb_curses.h"
44 #include "gdb_assert.h"
45
46 /* Function to display the "main" routine. */
47 void
48 tui_display_main (void)
49 {
50 if ((tui_source_windows ())->count > 0)
51 {
52 CORE_ADDR addr;
53
54 addr = tui_get_begin_asm_address ();
55 if (addr != (CORE_ADDR) 0)
56 {
57 struct symtab_and_line sal;
58
59 tui_update_source_windows_with_addr (addr);
60 sal = find_pc_line (addr, 0);
61 if (sal.symtab)
62 tui_update_locator_filename (sal.symtab->filename);
63 else
64 tui_update_locator_filename ("??");
65 }
66 }
67 }
68
69
70
71 /* Function to display source in the source window. This function
72 initializes the horizontal scroll to 0. */
73 void
74 tui_update_source_window (struct tui_win_info *win_info,
75 struct symtab *s,
76 struct tui_line_or_address line_or_addr,
77 int noerror)
78 {
79 win_info->detail.source_info.horizontal_offset = 0;
80 tui_update_source_window_as_is (win_info, s, line_or_addr, noerror);
81
82 return;
83 }
84
85
86 /* Function to display source in the source/asm window. This function
87 shows the source as specified by the horizontal offset. */
88 void
89 tui_update_source_window_as_is (struct tui_win_info *win_info,
90 struct symtab *s,
91 struct tui_line_or_address line_or_addr,
92 int noerror)
93 {
94 enum tui_status ret;
95
96 if (win_info->generic.type == SRC_WIN)
97 ret = tui_set_source_content (s, line_or_addr.u.line_no, noerror);
98 else
99 ret = tui_set_disassem_content (line_or_addr.u.addr);
100
101 if (ret == TUI_FAILURE)
102 {
103 tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT);
104 tui_clear_exec_info_content (win_info);
105 }
106 else
107 {
108 tui_update_breakpoint_info (win_info, 0);
109 tui_show_source_content (win_info);
110 tui_update_exec_info (win_info);
111 if (win_info->generic.type == SRC_WIN)
112 {
113 struct symtab_and_line sal;
114
115 sal.line = line_or_addr.u.line_no +
116 (win_info->generic.content_size - 2);
117 sal.symtab = s;
118 set_current_source_symtab_and_line (&sal);
119 /* If the focus was in the asm win, put it in the src win if
120 we don't have a split layout. */
121 if (tui_win_with_focus () == TUI_DISASM_WIN
122 && tui_current_layout () != SRC_DISASSEM_COMMAND)
123 tui_set_win_focus_to (TUI_SRC_WIN);
124 }
125 }
126
127
128 return;
129 }
130
131
132 /* Function to ensure that the source and/or disassemly windows
133 reflect the input address. */
134 void
135 tui_update_source_windows_with_addr (CORE_ADDR addr)
136 {
137 if (addr != 0)
138 {
139 struct symtab_and_line sal;
140 struct tui_line_or_address l;
141
142 switch (tui_current_layout ())
143 {
144 case DISASSEM_COMMAND:
145 case DISASSEM_DATA_COMMAND:
146 tui_show_disassem (addr);
147 break;
148 case SRC_DISASSEM_COMMAND:
149 tui_show_disassem_and_update_source (addr);
150 break;
151 default:
152 sal = find_pc_line (addr, 0);
153 l.loa = LOA_LINE;
154 l.u.line_no = sal.line;
155 tui_show_symtab_source (sal.symtab, l, FALSE);
156 break;
157 }
158 }
159 else
160 {
161 int i;
162
163 for (i = 0; i < (tui_source_windows ())->count; i++)
164 {
165 struct tui_win_info *win_info = (tui_source_windows ())->list[i];
166
167 tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT);
168 tui_clear_exec_info_content (win_info);
169 }
170 }
171 }
172
173 /* Function to ensure that the source and/or disassemly windows
174 reflect the input address. */
175 void
176 tui_update_source_windows_with_line (struct symtab *s, int line)
177 {
178 CORE_ADDR pc;
179 struct tui_line_or_address l;
180
181 switch (tui_current_layout ())
182 {
183 case DISASSEM_COMMAND:
184 case DISASSEM_DATA_COMMAND:
185 find_line_pc (s, line, &pc);
186 tui_update_source_windows_with_addr (pc);
187 break;
188 default:
189 l.loa = LOA_LINE;
190 l.u.line_no = line;
191 tui_show_symtab_source (s, l, FALSE);
192 if (tui_current_layout () == SRC_DISASSEM_COMMAND)
193 {
194 find_line_pc (s, line, &pc);
195 tui_show_disassem (pc);
196 }
197 break;
198 }
199
200 return;
201 }
202
203 void
204 tui_clear_source_content (struct tui_win_info *win_info,
205 int display_prompt)
206 {
207 if (win_info != NULL)
208 {
209 int i;
210
211 win_info->generic.content_in_use = FALSE;
212 tui_erase_source_content (win_info, display_prompt);
213 for (i = 0; i < win_info->generic.content_size; i++)
214 {
215 struct tui_win_element *element =
216 (struct tui_win_element *) win_info->generic.content[i];
217 element->which_element.source.has_break = FALSE;
218 element->which_element.source.is_exec_point = FALSE;
219 }
220 }
221 }
222
223
224 void
225 tui_erase_source_content (struct tui_win_info *win_info,
226 int display_prompt)
227 {
228 int x_pos;
229 int half_width = (win_info->generic.width - 2) / 2;
230
231 if (win_info->generic.handle != (WINDOW *) NULL)
232 {
233 werase (win_info->generic.handle);
234 tui_check_and_display_highlight_if_needed (win_info);
235 if (display_prompt == EMPTY_SOURCE_PROMPT)
236 {
237 char *no_src_str;
238
239 if (win_info->generic.type == SRC_WIN)
240 no_src_str = NO_SRC_STRING;
241 else
242 no_src_str = NO_DISASSEM_STRING;
243 if (strlen (no_src_str) >= half_width)
244 x_pos = 1;
245 else
246 x_pos = half_width - strlen (no_src_str);
247 mvwaddstr (win_info->generic.handle,
248 (win_info->generic.height / 2),
249 x_pos,
250 no_src_str);
251
252 /* elz: Added this function call to set the real contents of
253 the window to what is on the screen, so that later calls
254 to refresh, do display the correct stuff, and not the old
255 image. */
256
257 tui_set_source_content_nil (win_info, no_src_str);
258 }
259 tui_refresh_win (&win_info->generic);
260 }
261 }
262
263
264 /* Redraw the complete line of a source or disassembly window. */
265 static void
266 tui_show_source_line (struct tui_win_info *win_info, int lineno)
267 {
268 struct tui_win_element *line;
269 int x, y;
270
271 line = (struct tui_win_element *) win_info->generic.content[lineno - 1];
272 if (line->which_element.source.is_exec_point)
273 wattron (win_info->generic.handle, A_STANDOUT);
274
275 mvwaddstr (win_info->generic.handle, lineno, 1,
276 line->which_element.source.line);
277 if (line->which_element.source.is_exec_point)
278 wattroff (win_info->generic.handle, A_STANDOUT);
279
280 /* Clear to end of line but stop before the border. */
281 getyx (win_info->generic.handle, y, x);
282 while (x + 1 < win_info->generic.width)
283 {
284 waddch (win_info->generic.handle, ' ');
285 getyx (win_info->generic.handle, y, x);
286 }
287 }
288
289 void
290 tui_show_source_content (struct tui_win_info *win_info)
291 {
292 if (win_info->generic.content_size > 0)
293 {
294 int lineno;
295
296 for (lineno = 1; lineno <= win_info->generic.content_size; lineno++)
297 tui_show_source_line (win_info, lineno);
298 }
299 else
300 tui_erase_source_content (win_info, TRUE);
301
302 tui_check_and_display_highlight_if_needed (win_info);
303 tui_refresh_win (&win_info->generic);
304 win_info->generic.content_in_use = TRUE;
305 }
306
307
308 /* Scroll the source forward or backward horizontally. */
309 void
310 tui_horizontal_source_scroll (struct tui_win_info *win_info,
311 enum tui_scroll_direction direction,
312 int num_to_scroll)
313 {
314 if (win_info->generic.content != NULL)
315 {
316 int offset;
317 struct symtab *s;
318 struct symtab_and_line cursal = get_current_source_symtab_and_line ();
319
320 if (cursal.symtab == (struct symtab *) NULL)
321 s = find_pc_symtab (get_frame_pc (get_selected_frame (NULL)));
322 else
323 s = cursal.symtab;
324
325 if (direction == LEFT_SCROLL)
326 offset = win_info->detail.source_info.horizontal_offset + num_to_scroll;
327 else
328 {
329 if ((offset =
330 win_info->detail.source_info.horizontal_offset - num_to_scroll) < 0)
331 offset = 0;
332 }
333 win_info->detail.source_info.horizontal_offset = offset;
334 tui_update_source_window_as_is (win_info, s,
335 ((struct tui_win_element *)
336 win_info->generic.content[0])->which_element.source.line_or_addr,
337 FALSE);
338 }
339
340 return;
341 }
342
343
344 /* Set or clear the has_break flag in the line whose line is
345 line_no. */
346
347 void
348 tui_set_is_exec_point_at (struct tui_line_or_address l,
349 struct tui_win_info *win_info)
350 {
351 int changed = 0;
352 int i;
353 tui_win_content content = (tui_win_content) win_info->generic.content;
354
355 i = 0;
356 while (i < win_info->generic.content_size)
357 {
358 int new_state;
359 struct tui_line_or_address content_loa =
360 content[i]->which_element.source.line_or_addr;
361
362 gdb_assert (l.loa == LOA_ADDRESS || l.loa == LOA_LINE);
363 gdb_assert (content_loa.loa == LOA_LINE
364 || content_loa.loa == LOA_ADDRESS);
365 if (content_loa.loa == l.loa
366 && ((l.loa == LOA_LINE && content_loa.u.line_no == l.u.line_no)
367 || (content_loa.u.addr == l.u.addr)))
368 new_state = TRUE;
369 else
370 new_state = FALSE;
371 if (new_state != content[i]->which_element.source.is_exec_point)
372 {
373 changed++;
374 content[i]->which_element.source.is_exec_point = new_state;
375 tui_show_source_line (win_info, i + 1);
376 }
377 i++;
378 }
379 if (changed)
380 tui_refresh_win (&win_info->generic);
381 }
382
383 /* Update the execution windows to show the active breakpoints.
384 This is called whenever a breakpoint is inserted, removed or
385 has its state changed. */
386 void
387 tui_update_all_breakpoint_info (void)
388 {
389 struct tui_list *list = tui_source_windows ();
390 int i;
391
392 for (i = 0; i < list->count; i++)
393 {
394 struct tui_win_info *win = list->list[i];
395
396 if (tui_update_breakpoint_info (win, FALSE))
397 {
398 tui_update_exec_info (win);
399 }
400 }
401 }
402
403
404 /* Scan the source window and the breakpoints to update the has_break
405 information for each line.
406
407 Returns 1 if something changed and the execution window must be
408 refreshed. */
409
410 int
411 tui_update_breakpoint_info (struct tui_win_info *win,
412 int current_only)
413 {
414 int i;
415 int need_refresh = 0;
416 struct tui_source_info *src = &win->detail.source_info;
417
418 for (i = 0; i < win->generic.content_size; i++)
419 {
420 struct breakpoint *bp;
421 extern struct breakpoint *breakpoint_chain;
422 int mode;
423 struct tui_source_element *line;
424
425 line = &((struct tui_win_element *) win->generic.content[i])->which_element.source;
426 if (current_only && !line->is_exec_point)
427 continue;
428
429 /* Scan each breakpoint to see if the current line has something to
430 do with it. Identify enable/disabled breakpoints as well as
431 those that we already hit. */
432 mode = 0;
433 for (bp = breakpoint_chain;
434 bp != (struct breakpoint *) NULL;
435 bp = bp->next)
436 {
437 gdb_assert (line->line_or_addr.loa == LOA_LINE
438 || line->line_or_addr.loa == LOA_ADDRESS);
439 if ((win == TUI_SRC_WIN
440 && bp->source_file
441 && (strcmp (src->filename, bp->source_file) == 0)
442 && line->line_or_addr.loa == LOA_LINE
443 && bp->line_number == line->line_or_addr.u.line_no)
444 || (win == TUI_DISASM_WIN
445 && line->line_or_addr.loa == LOA_ADDRESS
446 && bp->loc->address == line->line_or_addr.u.addr))
447 {
448 if (bp->enable_state == bp_disabled)
449 mode |= TUI_BP_DISABLED;
450 else
451 mode |= TUI_BP_ENABLED;
452 if (bp->hit_count)
453 mode |= TUI_BP_HIT;
454 if (bp->cond)
455 mode |= TUI_BP_CONDITIONAL;
456 if (bp->type == bp_hardware_breakpoint)
457 mode |= TUI_BP_HARDWARE;
458 }
459 }
460 if (line->has_break != mode)
461 {
462 line->has_break = mode;
463 need_refresh = 1;
464 }
465 }
466 return need_refresh;
467 }
468
469
470 /* Function to initialize the content of the execution info window,
471 based upon the input window which is either the source or
472 disassembly window. */
473 enum tui_status
474 tui_set_exec_info_content (struct tui_win_info *win_info)
475 {
476 enum tui_status ret = TUI_SUCCESS;
477
478 if (win_info->detail.source_info.execution_info != (struct tui_gen_win_info *) NULL)
479 {
480 struct tui_gen_win_info *exec_info_ptr = win_info->detail.source_info.execution_info;
481
482 if (exec_info_ptr->content == NULL)
483 exec_info_ptr->content =
484 (void **) tui_alloc_content (win_info->generic.height,
485 exec_info_ptr->type);
486 if (exec_info_ptr->content != NULL)
487 {
488 int i;
489
490 tui_update_breakpoint_info (win_info, 1);
491 for (i = 0; i < win_info->generic.content_size; i++)
492 {
493 struct tui_win_element *element;
494 struct tui_win_element *src_element;
495 int mode;
496
497 element = (struct tui_win_element *) exec_info_ptr->content[i];
498 src_element = (struct tui_win_element *) win_info->generic.content[i];
499
500 memset(element->which_element.simple_string, ' ',
501 sizeof(element->which_element.simple_string));
502 element->which_element.simple_string[TUI_EXECINFO_SIZE - 1] = 0;
503
504 /* Now update the exec info content based upon the state
505 of each line as indicated by the source content. */
506 mode = src_element->which_element.source.has_break;
507 if (mode & TUI_BP_HIT)
508 element->which_element.simple_string[TUI_BP_HIT_POS] =
509 (mode & TUI_BP_HARDWARE) ? 'H' : 'B';
510 else if (mode & (TUI_BP_ENABLED | TUI_BP_DISABLED))
511 element->which_element.simple_string[TUI_BP_HIT_POS] =
512 (mode & TUI_BP_HARDWARE) ? 'h' : 'b';
513
514 if (mode & TUI_BP_ENABLED)
515 element->which_element.simple_string[TUI_BP_BREAK_POS] = '+';
516 else if (mode & TUI_BP_DISABLED)
517 element->which_element.simple_string[TUI_BP_BREAK_POS] = '-';
518
519 if (src_element->which_element.source.is_exec_point)
520 element->which_element.simple_string[TUI_EXEC_POS] = '>';
521 }
522 exec_info_ptr->content_size = win_info->generic.content_size;
523 }
524 else
525 ret = TUI_FAILURE;
526 }
527
528 return ret;
529 }
530
531
532 void
533 tui_show_exec_info_content (struct tui_win_info *win_info)
534 {
535 struct tui_gen_win_info *exec_info = win_info->detail.source_info.execution_info;
536 int cur_line;
537
538 werase (exec_info->handle);
539 tui_refresh_win (exec_info);
540 for (cur_line = 1; (cur_line <= exec_info->content_size); cur_line++)
541 mvwaddstr (exec_info->handle,
542 cur_line,
543 0,
544 ((struct tui_win_element *)
545 exec_info->content[cur_line - 1])->which_element.simple_string);
546 tui_refresh_win (exec_info);
547 exec_info->content_in_use = TRUE;
548 }
549
550
551 void
552 tui_erase_exec_info_content (struct tui_win_info *win_info)
553 {
554 struct tui_gen_win_info *exec_info = win_info->detail.source_info.execution_info;
555
556 werase (exec_info->handle);
557 tui_refresh_win (exec_info);
558 }
559
560 void
561 tui_clear_exec_info_content (struct tui_win_info *win_info)
562 {
563 win_info->detail.source_info.execution_info->content_in_use = FALSE;
564 tui_erase_exec_info_content (win_info);
565
566 return;
567 }
568
569 /* Function to update the execution info window. */
570 void
571 tui_update_exec_info (struct tui_win_info *win_info)
572 {
573 tui_set_exec_info_content (win_info);
574 tui_show_exec_info_content (win_info);
575 }
576
577 enum tui_status
578 tui_alloc_source_buffer (struct tui_win_info *win_info)
579 {
580 char *src_line_buf;
581 int i, line_width, max_lines;
582
583 max_lines = win_info->generic.height; /* Less the highlight box. */
584 line_width = win_info->generic.width - 1;
585 /*
586 * Allocate the buffer for the source lines. Do this only once
587 * since they will be re-used for all source displays. The only
588 * other time this will be done is when a window's size changes.
589 */
590 if (win_info->generic.content == NULL)
591 {
592 src_line_buf = (char *)
593 xmalloc ((max_lines * line_width) * sizeof (char));
594 if (src_line_buf == (char *) NULL)
595 {
596 fputs_unfiltered ("Unable to Allocate Memory for Source or Disassembly Display.\n",
597 gdb_stderr);
598 return TUI_FAILURE;
599 }
600 /* Allocate the content list. */
601 if ((win_info->generic.content =
602 (void **) tui_alloc_content (max_lines, SRC_WIN)) == NULL)
603 {
604 xfree (src_line_buf);
605 fputs_unfiltered ("Unable to Allocate Memory for Source or Disassembly Display.\n",
606 gdb_stderr);
607 return TUI_FAILURE;
608 }
609 for (i = 0; i < max_lines; i++)
610 ((struct tui_win_element *)
611 win_info->generic.content[i])->which_element.source.line =
612 src_line_buf + (line_width * i);
613 }
614
615 return TUI_SUCCESS;
616 }
617
618
619 /* Answer whether the a particular line number or address is displayed
620 in the current source window. */
621 int
622 tui_line_is_displayed (int line,
623 struct tui_win_info *win_info,
624 int check_threshold)
625 {
626 int is_displayed = FALSE;
627 int i, threshold;
628
629 if (check_threshold)
630 threshold = SCROLL_THRESHOLD;
631 else
632 threshold = 0;
633 i = 0;
634 while (i < win_info->generic.content_size - threshold
635 && !is_displayed)
636 {
637 is_displayed = (((struct tui_win_element *)
638 win_info->generic.content[i])->which_element.source.line_or_addr.loa
639 == LOA_LINE)
640 && (((struct tui_win_element *)
641 win_info->generic.content[i])->which_element.source.line_or_addr.u.line_no
642 == (int) line);
643 i++;
644 }
645
646 return is_displayed;
647 }
648
649
650 /* Answer whether the a particular line number or address is displayed
651 in the current source window. */
652 int
653 tui_addr_is_displayed (CORE_ADDR addr,
654 struct tui_win_info *win_info,
655 int check_threshold)
656 {
657 int is_displayed = FALSE;
658 int i, threshold;
659
660 if (check_threshold)
661 threshold = SCROLL_THRESHOLD;
662 else
663 threshold = 0;
664 i = 0;
665 while (i < win_info->generic.content_size - threshold
666 && !is_displayed)
667 {
668 is_displayed = (((struct tui_win_element *)
669 win_info->generic.content[i])->which_element.source.line_or_addr.loa
670 == LOA_ADDRESS)
671 && (((struct tui_win_element *)
672 win_info->generic.content[i])->which_element.source.line_or_addr.u.addr
673 == addr);
674 i++;
675 }
676
677 return is_displayed;
678 }
679
680
681 /*****************************************
682 ** STATIC LOCAL FUNCTIONS **
683 ******************************************/
This page took 0.053536 seconds and 4 git commands to generate.