]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/cli-out.c
Update copyright year range in all GDB files
[thirdparty/binutils-gdb.git] / gdb / cli-out.c
CommitLineData
8b93c638 1/* Output generating routines for GDB CLI.
349c5d5f 2
3666a048 3 Copyright (C) 1999-2021 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"
4de283e4 24#include "ui-out.h"
8b93c638 25#include "cli-out.h"
82083d6d 26#include "completer.h"
82083d6d 27#include "readline/readline.h"
4de283e4 28#include "cli/cli-style.h"
8b93c638 29
02a45ac0
PA
30/* These are the CLI output functions */
31
8b93c638
JM
32/* Mark beginning of a table */
33
112e8700
SM
34void
35cli_ui_out::do_table_begin (int nbrofcols, int nr_rows, const char *tblid)
8b93c638 36{
698384cd 37 if (nr_rows == 0)
112e8700 38 m_suppress_output = true;
698384cd 39 else
ce2826aa 40 /* Only the table suppresses the output and, fortunately, a table
30fdc99f 41 is not a recursive data structure. */
112e8700 42 gdb_assert (!m_suppress_output);
8b93c638
JM
43}
44
45/* Mark beginning of a table body */
46
112e8700
SM
47void
48cli_ui_out::do_table_body ()
8b93c638 49{
112e8700 50 if (m_suppress_output)
698384cd 51 return;
112e8700 52
8b93c638 53 /* first, close the table header line */
112e8700 54 text ("\n");
8b93c638
JM
55}
56
57/* Mark end of a table */
58
112e8700
SM
59void
60cli_ui_out::do_table_end ()
8b93c638 61{
112e8700 62 m_suppress_output = false;
8b93c638
JM
63}
64
65/* Specify table header */
66
112e8700
SM
67void
68cli_ui_out::do_table_header (int width, ui_align alignment,
69 const std::string &col_name,
70 const std::string &col_hdr)
8b93c638 71{
112e8700 72 if (m_suppress_output)
698384cd 73 return;
0a8fce9a 74
cbe56571 75 do_field_string (0, width, alignment, 0, col_hdr.c_str (),
e43b10e1 76 ui_file_style ());
8b93c638
JM
77}
78
79/* Mark beginning of a list */
80
112e8700
SM
81void
82cli_ui_out::do_begin (ui_out_type type, const char *id)
8b93c638
JM
83{
84}
85
86/* Mark end of a list */
87
112e8700
SM
88void
89cli_ui_out::do_end (ui_out_type type)
8b93c638
JM
90{
91}
92
93/* output an int field */
94
112e8700 95void
381befee
TT
96cli_ui_out::do_field_signed (int fldno, int width, ui_align alignment,
97 const char *fldname, LONGEST value)
8b93c638 98{
112e8700 99 if (m_suppress_output)
698384cd 100 return;
112e8700 101
381befee 102 do_field_string (fldno, width, alignment, fldname, plongest (value),
e43b10e1 103 ui_file_style ());
8b93c638
JM
104}
105
1f77b012
TT
106/* output an unsigned field */
107
108void
109cli_ui_out::do_field_unsigned (int fldno, int width, ui_align alignment,
110 const char *fldname, ULONGEST value)
111{
112 if (m_suppress_output)
113 return;
114
115 do_field_string (fldno, width, alignment, fldname, pulongest (value),
e43b10e1 116 ui_file_style ());
1f77b012
TT
117}
118
112e8700 119/* used to omit a field */
8b93c638 120
112e8700
SM
121void
122cli_ui_out::do_field_skip (int fldno, int width, ui_align alignment,
123 const char *fldname)
8b93c638 124{
112e8700 125 if (m_suppress_output)
698384cd 126 return;
0a8fce9a 127
cbe56571 128 do_field_string (fldno, width, alignment, fldname, "",
e43b10e1 129 ui_file_style ());
8b93c638
JM
130}
131
132/* other specific cli_field_* end up here so alignment and field
133 separators are both handled by cli_field_string */
134
112e8700
SM
135void
136cli_ui_out::do_field_string (int fldno, int width, ui_align align,
cbe56571 137 const char *fldname, const char *string,
e43b10e1 138 const ui_file_style &style)
8b93c638
JM
139{
140 int before = 0;
141 int after = 0;
c5504eaf 142
112e8700 143 if (m_suppress_output)
698384cd
AC
144 return;
145
8b93c638
JM
146 if ((align != ui_noalign) && string)
147 {
148 before = width - strlen (string);
149 if (before <= 0)
150 before = 0;
151 else
152 {
153 if (align == ui_right)
154 after = 0;
155 else if (align == ui_left)
156 {
157 after = before;
158 before = 0;
159 }
160 else
161 /* ui_center */
162 {
163 after = before / 2;
164 before -= after;
165 }
166 }
167 }
168
169 if (before)
112e8700
SM
170 spaces (before);
171
8b93c638 172 if (string)
2a3c1174
PA
173 {
174 if (test_flags (unfiltered_output))
175 fputs_styled_unfiltered (string, style, m_streams.back ());
176 else
177 fputs_styled (string, style, m_streams.back ());
178 }
112e8700 179
8b93c638 180 if (after)
112e8700 181 spaces (after);
8b93c638
JM
182
183 if (align != ui_noalign)
184 field_separator ();
185}
186
1871a62d 187/* Output field containing ARGS using printf formatting in FORMAT. */
8b93c638 188
112e8700
SM
189void
190cli_ui_out::do_field_fmt (int fldno, int width, ui_align align,
7f6aba03
TT
191 const char *fldname, const ui_file_style &style,
192 const char *format, va_list args)
8b93c638 193{
112e8700 194 if (m_suppress_output)
698384cd
AC
195 return;
196
1871a62d 197 std::string str = string_vprintf (format, args);
8b93c638 198
7f6aba03 199 do_field_string (fldno, width, align, fldname, str.c_str (), style);
8b93c638
JM
200}
201
112e8700
SM
202void
203cli_ui_out::do_spaces (int numspaces)
8b93c638 204{
112e8700 205 if (m_suppress_output)
698384cd 206 return;
14dba4b4 207
2a3c1174
PA
208 if (test_flags (unfiltered_output))
209 print_spaces (numspaces, m_streams.back ());
210 else
211 print_spaces_filtered (numspaces, m_streams.back ());
8b93c638
JM
212}
213
112e8700
SM
214void
215cli_ui_out::do_text (const char *string)
8b93c638 216{
112e8700 217 if (m_suppress_output)
698384cd 218 return;
14dba4b4 219
2a3c1174
PA
220 if (test_flags (unfiltered_output))
221 fputs_unfiltered (string, m_streams.back ());
222 else
223 fputs_filtered (string, m_streams.back ());
8b93c638
JM
224}
225
112e8700 226void
2a3c1174
PA
227cli_ui_out::do_message (const ui_file_style &style,
228 const char *format, va_list args)
8b93c638 229{
112e8700 230 if (m_suppress_output)
698384cd 231 return;
14dba4b4 232
2a3c1174
PA
233 /* Use the "no_gdbfmt" variant here to avoid recursion.
234 vfprintf_styled calls into cli_ui_out::message to handle the
235 gdb-specific printf formats. */
236 vfprintf_styled_no_gdbfmt (m_streams.back (), style,
237 !test_flags (unfiltered_output), format, args);
8b93c638
JM
238}
239
112e8700
SM
240void
241cli_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
249void
250cli_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 259void
112e8700 260cli_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
2f228731
TT
268/* The cli_ui_out::do_progress_* functions result in the following:
269 - printed for tty, SHOULD_PRINT == true:
270 <NAME
271 [##### ]\r>
272 - printed for tty, SHOULD_PRINT == false:
273 <>
274 - printed for not-a-tty:
d6f26c9d 275 <NAME...
2f228731
TT
276 >
277*/
278
279void
280cli_ui_out::do_progress_start (const std::string &name, bool should_print)
281{
282 struct ui_file *stream = m_streams.back ();
283 cli_progress_info meter;
284
285 meter.last_value = 0;
286 meter.name = name;
287 if (!stream->isatty ())
288 {
289 fprintf_unfiltered (stream, "%s...", meter.name.c_str ());
290 gdb_flush (stream);
291 meter.printing = WORKING;
292 }
293 else
294 {
295 /* Don't actually emit anything until the first call notifies us
296 of progress. This makes it so a second progress message can
297 be started before the first one has been notified, without
298 messy output. */
299 meter.printing = should_print ? START : NO_PRINT;
300 }
301
302 m_meters.push_back (std::move (meter));
303}
304
305void
306cli_ui_out::do_progress_notify (double howmuch)
307{
308 struct ui_file *stream = m_streams.back ();
309 cli_progress_info &meter (m_meters.back ());
310
311 if (meter.printing == NO_PRINT)
312 return;
313
314 if (meter.printing == START)
315 {
316 fprintf_unfiltered (stream, "%s\n", meter.name.c_str ());
317 gdb_flush (stream);
318 meter.printing = WORKING;
319 }
320
321 if (meter.printing == WORKING && howmuch >= 1.0)
322 return;
323
324 if (!stream->isatty ())
325 return;
326
327 int chars_per_line = get_chars_per_line ();
328 if (chars_per_line > 0)
329 {
330 int i, max;
331 int width = chars_per_line - 3;
332
333 max = width * howmuch;
334 fprintf_unfiltered (stream, "\r[");
335 for (i = 0; i < width; ++i)
336 fprintf_unfiltered (stream, i < max ? "#" : " ");
337 fprintf_unfiltered (stream, "]");
338 gdb_flush (stream);
339 meter.printing = PROGRESS;
340 }
341}
342
343void
344cli_ui_out::do_progress_end ()
345{
346 struct ui_file *stream = m_streams.back ();
347 cli_progress_info &meter = m_meters.back ();
348
349 if (!stream->isatty ())
350 {
d6f26c9d 351 fprintf_unfiltered (stream, "\n");
2f228731
TT
352 gdb_flush (stream);
353 }
354 else if (meter.printing == PROGRESS)
355 {
356 int i;
357 int width = get_chars_per_line () - 3;
358
359 fprintf_unfiltered (stream, "\r");
360 for (i = 0; i < width + 2; ++i)
361 fprintf_unfiltered (stream, " ");
362 fprintf_unfiltered (stream, "\r");
363 gdb_flush (stream);
364 }
365
366 m_meters.pop_back ();
367}
368
8b93c638
JM
369/* local functions */
370
112e8700
SM
371void
372cli_ui_out::field_separator ()
8b93c638 373{
2a3c1174
PA
374 if (test_flags (unfiltered_output))
375 fputc_unfiltered (' ', m_streams.back ());
376 else
377 fputc_filtered (' ', m_streams.back ());
8b93c638
JM
378}
379
112e8700 380/* Constructor for cli_ui_out. */
02a45ac0 381
112e8700
SM
382cli_ui_out::cli_ui_out (ui_file *stream, ui_out_flags flags)
383: ui_out (flags),
384 m_suppress_output (false)
0a8fce9a 385{
14dba4b4
JK
386 gdb_assert (stream != NULL);
387
112e8700
SM
388 m_streams.push_back (stream);
389}
14dba4b4 390
112e8700
SM
391cli_ui_out::~cli_ui_out ()
392{
0a8fce9a
PA
393}
394
395/* Initialize private members at startup. */
8b93c638 396
112e8700 397cli_ui_out *
8b93c638
JM
398cli_out_new (struct ui_file *stream)
399{
112e8700 400 return new cli_ui_out (stream, ui_source_list);
8b93c638
JM
401}
402
112e8700
SM
403ui_file *
404cli_ui_out::set_stream (struct ui_file *stream)
4389a95a 405{
112e8700 406 ui_file *old;
b9b118c3 407
112e8700
SM
408 old = m_streams.back ();
409 m_streams.back () = stream;
c5504eaf 410
4389a95a
AC
411 return old;
412}
b9b118c3 413
046bebe1
TT
414bool
415cli_ui_out::can_emit_style_escape () const
416{
417 return m_streams.back ()->can_emit_style_escape ();
418}
419
82083d6d
DE
420/* CLI interface to display tab-completion matches. */
421
422/* CLI version of displayer.crlf. */
423
424static void
425cli_mld_crlf (const struct match_list_displayer *displayer)
426{
427 rl_crlf ();
428}
429
430/* CLI version of displayer.putch. */
431
432static void
433cli_mld_putch (const struct match_list_displayer *displayer, int ch)
434{
435 putc (ch, rl_outstream);
436}
437
438/* CLI version of displayer.puts. */
439
440static void
441cli_mld_puts (const struct match_list_displayer *displayer, const char *s)
442{
443 fputs (s, rl_outstream);
444}
445
446/* CLI version of displayer.flush. */
447
448static void
449cli_mld_flush (const struct match_list_displayer *displayer)
450{
451 fflush (rl_outstream);
452}
453
56000a98
PA
454EXTERN_C void _rl_erase_entire_line (void);
455
82083d6d
DE
456/* CLI version of displayer.erase_entire_line. */
457
458static void
459cli_mld_erase_entire_line (const struct match_list_displayer *displayer)
460{
82083d6d
DE
461 _rl_erase_entire_line ();
462}
463
464/* CLI version of displayer.beep. */
465
466static void
467cli_mld_beep (const struct match_list_displayer *displayer)
468{
469 rl_ding ();
470}
471
472/* CLI version of displayer.read_key. */
473
474static int
475cli_mld_read_key (const struct match_list_displayer *displayer)
476{
477 return rl_read_key ();
478}
479
480/* CLI version of rl_completion_display_matches_hook.
481 See gdb_display_match_list for a description of the arguments. */
482
483void
484cli_display_match_list (char **matches, int len, int max)
485{
486 struct match_list_displayer displayer;
487
488 rl_get_screen_size (&displayer.height, &displayer.width);
489 displayer.crlf = cli_mld_crlf;
490 displayer.putch = cli_mld_putch;
491 displayer.puts = cli_mld_puts;
492 displayer.flush = cli_mld_flush;
493 displayer.erase_entire_line = cli_mld_erase_entire_line;
494 displayer.beep = cli_mld_beep;
495 displayer.read_key = cli_mld_read_key;
496
497 gdb_display_match_list (matches, len, max, &displayer);
498 rl_forced_update_display ();
499}