Fix issues with multiple inferiors
[deliverable/binutils-gdb.git] / gdb / ui-file.c
CommitLineData
d9fcf2fb 1/* UI_FILE - a generic STDIO like output stream.
349c5d5f 2
b811d2c2 3 Copyright (C) 1999-2020 Free Software Foundation, Inc.
4e5106e6 4 Copyright (C) 2019-2020 Advanced Micro Devices, Inc. All rights reserved.
d9fcf2fb
JM
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
a9762ec7 10 the Free Software Foundation; either version 3 of the License, or
d9fcf2fb
JM
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
a9762ec7 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
d9fcf2fb 20
581e13c1 21/* Implement the ``struct ui_file'' object. */
d9fcf2fb
JM
22
23#include "defs.h"
24#include "ui-file.h"
94af9270 25#include "gdb_obstack.h"
ad960ed2 26#include "gdb_select.h"
268a13a5 27#include "gdbsupport/filestuff.h"
f64eea3a 28#include "cli/cli-style.h"
d9fcf2fb 29
d7e74731 30null_file null_stream;
d9fcf2fb 31
d7e74731
PA
32ui_file::ui_file ()
33{}
d9fcf2fb 34
d7e74731
PA
35ui_file::~ui_file ()
36{}
d9fcf2fb 37
d7e74731
PA
38void
39ui_file::printf (const char *format, ...)
d9fcf2fb 40{
d7e74731 41 va_list args;
d9fcf2fb 42
d7e74731
PA
43 va_start (args, format);
44 vfprintf_unfiltered (this, format, args);
45 va_end (args);
d9fcf2fb
JM
46}
47
d7e74731
PA
48void
49ui_file::putstr (const char *str, int quoter)
d9fcf2fb 50{
d7e74731 51 fputstr_unfiltered (str, quoter, this);
d9fcf2fb
JM
52}
53
d7e74731
PA
54void
55ui_file::putstrn (const char *str, int n, int quoter)
d9fcf2fb 56{
7c4e78cf 57 fputstrn_unfiltered (str, n, quoter, fputc_unfiltered, this);
d9fcf2fb
JM
58}
59
d7e74731
PA
60int
61ui_file::putc (int c)
449092f6 62{
d7e74731 63 return fputc_unfiltered (c, this);
449092f6
CV
64}
65
d7e74731
PA
66void
67ui_file::vprintf (const char *format, va_list args)
d9fcf2fb 68{
d7e74731 69 vfprintf_unfiltered (this, format, args);
d9fcf2fb
JM
70}
71
d7e74731 72\f
01124a23 73
d7e74731
PA
74void
75null_file::write (const char *buf, long sizeof_buf)
d9fcf2fb 76{
d7e74731 77 /* Discard the request. */
d9fcf2fb
JM
78}
79
d7e74731
PA
80void
81null_file::puts (const char *)
2a9d5ccf 82{
d7e74731 83 /* Discard the request. */
2a9d5ccf
HZ
84}
85
d7e74731
PA
86void
87null_file::write_async_safe (const char *buf, long sizeof_buf)
d9fcf2fb 88{
d7e74731 89 /* Discard the request. */
d9fcf2fb
JM
90}
91
d7e74731
PA
92\f
93
d9fcf2fb 94void
fba45db2 95gdb_flush (struct ui_file *file)
d9fcf2fb 96{
d7e74731 97 file->flush ();
d9fcf2fb
JM
98}
99
100int
fba45db2 101ui_file_isatty (struct ui_file *file)
d9fcf2fb 102{
d7e74731 103 return file->isatty ();
d9fcf2fb
JM
104}
105
8a522c6c
PW
106/* true if the gdb terminal supports styling, and styling is enabled. */
107
108static bool
109term_cli_styling ()
110{
8a522c6c
PW
111 if (!cli_styling)
112 return false;
113
114 const char *term = getenv ("TERM");
115 /* Windows doesn't by default define $TERM, but can support styles
116 regardless. */
117#ifndef _WIN32
118 if (term == nullptr || !strcmp (term, "dumb"))
119 return false;
120#else
121 /* But if they do define $TERM, let us behave the same as on Posix
122 platforms, for the benefit of programs which invoke GDB as their
123 back-end. */
124 if (term && !strcmp (term, "dumb"))
125 return false;
126#endif
127 return true;
128}
129
130
d9fcf2fb
JM
131void
132ui_file_write (struct ui_file *file,
133 const char *buf,
134 long length_buf)
135{
d7e74731 136 file->write (buf, length_buf);
de571fc5
TT
137}
138
01124a23
DE
139void
140ui_file_write_async_safe (struct ui_file *file,
141 const char *buf,
142 long length_buf)
143{
d7e74731 144 file->write_async_safe (buf, length_buf);
01124a23
DE
145}
146
449092f6
CV
147long
148ui_file_read (struct ui_file *file, char *buf, long length_buf)
149{
d7e74731 150 return file->read (buf, length_buf);
2a9d5ccf
HZ
151}
152
d9fcf2fb 153void
fba45db2 154fputs_unfiltered (const char *buf, struct ui_file *file)
d9fcf2fb 155{
d7e74731 156 file->puts (buf);
d9fcf2fb
JM
157}
158
d7e74731 159\f
d9fcf2fb 160
d7e74731
PA
161string_file::~string_file ()
162{}
d9fcf2fb
JM
163
164void
d7e74731 165string_file::write (const char *buf, long length_buf)
d9fcf2fb 166{
d7e74731 167 m_string.append (buf, length_buf);
d9fcf2fb
JM
168}
169
8a522c6c
PW
170/* See ui-file.h. */
171
172bool
173string_file::term_out ()
174{
175 return m_term_out;
176}
177
178/* See ui-file.h. */
179
180bool
181string_file::can_emit_style_escape ()
182{
183 return m_term_out && term_cli_styling ();
184}
185
d7e74731 186\f
01124a23 187
d7e74731 188stdio_file::stdio_file (FILE *file, bool close_p)
449092f6 189{
d7e74731
PA
190 set_stream (file);
191 m_close_p = close_p;
449092f6
CV
192}
193
d7e74731
PA
194stdio_file::stdio_file ()
195 : m_file (NULL),
196 m_fd (-1),
197 m_close_p (false)
198{}
d9fcf2fb 199
d7e74731 200stdio_file::~stdio_file ()
2a9d5ccf 201{
d7e74731
PA
202 if (m_close_p)
203 fclose (m_file);
2a9d5ccf
HZ
204}
205
d9fcf2fb 206void
d7e74731 207stdio_file::set_stream (FILE *file)
d9fcf2fb 208{
d7e74731
PA
209 m_file = file;
210 m_fd = fileno (file);
d9fcf2fb
JM
211}
212
d7e74731
PA
213bool
214stdio_file::open (const char *name, const char *mode)
d9fcf2fb 215{
d7e74731
PA
216 /* Close the previous stream, if we own it. */
217 if (m_close_p)
218 {
219 fclose (m_file);
220 m_close_p = false;
221 }
5d502164 222
d419f42d 223 gdb_file_up f = gdb_fopen_cloexec (name, mode);
d9fcf2fb 224
d7e74731
PA
225 if (f == NULL)
226 return false;
d9fcf2fb 227
d419f42d 228 set_stream (f.release ());
d7e74731 229 m_close_p = true;
5d502164 230
d7e74731 231 return true;
d9fcf2fb
JM
232}
233
234void
d7e74731 235stdio_file::flush ()
d9fcf2fb 236{
d7e74731 237 fflush (m_file);
d9fcf2fb
JM
238}
239
d7e74731
PA
240long
241stdio_file::read (char *buf, long length_buf)
449092f6 242{
f0881b37
PA
243 /* Wait until at least one byte of data is available, or we get
244 interrupted with Control-C. */
ad960ed2 245 {
ad960ed2 246 fd_set readfds;
f0881b37 247
ad960ed2 248 FD_ZERO (&readfds);
d7e74731
PA
249 FD_SET (m_fd, &readfds);
250 if (interruptible_select (m_fd + 1, &readfds, NULL, NULL, NULL) == -1)
ad960ed2
DJ
251 return -1;
252 }
253
d7e74731 254 return ::read (m_fd, buf, length_buf);
449092f6
CV
255}
256
d7e74731
PA
257void
258stdio_file::write (const char *buf, long length_buf)
d9fcf2fb 259{
bf1d7d9c 260 /* Calling error crashes when we are called from the exception framework. */
d7e74731 261 if (fwrite (buf, length_buf, 1, m_file))
d4fb63e1
TT
262 {
263 /* Nothing. */
264 }
d9fcf2fb
JM
265}
266
d7e74731
PA
267void
268stdio_file::write_async_safe (const char *buf, long length_buf)
01124a23 269{
9f7bc587
DE
270 /* This is written the way it is to avoid a warning from gcc about not using the
271 result of write (since it can be declared with attribute warn_unused_result).
272 Alas casting to void doesn't work for this. */
d7e74731 273 if (::write (m_fd, buf, length_buf))
d4fb63e1
TT
274 {
275 /* Nothing. */
276 }
01124a23
DE
277}
278
d7e74731
PA
279void
280stdio_file::puts (const char *linebuffer)
d9fcf2fb 281{
e4adb939
EZ
282 /* This host-dependent function (with implementations in
283 posix-hdep.c and mingw-hdep.c) is given the opportunity to
284 process the output first in host-dependent way. If it does, it
285 should return non-zero, to avoid calling fputs below. */
286 if (gdb_console_fputs (linebuffer, m_file))
287 return;
bf1d7d9c 288 /* Calling error crashes when we are called from the exception framework. */
d7e74731 289 if (fputs (linebuffer, m_file))
d4fb63e1
TT
290 {
291 /* Nothing. */
292 }
d9fcf2fb
JM
293}
294
d7e74731
PA
295bool
296stdio_file::isatty ()
d9fcf2fb 297{
d7e74731 298 return ::isatty (m_fd);
d9fcf2fb
JM
299}
300
8a522c6c
PW
301/* See ui-file.h. */
302
303bool
304stdio_file::can_emit_style_escape ()
305{
5922befa 306 return ((this == gdb_stdout || this == gdb_stderr)
8a522c6c
PW
307 && this->isatty ()
308 && term_cli_styling ());
309}
310
d7e74731 311\f
2a9d5ccf 312
d7e74731 313/* This is the implementation of ui_file method 'write' for stderr.
ffa4ac95
YQ
314 gdb_stdout is flushed before writing to gdb_stderr. */
315
d7e74731
PA
316void
317stderr_file::write (const char *buf, long length_buf)
ffa4ac95
YQ
318{
319 gdb_flush (gdb_stdout);
d7e74731 320 stdio_file::write (buf, length_buf);
ffa4ac95
YQ
321}
322
d7e74731 323/* This is the implementation of ui_file method 'puts' for stderr.
ffa4ac95
YQ
324 gdb_stdout is flushed before writing to gdb_stderr. */
325
d7e74731
PA
326void
327stderr_file::puts (const char *linebuffer)
ffa4ac95
YQ
328{
329 gdb_flush (gdb_stdout);
d7e74731 330 stdio_file::puts (linebuffer);
ffa4ac95 331}
ffa4ac95 332
d7e74731
PA
333stderr_file::stderr_file (FILE *stream)
334 : stdio_file (stream)
335{}
d9fcf2fb 336
d7e74731 337\f
e4c242d9 338
f3a09c80 339tee_file::tee_file (ui_file *one, ui_file_up &&two)
d7e74731 340 : m_one (one),
f3a09c80 341 m_two (std::move (two))
d7e74731 342{}
e4c242d9 343
d7e74731 344tee_file::~tee_file ()
e4c242d9 345{
e4c242d9
DJ
346}
347
d7e74731
PA
348void
349tee_file::flush ()
e4c242d9 350{
d7e74731
PA
351 m_one->flush ();
352 m_two->flush ();
e4c242d9
DJ
353}
354
d7e74731
PA
355void
356tee_file::write (const char *buf, long length_buf)
e4c242d9 357{
d7e74731
PA
358 m_one->write (buf, length_buf);
359 m_two->write (buf, length_buf);
e4c242d9
DJ
360}
361
d7e74731
PA
362void
363tee_file::write_async_safe (const char *buf, long length_buf)
e4c242d9 364{
d7e74731
PA
365 m_one->write_async_safe (buf, length_buf);
366 m_two->write_async_safe (buf, length_buf);
e4c242d9
DJ
367}
368
d7e74731
PA
369void
370tee_file::puts (const char *linebuffer)
e4c242d9 371{
d7e74731
PA
372 m_one->puts (linebuffer);
373 m_two->puts (linebuffer);
e4c242d9
DJ
374}
375
d7e74731
PA
376bool
377tee_file::isatty ()
e4c242d9 378{
d7e74731 379 return m_one->isatty ();
e4c242d9 380}
8a522c6c
PW
381
382/* See ui-file.h. */
383
384bool
385tee_file::term_out ()
386{
387 return m_one->term_out ();
388}
389
390/* See ui-file.h. */
391
392bool
393tee_file::can_emit_style_escape ()
394{
5922befa 395 return ((this == gdb_stdout || this == gdb_stderr)
8a522c6c
PW
396 && m_one->term_out ()
397 && term_cli_styling ());
398}
0735b091
TT
399
400/* See ui-file.h. */
401
402void
403no_terminal_escape_file::write (const char *buf, long length_buf)
404{
405 std::string copy (buf, length_buf);
406 this->puts (copy.c_str ());
407}
408
409/* See ui-file.h. */
410
411void
412no_terminal_escape_file::puts (const char *buf)
413{
414 while (*buf != '\0')
415 {
416 const char *esc = strchr (buf, '\033');
417 if (esc == nullptr)
418 break;
419
420 int n_read = 0;
421 if (!skip_ansi_escape (esc, &n_read))
422 ++esc;
423
424 this->stdio_file::write (buf, esc - buf);
425 buf = esc + n_read;
426 }
427
428 if (*buf != '\0')
429 this->stdio_file::write (buf, strlen (buf));
430}
This page took 2.113067 seconds and 4 git commands to generate.