* config/tc-arm.c (arm_cpus): Add entry for ARM Cortex-M0.
[binutils-gdb.git] / gdb / tui / tui-winsource.c
blob158aa89cccd42f884616a4c648c3f6915447e94e
1 /* TUI display source/assembly window.
3 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2008,
4 2009 Free Software Foundation, Inc.
6 Contributed by Hewlett-Packard Company.
8 This file is part of GDB.
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.
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.
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/>. */
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"
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"
40 #include "gdb_string.h"
41 #include "gdb_curses.h"
42 #include "gdb_assert.h"
44 /* Function to display the "main" routine. */
45 void
46 tui_display_main (void)
48 if ((tui_source_windows ())->count > 0)
50 CORE_ADDR addr;
52 addr = tui_get_begin_asm_address ();
53 if (addr != (CORE_ADDR) 0)
55 struct symtab_and_line sal;
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 ("??");
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)
77 win_info->detail.source_info.horizontal_offset = 0;
78 tui_update_source_window_as_is (win_info, s, line_or_addr, noerror);
80 return;
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)
92 enum tui_status ret;
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);
99 if (ret == TUI_FAILURE)
101 tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT);
102 tui_clear_exec_info_content (win_info);
104 else
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)
111 struct symtab_and_line sal;
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);
126 return;
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)
135 if (addr != 0)
137 struct symtab_and_line sal;
138 struct tui_line_or_address l;
140 switch (tui_current_layout ())
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;
157 else
159 int i;
161 for (i = 0; i < (tui_source_windows ())->count; i++)
163 struct tui_win_info *win_info = (tui_source_windows ())->list[i];
165 tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT);
166 tui_clear_exec_info_content (win_info);
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)
176 CORE_ADDR pc;
177 struct tui_line_or_address l;
179 switch (tui_current_layout ())
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)
192 find_line_pc (s, line, &pc);
193 tui_show_disassem (pc);
195 break;
198 return;
201 void
202 tui_clear_source_content (struct tui_win_info *win_info,
203 int display_prompt)
205 if (win_info != NULL)
207 int i;
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++)
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;
222 void
223 tui_erase_source_content (struct tui_win_info *win_info,
224 int display_prompt)
226 int x_pos;
227 int half_width = (win_info->generic.width - 2) / 2;
229 if (win_info->generic.handle != (WINDOW *) NULL)
231 werase (win_info->generic.handle);
232 tui_check_and_display_highlight_if_needed (win_info);
233 if (display_prompt == EMPTY_SOURCE_PROMPT)
235 char *no_src_str;
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);
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. */
255 tui_set_source_content_nil (win_info, no_src_str);
257 tui_refresh_win (&win_info->generic);
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)
266 struct tui_win_element *line;
267 int x, y;
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);
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);
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)
282 waddch (win_info->generic.handle, ' ');
283 getyx (win_info->generic.handle, y, x);
287 void
288 tui_show_source_content (struct tui_win_info *win_info)
290 if (win_info->generic.content_size > 0)
292 int lineno;
294 for (lineno = 1; lineno <= win_info->generic.content_size; lineno++)
295 tui_show_source_line (win_info, lineno);
297 else
298 tui_erase_source_content (win_info, TRUE);
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;
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)
312 if (win_info->generic.content != NULL)
314 int offset;
315 struct symtab *s = NULL;
317 if (win_info->generic.type == SRC_WIN)
319 struct symtab_and_line cursal = get_current_source_symtab_and_line ();
320 if (cursal.symtab == NULL)
321 s = find_pc_symtab (get_frame_pc (get_selected_frame (NULL)));
322 else
323 s = cursal.symtab;
326 if (direction == LEFT_SCROLL)
327 offset = win_info->detail.source_info.horizontal_offset + num_to_scroll;
328 else
330 if ((offset =
331 win_info->detail.source_info.horizontal_offset - num_to_scroll) < 0)
332 offset = 0;
334 win_info->detail.source_info.horizontal_offset = offset;
335 tui_update_source_window_as_is (win_info, s,
336 ((struct tui_win_element *)
337 win_info->generic.content[0])->which_element.source.line_or_addr,
338 FALSE);
341 return;
345 /* Set or clear the has_break flag in the line whose line is
346 line_no. */
348 void
349 tui_set_is_exec_point_at (struct tui_line_or_address l,
350 struct tui_win_info *win_info)
352 int changed = 0;
353 int i;
354 tui_win_content content = (tui_win_content) win_info->generic.content;
356 i = 0;
357 while (i < win_info->generic.content_size)
359 int new_state;
360 struct tui_line_or_address content_loa =
361 content[i]->which_element.source.line_or_addr;
363 gdb_assert (l.loa == LOA_ADDRESS || l.loa == LOA_LINE);
364 gdb_assert (content_loa.loa == LOA_LINE
365 || content_loa.loa == LOA_ADDRESS);
366 if (content_loa.loa == l.loa
367 && ((l.loa == LOA_LINE && content_loa.u.line_no == l.u.line_no)
368 || (content_loa.u.addr == l.u.addr)))
369 new_state = TRUE;
370 else
371 new_state = FALSE;
372 if (new_state != content[i]->which_element.source.is_exec_point)
374 changed++;
375 content[i]->which_element.source.is_exec_point = new_state;
376 tui_show_source_line (win_info, i + 1);
378 i++;
380 if (changed)
381 tui_refresh_win (&win_info->generic);
384 /* Update the execution windows to show the active breakpoints.
385 This is called whenever a breakpoint is inserted, removed or
386 has its state changed. */
387 void
388 tui_update_all_breakpoint_info (void)
390 struct tui_list *list = tui_source_windows ();
391 int i;
393 for (i = 0; i < list->count; i++)
395 struct tui_win_info *win = list->list[i];
397 if (tui_update_breakpoint_info (win, FALSE))
399 tui_update_exec_info (win);
405 /* Scan the source window and the breakpoints to update the has_break
406 information for each line.
408 Returns 1 if something changed and the execution window must be
409 refreshed. */
412 tui_update_breakpoint_info (struct tui_win_info *win,
413 int current_only)
415 int i;
416 int need_refresh = 0;
417 struct tui_source_info *src = &win->detail.source_info;
419 for (i = 0; i < win->generic.content_size; i++)
421 struct breakpoint *bp;
422 extern struct breakpoint *breakpoint_chain;
423 int mode;
424 struct tui_source_element *line;
426 line = &((struct tui_win_element *) win->generic.content[i])->which_element.source;
427 if (current_only && !line->is_exec_point)
428 continue;
430 /* Scan each breakpoint to see if the current line has something to
431 do with it. Identify enable/disabled breakpoints as well as
432 those that we already hit. */
433 mode = 0;
434 for (bp = breakpoint_chain;
435 bp != (struct breakpoint *) NULL;
436 bp = bp->next)
438 gdb_assert (line->line_or_addr.loa == LOA_LINE
439 || line->line_or_addr.loa == LOA_ADDRESS);
440 if ((win == TUI_SRC_WIN
441 && bp->source_file
442 && (strcmp (src->filename, bp->source_file) == 0)
443 && line->line_or_addr.loa == LOA_LINE
444 && bp->line_number == line->line_or_addr.u.line_no)
445 || (win == TUI_DISASM_WIN
446 && line->line_or_addr.loa == LOA_ADDRESS
447 && bp->loc != NULL
448 && bp->loc->address == line->line_or_addr.u.addr))
450 if (bp->enable_state == bp_disabled)
451 mode |= TUI_BP_DISABLED;
452 else
453 mode |= TUI_BP_ENABLED;
454 if (bp->hit_count)
455 mode |= TUI_BP_HIT;
456 if (bp->loc->cond)
457 mode |= TUI_BP_CONDITIONAL;
458 if (bp->type == bp_hardware_breakpoint)
459 mode |= TUI_BP_HARDWARE;
462 if (line->has_break != mode)
464 line->has_break = mode;
465 need_refresh = 1;
468 return need_refresh;
472 /* Function to initialize the content of the execution info window,
473 based upon the input window which is either the source or
474 disassembly window. */
475 enum tui_status
476 tui_set_exec_info_content (struct tui_win_info *win_info)
478 enum tui_status ret = TUI_SUCCESS;
480 if (win_info->detail.source_info.execution_info != (struct tui_gen_win_info *) NULL)
482 struct tui_gen_win_info *exec_info_ptr = win_info->detail.source_info.execution_info;
484 if (exec_info_ptr->content == NULL)
485 exec_info_ptr->content =
486 (void **) tui_alloc_content (win_info->generic.height,
487 exec_info_ptr->type);
488 if (exec_info_ptr->content != NULL)
490 int i;
492 tui_update_breakpoint_info (win_info, 1);
493 for (i = 0; i < win_info->generic.content_size; i++)
495 struct tui_win_element *element;
496 struct tui_win_element *src_element;
497 int mode;
499 element = (struct tui_win_element *) exec_info_ptr->content[i];
500 src_element = (struct tui_win_element *) win_info->generic.content[i];
502 memset(element->which_element.simple_string, ' ',
503 sizeof(element->which_element.simple_string));
504 element->which_element.simple_string[TUI_EXECINFO_SIZE - 1] = 0;
506 /* Now update the exec info content based upon the state
507 of each line as indicated by the source content. */
508 mode = src_element->which_element.source.has_break;
509 if (mode & TUI_BP_HIT)
510 element->which_element.simple_string[TUI_BP_HIT_POS] =
511 (mode & TUI_BP_HARDWARE) ? 'H' : 'B';
512 else if (mode & (TUI_BP_ENABLED | TUI_BP_DISABLED))
513 element->which_element.simple_string[TUI_BP_HIT_POS] =
514 (mode & TUI_BP_HARDWARE) ? 'h' : 'b';
516 if (mode & TUI_BP_ENABLED)
517 element->which_element.simple_string[TUI_BP_BREAK_POS] = '+';
518 else if (mode & TUI_BP_DISABLED)
519 element->which_element.simple_string[TUI_BP_BREAK_POS] = '-';
521 if (src_element->which_element.source.is_exec_point)
522 element->which_element.simple_string[TUI_EXEC_POS] = '>';
524 exec_info_ptr->content_size = win_info->generic.content_size;
526 else
527 ret = TUI_FAILURE;
530 return ret;
534 void
535 tui_show_exec_info_content (struct tui_win_info *win_info)
537 struct tui_gen_win_info *exec_info = win_info->detail.source_info.execution_info;
538 int cur_line;
540 werase (exec_info->handle);
541 tui_refresh_win (exec_info);
542 for (cur_line = 1; (cur_line <= exec_info->content_size); cur_line++)
543 mvwaddstr (exec_info->handle,
544 cur_line,
546 ((struct tui_win_element *)
547 exec_info->content[cur_line - 1])->which_element.simple_string);
548 tui_refresh_win (exec_info);
549 exec_info->content_in_use = TRUE;
553 void
554 tui_erase_exec_info_content (struct tui_win_info *win_info)
556 struct tui_gen_win_info *exec_info = win_info->detail.source_info.execution_info;
558 werase (exec_info->handle);
559 tui_refresh_win (exec_info);
562 void
563 tui_clear_exec_info_content (struct tui_win_info *win_info)
565 win_info->detail.source_info.execution_info->content_in_use = FALSE;
566 tui_erase_exec_info_content (win_info);
568 return;
571 /* Function to update the execution info window. */
572 void
573 tui_update_exec_info (struct tui_win_info *win_info)
575 tui_set_exec_info_content (win_info);
576 tui_show_exec_info_content (win_info);
579 enum tui_status
580 tui_alloc_source_buffer (struct tui_win_info *win_info)
582 char *src_line_buf;
583 int i, line_width, max_lines;
585 max_lines = win_info->generic.height; /* Less the highlight box. */
586 line_width = win_info->generic.width - 1;
588 * Allocate the buffer for the source lines. Do this only once
589 * since they will be re-used for all source displays. The only
590 * other time this will be done is when a window's size changes.
592 if (win_info->generic.content == NULL)
594 src_line_buf = (char *)
595 xmalloc ((max_lines * line_width) * sizeof (char));
596 if (src_line_buf == (char *) NULL)
598 fputs_unfiltered ("Unable to Allocate Memory for Source or Disassembly Display.\n",
599 gdb_stderr);
600 return TUI_FAILURE;
602 /* Allocate the content list. */
603 if ((win_info->generic.content =
604 (void **) tui_alloc_content (max_lines, SRC_WIN)) == NULL)
606 xfree (src_line_buf);
607 fputs_unfiltered ("Unable to Allocate Memory for Source or Disassembly Display.\n",
608 gdb_stderr);
609 return TUI_FAILURE;
611 for (i = 0; i < max_lines; i++)
612 ((struct tui_win_element *)
613 win_info->generic.content[i])->which_element.source.line =
614 src_line_buf + (line_width * i);
617 return TUI_SUCCESS;
621 /* Answer whether the a particular line number or address is displayed
622 in the current source window. */
624 tui_line_is_displayed (int line,
625 struct tui_win_info *win_info,
626 int check_threshold)
628 int is_displayed = FALSE;
629 int i, threshold;
631 if (check_threshold)
632 threshold = SCROLL_THRESHOLD;
633 else
634 threshold = 0;
635 i = 0;
636 while (i < win_info->generic.content_size - threshold
637 && !is_displayed)
639 is_displayed = (((struct tui_win_element *)
640 win_info->generic.content[i])->which_element.source.line_or_addr.loa
641 == LOA_LINE)
642 && (((struct tui_win_element *)
643 win_info->generic.content[i])->which_element.source.line_or_addr.u.line_no
644 == (int) line);
645 i++;
648 return is_displayed;
652 /* Answer whether the a particular line number or address is displayed
653 in the current source window. */
655 tui_addr_is_displayed (CORE_ADDR addr,
656 struct tui_win_info *win_info,
657 int check_threshold)
659 int is_displayed = FALSE;
660 int i, threshold;
662 if (check_threshold)
663 threshold = SCROLL_THRESHOLD;
664 else
665 threshold = 0;
666 i = 0;
667 while (i < win_info->generic.content_size - threshold
668 && !is_displayed)
670 is_displayed = (((struct tui_win_element *)
671 win_info->generic.content[i])->which_element.source.line_or_addr.loa
672 == LOA_ADDRESS)
673 && (((struct tui_win_element *)
674 win_info->generic.content[i])->which_element.source.line_or_addr.u.addr
675 == addr);
676 i++;
679 return is_displayed;
683 /*****************************************
684 ** STATIC LOCAL FUNCTIONS **
685 ******************************************/