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