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