Commit | Line | Data |
---|---|---|
8b93c638 | 1 | /* Output generating routines for GDB CLI. |
349c5d5f | 2 | |
42a4f53d | 3 | Copyright (C) 1999-2019 Free Software Foundation, Inc. |
349c5d5f | 4 | |
8b93c638 JM |
5 | Contributed by Cygnus Solutions. |
6 | Written by Fernando Nasser for Cygnus. | |
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 | |
a9762ec7 | 12 | the Free Software Foundation; either version 3 of the License, or |
8b93c638 JM |
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 | |
a9762ec7 | 21 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
8b93c638 JM |
22 | |
23 | #include "defs.h" | |
d55e5aa6 TT |
24 | |
25 | /* Local non-gdb includes. */ | |
8b93c638 | 26 | #include "cli-out.h" |
d55e5aa6 | 27 | #include "cli/cli-style.h" |
82083d6d | 28 | #include "completer.h" |
82083d6d | 29 | #include "readline/readline.h" |
d55e5aa6 | 30 | #include "ui-out.h" |
8b93c638 | 31 | |
02a45ac0 PA |
32 | /* These are the CLI output functions */ |
33 | ||
8b93c638 JM |
34 | /* Mark beginning of a table */ |
35 | ||
112e8700 SM |
36 | void |
37 | cli_ui_out::do_table_begin (int nbrofcols, int nr_rows, const char *tblid) | |
8b93c638 | 38 | { |
698384cd | 39 | if (nr_rows == 0) |
112e8700 | 40 | m_suppress_output = true; |
698384cd | 41 | else |
ce2826aa | 42 | /* Only the table suppresses the output and, fortunately, a table |
30fdc99f | 43 | is not a recursive data structure. */ |
112e8700 | 44 | gdb_assert (!m_suppress_output); |
8b93c638 JM |
45 | } |
46 | ||
47 | /* Mark beginning of a table body */ | |
48 | ||
112e8700 SM |
49 | void |
50 | cli_ui_out::do_table_body () | |
8b93c638 | 51 | { |
112e8700 | 52 | if (m_suppress_output) |
698384cd | 53 | return; |
112e8700 | 54 | |
8b93c638 | 55 | /* first, close the table header line */ |
112e8700 | 56 | text ("\n"); |
8b93c638 JM |
57 | } |
58 | ||
59 | /* Mark end of a table */ | |
60 | ||
112e8700 SM |
61 | void |
62 | cli_ui_out::do_table_end () | |
8b93c638 | 63 | { |
112e8700 | 64 | m_suppress_output = false; |
8b93c638 JM |
65 | } |
66 | ||
67 | /* Specify table header */ | |
68 | ||
112e8700 SM |
69 | void |
70 | cli_ui_out::do_table_header (int width, ui_align alignment, | |
71 | const std::string &col_name, | |
72 | const std::string &col_hdr) | |
8b93c638 | 73 | { |
112e8700 | 74 | if (m_suppress_output) |
698384cd | 75 | return; |
0a8fce9a | 76 | |
cbe56571 TT |
77 | do_field_string (0, width, alignment, 0, col_hdr.c_str (), |
78 | ui_out_style_kind::DEFAULT); | |
8b93c638 JM |
79 | } |
80 | ||
81 | /* Mark beginning of a list */ | |
82 | ||
112e8700 SM |
83 | void |
84 | cli_ui_out::do_begin (ui_out_type type, const char *id) | |
8b93c638 JM |
85 | { |
86 | } | |
87 | ||
88 | /* Mark end of a list */ | |
89 | ||
112e8700 SM |
90 | void |
91 | cli_ui_out::do_end (ui_out_type type) | |
8b93c638 JM |
92 | { |
93 | } | |
94 | ||
95 | /* output an int field */ | |
96 | ||
112e8700 SM |
97 | void |
98 | cli_ui_out::do_field_int (int fldno, int width, ui_align alignment, | |
99 | const char *fldname, int value) | |
8b93c638 | 100 | { |
112e8700 | 101 | if (m_suppress_output) |
698384cd | 102 | return; |
112e8700 | 103 | |
d63095c4 | 104 | std::string str = string_printf ("%d", value); |
0a8fce9a | 105 | |
cbe56571 TT |
106 | do_field_string (fldno, width, alignment, fldname, str.c_str (), |
107 | ui_out_style_kind::DEFAULT); | |
8b93c638 JM |
108 | } |
109 | ||
112e8700 | 110 | /* used to omit a field */ |
8b93c638 | 111 | |
112e8700 SM |
112 | void |
113 | cli_ui_out::do_field_skip (int fldno, int width, ui_align alignment, | |
114 | const char *fldname) | |
8b93c638 | 115 | { |
112e8700 | 116 | if (m_suppress_output) |
698384cd | 117 | return; |
0a8fce9a | 118 | |
cbe56571 TT |
119 | do_field_string (fldno, width, alignment, fldname, "", |
120 | ui_out_style_kind::DEFAULT); | |
8b93c638 JM |
121 | } |
122 | ||
123 | /* other specific cli_field_* end up here so alignment and field | |
124 | separators are both handled by cli_field_string */ | |
125 | ||
112e8700 SM |
126 | void |
127 | cli_ui_out::do_field_string (int fldno, int width, ui_align align, | |
cbe56571 TT |
128 | const char *fldname, const char *string, |
129 | ui_out_style_kind style) | |
8b93c638 JM |
130 | { |
131 | int before = 0; | |
132 | int after = 0; | |
c5504eaf | 133 | |
112e8700 | 134 | if (m_suppress_output) |
698384cd AC |
135 | return; |
136 | ||
8b93c638 JM |
137 | if ((align != ui_noalign) && string) |
138 | { | |
139 | before = width - strlen (string); | |
140 | if (before <= 0) | |
141 | before = 0; | |
142 | else | |
143 | { | |
144 | if (align == ui_right) | |
145 | after = 0; | |
146 | else if (align == ui_left) | |
147 | { | |
148 | after = before; | |
149 | before = 0; | |
150 | } | |
151 | else | |
152 | /* ui_center */ | |
153 | { | |
154 | after = before / 2; | |
155 | before -= after; | |
156 | } | |
157 | } | |
158 | } | |
159 | ||
160 | if (before) | |
112e8700 SM |
161 | spaces (before); |
162 | ||
8b93c638 | 163 | if (string) |
cbe56571 TT |
164 | { |
165 | ui_file_style fstyle; | |
166 | switch (style) | |
167 | { | |
168 | case ui_out_style_kind::DEFAULT: | |
169 | /* Nothing. */ | |
170 | break; | |
171 | case ui_out_style_kind::FILE: | |
172 | /* Nothing. */ | |
173 | fstyle = file_name_style.style (); | |
174 | break; | |
175 | case ui_out_style_kind::FUNCTION: | |
176 | fstyle = function_name_style.style (); | |
177 | break; | |
80ae2043 TT |
178 | case ui_out_style_kind::VARIABLE: |
179 | fstyle = variable_name_style.style (); | |
180 | break; | |
35fb8261 TT |
181 | case ui_out_style_kind::ADDRESS: |
182 | fstyle = address_style.style (); | |
183 | break; | |
cbe56571 TT |
184 | default: |
185 | gdb_assert_not_reached ("missing case"); | |
186 | } | |
187 | fputs_styled (string, fstyle, m_streams.back ()); | |
188 | } | |
112e8700 | 189 | |
8b93c638 | 190 | if (after) |
112e8700 | 191 | spaces (after); |
8b93c638 JM |
192 | |
193 | if (align != ui_noalign) | |
194 | field_separator (); | |
195 | } | |
196 | ||
1871a62d | 197 | /* Output field containing ARGS using printf formatting in FORMAT. */ |
8b93c638 | 198 | |
112e8700 SM |
199 | void |
200 | cli_ui_out::do_field_fmt (int fldno, int width, ui_align align, | |
201 | const char *fldname, const char *format, | |
202 | va_list args) | |
8b93c638 | 203 | { |
112e8700 | 204 | if (m_suppress_output) |
698384cd AC |
205 | return; |
206 | ||
1871a62d | 207 | std::string str = string_vprintf (format, args); |
8b93c638 | 208 | |
cbe56571 TT |
209 | do_field_string (fldno, width, align, fldname, str.c_str (), |
210 | ui_out_style_kind::DEFAULT); | |
8b93c638 JM |
211 | } |
212 | ||
112e8700 SM |
213 | void |
214 | cli_ui_out::do_spaces (int numspaces) | |
8b93c638 | 215 | { |
112e8700 | 216 | if (m_suppress_output) |
698384cd | 217 | return; |
14dba4b4 | 218 | |
112e8700 | 219 | print_spaces_filtered (numspaces, m_streams.back ()); |
8b93c638 JM |
220 | } |
221 | ||
112e8700 SM |
222 | void |
223 | cli_ui_out::do_text (const char *string) | |
8b93c638 | 224 | { |
112e8700 | 225 | if (m_suppress_output) |
698384cd | 226 | return; |
14dba4b4 | 227 | |
112e8700 | 228 | fputs_filtered (string, m_streams.back ()); |
8b93c638 JM |
229 | } |
230 | ||
112e8700 SM |
231 | void |
232 | cli_ui_out::do_message (const char *format, va_list args) | |
8b93c638 | 233 | { |
112e8700 | 234 | if (m_suppress_output) |
698384cd | 235 | return; |
14dba4b4 | 236 | |
112e8700 | 237 | vfprintf_unfiltered (m_streams.back (), format, args); |
8b93c638 JM |
238 | } |
239 | ||
112e8700 SM |
240 | void |
241 | cli_ui_out::do_wrap_hint (const char *identstring) | |
8b93c638 | 242 | { |
112e8700 | 243 | if (m_suppress_output) |
698384cd | 244 | return; |
112e8700 | 245 | |
8b93c638 JM |
246 | wrap_here (identstring); |
247 | } | |
248 | ||
112e8700 SM |
249 | void |
250 | cli_ui_out::do_flush () | |
8b93c638 | 251 | { |
112e8700 | 252 | gdb_flush (m_streams.back ()); |
8b93c638 JM |
253 | } |
254 | ||
14dba4b4 JK |
255 | /* OUTSTREAM as non-NULL will push OUTSTREAM on the stack of output streams |
256 | and make it therefore active. OUTSTREAM as NULL will pop the last pushed | |
257 | output stream; it is an internal error if it does not exist. */ | |
258 | ||
7becfd03 | 259 | void |
112e8700 | 260 | cli_ui_out::do_redirect (ui_file *outstream) |
0fac0b41 | 261 | { |
0fac0b41 | 262 | if (outstream != NULL) |
112e8700 | 263 | m_streams.push_back (outstream); |
14dba4b4 | 264 | else |
112e8700 | 265 | m_streams.pop_back (); |
0fac0b41 DJ |
266 | } |
267 | ||
8b93c638 JM |
268 | /* local functions */ |
269 | ||
112e8700 SM |
270 | void |
271 | cli_ui_out::field_separator () | |
8b93c638 | 272 | { |
112e8700 | 273 | fputc_filtered (' ', m_streams.back ()); |
8b93c638 JM |
274 | } |
275 | ||
112e8700 | 276 | /* Constructor for cli_ui_out. */ |
02a45ac0 | 277 | |
112e8700 SM |
278 | cli_ui_out::cli_ui_out (ui_file *stream, ui_out_flags flags) |
279 | : ui_out (flags), | |
280 | m_suppress_output (false) | |
0a8fce9a | 281 | { |
14dba4b4 JK |
282 | gdb_assert (stream != NULL); |
283 | ||
112e8700 SM |
284 | m_streams.push_back (stream); |
285 | } | |
14dba4b4 | 286 | |
112e8700 SM |
287 | cli_ui_out::~cli_ui_out () |
288 | { | |
0a8fce9a PA |
289 | } |
290 | ||
291 | /* Initialize private members at startup. */ | |
8b93c638 | 292 | |
112e8700 | 293 | cli_ui_out * |
8b93c638 JM |
294 | cli_out_new (struct ui_file *stream) |
295 | { | |
112e8700 | 296 | return new cli_ui_out (stream, ui_source_list); |
8b93c638 JM |
297 | } |
298 | ||
112e8700 SM |
299 | ui_file * |
300 | cli_ui_out::set_stream (struct ui_file *stream) | |
4389a95a | 301 | { |
112e8700 | 302 | ui_file *old; |
b9b118c3 | 303 | |
112e8700 SM |
304 | old = m_streams.back (); |
305 | m_streams.back () = stream; | |
c5504eaf | 306 | |
4389a95a AC |
307 | return old; |
308 | } | |
b9b118c3 | 309 | |
82083d6d DE |
310 | /* CLI interface to display tab-completion matches. */ |
311 | ||
312 | /* CLI version of displayer.crlf. */ | |
313 | ||
314 | static void | |
315 | cli_mld_crlf (const struct match_list_displayer *displayer) | |
316 | { | |
317 | rl_crlf (); | |
318 | } | |
319 | ||
320 | /* CLI version of displayer.putch. */ | |
321 | ||
322 | static void | |
323 | cli_mld_putch (const struct match_list_displayer *displayer, int ch) | |
324 | { | |
325 | putc (ch, rl_outstream); | |
326 | } | |
327 | ||
328 | /* CLI version of displayer.puts. */ | |
329 | ||
330 | static void | |
331 | cli_mld_puts (const struct match_list_displayer *displayer, const char *s) | |
332 | { | |
333 | fputs (s, rl_outstream); | |
334 | } | |
335 | ||
336 | /* CLI version of displayer.flush. */ | |
337 | ||
338 | static void | |
339 | cli_mld_flush (const struct match_list_displayer *displayer) | |
340 | { | |
341 | fflush (rl_outstream); | |
342 | } | |
343 | ||
56000a98 PA |
344 | EXTERN_C void _rl_erase_entire_line (void); |
345 | ||
82083d6d DE |
346 | /* CLI version of displayer.erase_entire_line. */ |
347 | ||
348 | static void | |
349 | cli_mld_erase_entire_line (const struct match_list_displayer *displayer) | |
350 | { | |
82083d6d DE |
351 | _rl_erase_entire_line (); |
352 | } | |
353 | ||
354 | /* CLI version of displayer.beep. */ | |
355 | ||
356 | static void | |
357 | cli_mld_beep (const struct match_list_displayer *displayer) | |
358 | { | |
359 | rl_ding (); | |
360 | } | |
361 | ||
362 | /* CLI version of displayer.read_key. */ | |
363 | ||
364 | static int | |
365 | cli_mld_read_key (const struct match_list_displayer *displayer) | |
366 | { | |
367 | return rl_read_key (); | |
368 | } | |
369 | ||
370 | /* CLI version of rl_completion_display_matches_hook. | |
371 | See gdb_display_match_list for a description of the arguments. */ | |
372 | ||
373 | void | |
374 | cli_display_match_list (char **matches, int len, int max) | |
375 | { | |
376 | struct match_list_displayer displayer; | |
377 | ||
378 | rl_get_screen_size (&displayer.height, &displayer.width); | |
379 | displayer.crlf = cli_mld_crlf; | |
380 | displayer.putch = cli_mld_putch; | |
381 | displayer.puts = cli_mld_puts; | |
382 | displayer.flush = cli_mld_flush; | |
383 | displayer.erase_entire_line = cli_mld_erase_entire_line; | |
384 | displayer.beep = cli_mld_beep; | |
385 | displayer.read_key = cli_mld_read_key; | |
386 | ||
387 | gdb_display_match_list (matches, len, max, &displayer); | |
388 | rl_forced_update_display (); | |
389 | } |