gdb/testsuite: Improve detection of bug gdb/24541
[deliverable/binutils-gdb.git] / gdb / tui / tui-source.c
CommitLineData
f377b406 1/* TUI display source window.
f33c6cbf 2
42a4f53d 3 Copyright (C) 1998-2019 Free Software Foundation, Inc.
f33c6cbf 4
f377b406
SC
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
a9762ec7 11 the Free Software Foundation; either version 3 of the License, or
f377b406
SC
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
a9762ec7 20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
c906108c
SS
21
22#include "defs.h"
23#include <ctype.h>
24#include "symtab.h"
25#include "frame.h"
26#include "breakpoint.h"
c2c6d25f 27#include "source.h"
13274fc3 28#include "objfiles.h"
a7417d46 29#include "filenames.h"
62f29fda 30#include "source-cache.h"
c906108c 31
d7b2e967
AC
32#include "tui/tui.h"
33#include "tui/tui-data.h"
62f29fda 34#include "tui/tui-io.h"
d7b2e967
AC
35#include "tui/tui-stack.h"
36#include "tui/tui-winsource.h"
37#include "tui/tui-source.h"
6a83354a 38#include "gdb_curses.h"
c906108c 39
62f29fda
TT
40/* A helper function for tui_set_source_content that extracts some
41 source text from PTR. LINE_NO is the line number; FIRST_COL is the
42 first column to extract, and LINE_WIDTH is the number of characters
43 to display. Returns a string holding the desired text. */
44
45static std::string
46copy_source_line (const char **ptr, int line_no, int first_col,
47 int line_width)
48{
49 const char *lineptr = *ptr;
50
51 /* Init the line with the line number. */
52 std::string result = string_printf ("%-6d", line_no);
53 int len = result.size ();
54 len = len - ((len / tui_tab_width) * tui_tab_width);
55 result.append (len, ' ');
56
57 int column = 0;
58 char c;
59 do
60 {
61 int skip_bytes;
62
63 c = *lineptr;
64 if (c == '\033' && skip_ansi_escape (lineptr, &skip_bytes))
65 {
66 /* We always have to preserve escapes. */
67 result.append (lineptr, lineptr + skip_bytes);
68 lineptr += skip_bytes;
69 continue;
70 }
71
72 ++lineptr;
73 ++column;
647bb750
HD
74
75 auto process_tab = [&] ()
76 {
77 int max_tab_len = tui_tab_width;
78
79 --column;
80 for (int j = column % max_tab_len;
81 j < max_tab_len && column < first_col + line_width;
82 column++, j++)
83 if (column >= first_col)
84 result.push_back (' ');
85 };
86
62f29fda
TT
87 /* We have to process all the text in order to pick up all the
88 escapes. */
647bb750
HD
89 if (column <= first_col || column > first_col + line_width)
90 {
91 if (c == '\t')
92 process_tab ();
93 continue;
94 }
62f29fda
TT
95
96 if (c == '\n' || c == '\r' || c == '\0')
97 {
98 /* Nothing. */
99 }
100 else if (c < 040 && c != '\t')
101 {
102 result.push_back ('^');
103 result.push_back (c + 0100);
104 }
105 else if (c == 0177)
106 {
107 result.push_back ('^');
108 result.push_back ('?');
109 }
110 else if (c == '\t')
647bb750 111 process_tab ();
62f29fda
TT
112 else
113 result.push_back (c);
114 }
115 while (c != '\0' && c != '\n' && c != '\r');
116
117 if (c == '\r' && *lineptr == '\n')
118 ++lineptr;
119 *ptr = lineptr;
120
121 return result;
122}
123
98427f35 124/* Function to display source in the source window. */
a358af15 125enum tui_status
08ef48c5
MS
126tui_set_source_content (struct symtab *s,
127 int line_no,
128 int noerror)
c906108c 129{
22940a24 130 enum tui_status ret = TUI_FAILURE;
c906108c 131
4e04028d 132 if (s != (struct symtab *) NULL)
c906108c 133 {
62f29fda 134 int line_width, nlines;
c906108c 135
6d012f14 136 if ((ret = tui_alloc_source_buffer (TUI_SRC_WIN)) == TUI_SUCCESS)
c906108c 137 {
6ba8e26f 138 line_width = TUI_SRC_WIN->generic.width - 1;
1cc6d956
MS
139 /* Take hilite (window border) into account, when
140 calculating the number of lines. */
6d012f14 141 nlines = (line_no + (TUI_SRC_WIN->generic.height - 2)) - line_no;
62f29fda
TT
142
143 std::string srclines;
144 if (!g_source_cache.get_source_lines (s, line_no, line_no + nlines,
145 &srclines))
c906108c
SS
146 {
147 if (!noerror)
148 {
05cba821 149 const char *filename = symtab_to_filename_for_display (s);
224c3ddb 150 char *name = (char *) alloca (strlen (filename) + 100);
1c5313c5 151
05cba821 152 sprintf (name, "%s:%d", filename, line_no);
c906108c
SS
153 print_sys_errmsg (name, errno);
154 }
155 ret = TUI_FAILURE;
156 }
157 else
158 {
62f29fda
TT
159 int cur_line_no, cur_line;
160 struct tui_gen_win_info *locator
161 = tui_locator_win_info_ptr ();
162 struct tui_source_info *src
163 = &TUI_SRC_WIN->detail.source_info;
164 const char *s_filename = symtab_to_filename_for_display (s);
165
166 if (TUI_SRC_WIN->generic.title)
167 xfree (TUI_SRC_WIN->generic.title);
168 TUI_SRC_WIN->generic.title = xstrdup (s_filename);
169
170 xfree (src->fullname);
171 src->fullname = xstrdup (symtab_to_fullname (s));
172
173 cur_line = 0;
174 src->gdbarch = get_objfile_arch (SYMTAB_OBJFILE (s));
175 src->start_line_or_addr.loa = LOA_LINE;
176 cur_line_no = src->start_line_or_addr.u.line_no = line_no;
177
178 const char *iter = srclines.c_str ();
179 while (cur_line < nlines)
c906108c 180 {
62f29fda
TT
181 struct tui_win_element *element
182 = TUI_SRC_WIN->generic.content[cur_line];
183
184 std::string text;
185 if (*iter != '\0')
186 text = copy_source_line (&iter, cur_line_no,
187 src->horizontal_offset,
188 line_width);
189
190 /* Set whether element is the execution point
191 and whether there is a break point on it. */
192 element->which_element.source.line_or_addr.loa =
193 LOA_LINE;
194 element->which_element.source.line_or_addr.u.line_no =
195 cur_line_no;
196 element->which_element.source.is_exec_point =
197 (filename_cmp (locator->content[0]
198 ->which_element.locator.full_name,
199 symtab_to_fullname (s)) == 0
200 && cur_line_no
201 == locator->content[0]
202 ->which_element.locator.line_no);
203
204 xfree (TUI_SRC_WIN->generic.content[cur_line]
205 ->which_element.source.line);
62f29fda
TT
206 TUI_SRC_WIN->generic.content[cur_line]
207 ->which_element.source.line
986041cd 208 = xstrdup (text.c_str ());
62f29fda
TT
209
210 cur_line++;
211 cur_line_no++;
c906108c 212 }
62f29fda
TT
213 TUI_SRC_WIN->generic.content_size = nlines;
214 ret = TUI_SUCCESS;
c906108c
SS
215 }
216 }
217 }
218 return ret;
98427f35 219}
c906108c
SS
220
221
1cc6d956 222/* elz: This function sets the contents of the source window to empty
c906108c 223 except for a line in the middle with a warning message about the
1cc6d956 224 source not being available. This function is called by
6ba8e26f
AC
225 tui_erase_source_contents(), which in turn is invoked when the
226 source files cannot be accessed. */
c906108c
SS
227
228void
08ef48c5 229tui_set_source_content_nil (struct tui_win_info *win_info,
a121b7c1 230 const char *warning_string)
c906108c 231{
6ba8e26f
AC
232 int line_width;
233 int n_lines;
c906108c
SS
234 int curr_line = 0;
235
6ba8e26f
AC
236 line_width = win_info->generic.width - 1;
237 n_lines = win_info->generic.height - 2;
c906108c 238
1cc6d956
MS
239 /* Set to empty each line in the window, except for the one which
240 contains the message. */
6ba8e26f 241 while (curr_line < win_info->generic.content_size)
c906108c 242 {
1cc6d956
MS
243 /* Set the information related to each displayed line to null:
244 i.e. the line number is 0, there is no bp, it is not where
245 the program is stopped. */
c906108c 246
63ed8182 247 struct tui_win_element *element = win_info->generic.content[curr_line];
1c5313c5 248
362c05fe
AS
249 element->which_element.source.line_or_addr.loa = LOA_LINE;
250 element->which_element.source.line_or_addr.u.line_no = 0;
6d012f14
AC
251 element->which_element.source.is_exec_point = FALSE;
252 element->which_element.source.has_break = FALSE;
c906108c 253
1cc6d956 254 /* Set the contents of the line to blank. */
6d012f14 255 element->which_element.source.line[0] = (char) 0;
c906108c 256
1cc6d956 257 /* If the current line is in the middle of the screen, then we
6ba8e26f
AC
258 want to display the 'no source available' message in it.
259 Note: the 'weird' arithmetic with the line width and height
1cc6d956
MS
260 comes from the function tui_erase_source_content(). We need
261 to keep the screen and the window's actual contents in
262 synch. */
c906108c 263
6ba8e26f 264 if (curr_line == (n_lines / 2 + 1))
c906108c 265 {
c906108c
SS
266 int xpos;
267 int warning_length = strlen (warning_string);
6ba8e26f 268 char *src_line;
c906108c 269
6ba8e26f 270 if (warning_length >= ((line_width - 1) / 2))
c906108c
SS
271 xpos = 1;
272 else
6ba8e26f 273 xpos = (line_width - 1) / 2 - warning_length;
c906108c 274
0c820d67
TT
275 src_line = xstrprintf ("%s%s", n_spaces (xpos), warning_string);
276 xfree (element->which_element.source.line);
277 element->which_element.source.line = src_line;
278 }
c906108c
SS
279
280 curr_line++;
0c820d67 281 }
98427f35 282}
c906108c
SS
283
284
98427f35
SC
285/* Function to display source in the source window. This function
286 initializes the horizontal scroll to 0. */
c906108c 287void
13274fc3 288tui_show_symtab_source (struct gdbarch *gdbarch, struct symtab *s,
08ef48c5
MS
289 struct tui_line_or_address line,
290 int noerror)
c906108c 291{
6d012f14 292 TUI_SRC_WIN->detail.source_info.horizontal_offset = 0;
13274fc3 293 tui_update_source_window_as_is (TUI_SRC_WIN, gdbarch, s, line, noerror);
98427f35 294}
c906108c 295
c906108c 296
a358af15
AC
297/* Answer whether the source is currently displayed in the source
298 window. */
c906108c 299int
56d397a3 300tui_source_is_displayed (const char *fullname)
c906108c 301{
f629cd75
L
302 return (TUI_SRC_WIN != NULL
303 && TUI_SRC_WIN->generic.content_in_use
63ed8182
PP
304 && (filename_cmp (tui_locator_win_info_ptr ()->content[0]
305 ->which_element.locator.full_name,
56d397a3 306 fullname) == 0));
98427f35 307}
c906108c
SS
308
309
98427f35 310/* Scroll the source forward or backward vertically. */
c906108c 311void
6ba8e26f
AC
312tui_vertical_source_scroll (enum tui_scroll_direction scroll_direction,
313 int num_to_scroll)
c906108c 314{
6d012f14 315 if (TUI_SRC_WIN->generic.content != NULL)
c906108c 316 {
362c05fe 317 struct tui_line_or_address l;
c906108c 318 struct symtab *s;
63a33118 319 tui_win_content content = TUI_SRC_WIN->generic.content;
52575520 320 struct symtab_and_line cursal = get_current_source_symtab_and_line ();
c906108c 321
52575520 322 if (cursal.symtab == (struct symtab *) NULL)
34248c3a 323 s = find_pc_line_symtab (get_frame_pc (get_selected_frame (NULL)));
c906108c 324 else
52575520 325 s = cursal.symtab;
c906108c 326
362c05fe 327 l.loa = LOA_LINE;
6ba8e26f 328 if (scroll_direction == FORWARD_SCROLL)
c906108c 329 {
362c05fe
AS
330 l.u.line_no = content[0]->which_element.source.line_or_addr.u.line_no
331 + num_to_scroll;
332 if (l.u.line_no > s->nlines)
1cc6d956
MS
333 /* line = s->nlines - win_info->generic.content_size + 1; */
334 /* elz: fix for dts 23398. */
9a2b4c1b
MS
335 l.u.line_no
336 = content[0]->which_element.source.line_or_addr.u.line_no;
c906108c
SS
337 }
338 else
339 {
362c05fe
AS
340 l.u.line_no = content[0]->which_element.source.line_or_addr.u.line_no
341 - num_to_scroll;
342 if (l.u.line_no <= 0)
343 l.u.line_no = 1;
c906108c 344 }
27229e99 345
362c05fe 346 print_source_lines (s, l.u.line_no, l.u.line_no + 1, 0);
c906108c 347 }
98427f35 348}
This page took 1.940759 seconds and 4 git commands to generate.