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