]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/ui-file.c
Remove global wrap_here function
[thirdparty/binutils-gdb.git] / gdb / ui-file.c
CommitLineData
d9fcf2fb 1/* UI_FILE - a generic STDIO like output stream.
349c5d5f 2
4a94e368 3 Copyright (C) 1999-2022 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"
bf31fd38 24#include "gdbsupport/gdb_obstack.h"
06cc9596 25#include "gdbsupport/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{
d53fd721
TT
50 while (*str)
51 printchar (*str++, quoter, false);
d9fcf2fb
JM
52}
53
d7e74731 54void
d53fd721 55ui_file::putstrn (const char *str, int n, int quoter, bool async_safe)
d9fcf2fb 56{
d53fd721
TT
57 for (int i = 0; i < n; i++)
58 printchar (str[i], quoter, async_safe);
d9fcf2fb
JM
59}
60
d7e74731
PA
61int
62ui_file::putc (int c)
449092f6 63{
d7e74731 64 return fputc_unfiltered (c, this);
449092f6
CV
65}
66
d7e74731
PA
67void
68ui_file::vprintf (const char *format, va_list args)
d9fcf2fb 69{
d7e74731 70 vfprintf_unfiltered (this, format, args);
d9fcf2fb
JM
71}
72
d53fd721
TT
73/* See ui-file.h. */
74
75void
76ui_file::printchar (int c, int quoter, bool async_safe)
77{
78 char buf[4];
79 int out = 0;
80
81 c &= 0xFF; /* Avoid sign bit follies */
82
83 if (c < 0x20 /* Low control chars */
84 || (c >= 0x7F && c < 0xA0) /* DEL, High controls */
85 || (sevenbit_strings && c >= 0x80))
86 { /* high order bit set */
87 buf[out++] = '\\';
88
89 switch (c)
90 {
91 case '\n':
92 buf[out++] = 'n';
93 break;
94 case '\b':
95 buf[out++] = 'b';
96 break;
97 case '\t':
98 buf[out++] = 't';
99 break;
100 case '\f':
101 buf[out++] = 'f';
102 break;
103 case '\r':
104 buf[out++] = 'r';
105 break;
106 case '\033':
107 buf[out++] = 'e';
108 break;
109 case '\007':
110 buf[out++] = 'a';
111 break;
112 default:
113 {
114 buf[out++] = '0' + ((c >> 6) & 0x7);
115 buf[out++] = '0' + ((c >> 3) & 0x7);
116 buf[out++] = '0' + ((c >> 0) & 0x7);
117 break;
118 }
119 }
120 }
121 else
122 {
123 if (quoter != 0 && (c == '\\' || c == quoter))
124 buf[out++] = '\\';
125 buf[out++] = c;
126 }
127
128 if (async_safe)
129 this->write_async_safe (buf, out);
130 else
131 this->write (buf, out);
132}
133
d7e74731 134\f
01124a23 135
d7e74731
PA
136void
137null_file::write (const char *buf, long sizeof_buf)
d9fcf2fb 138{
d7e74731 139 /* Discard the request. */
d9fcf2fb
JM
140}
141
d7e74731
PA
142void
143null_file::puts (const char *)
2a9d5ccf 144{
d7e74731 145 /* Discard the request. */
2a9d5ccf
HZ
146}
147
d7e74731
PA
148void
149null_file::write_async_safe (const char *buf, long sizeof_buf)
d9fcf2fb 150{
d7e74731 151 /* Discard the request. */
d9fcf2fb
JM
152}
153
d7e74731
PA
154\f
155
8a522c6c
PW
156/* true if the gdb terminal supports styling, and styling is enabled. */
157
158static bool
159term_cli_styling ()
160{
8a522c6c
PW
161 if (!cli_styling)
162 return false;
163
164 const char *term = getenv ("TERM");
165 /* Windows doesn't by default define $TERM, but can support styles
166 regardless. */
167#ifndef _WIN32
168 if (term == nullptr || !strcmp (term, "dumb"))
169 return false;
170#else
171 /* But if they do define $TERM, let us behave the same as on Posix
172 platforms, for the benefit of programs which invoke GDB as their
173 back-end. */
174 if (term && !strcmp (term, "dumb"))
175 return false;
176#endif
177 return true;
178}
179
d7e74731 180\f
d9fcf2fb 181
d7e74731
PA
182string_file::~string_file ()
183{}
d9fcf2fb
JM
184
185void
d7e74731 186string_file::write (const char *buf, long length_buf)
d9fcf2fb 187{
d7e74731 188 m_string.append (buf, length_buf);
d9fcf2fb
JM
189}
190
8a522c6c
PW
191/* See ui-file.h. */
192
193bool
194string_file::term_out ()
195{
196 return m_term_out;
197}
198
199/* See ui-file.h. */
200
201bool
202string_file::can_emit_style_escape ()
203{
204 return m_term_out && term_cli_styling ();
205}
206
d7e74731 207\f
01124a23 208
d7e74731 209stdio_file::stdio_file (FILE *file, bool close_p)
449092f6 210{
d7e74731
PA
211 set_stream (file);
212 m_close_p = close_p;
449092f6
CV
213}
214
d7e74731
PA
215stdio_file::stdio_file ()
216 : m_file (NULL),
217 m_fd (-1),
218 m_close_p (false)
219{}
d9fcf2fb 220
d7e74731 221stdio_file::~stdio_file ()
2a9d5ccf 222{
d7e74731
PA
223 if (m_close_p)
224 fclose (m_file);
2a9d5ccf
HZ
225}
226
d9fcf2fb 227void
d7e74731 228stdio_file::set_stream (FILE *file)
d9fcf2fb 229{
d7e74731
PA
230 m_file = file;
231 m_fd = fileno (file);
d9fcf2fb
JM
232}
233
d7e74731
PA
234bool
235stdio_file::open (const char *name, const char *mode)
d9fcf2fb 236{
d7e74731
PA
237 /* Close the previous stream, if we own it. */
238 if (m_close_p)
239 {
240 fclose (m_file);
241 m_close_p = false;
242 }
5d502164 243
d419f42d 244 gdb_file_up f = gdb_fopen_cloexec (name, mode);
d9fcf2fb 245
d7e74731
PA
246 if (f == NULL)
247 return false;
d9fcf2fb 248
d419f42d 249 set_stream (f.release ());
d7e74731 250 m_close_p = true;
5d502164 251
d7e74731 252 return true;
d9fcf2fb
JM
253}
254
255void
d7e74731 256stdio_file::flush ()
d9fcf2fb 257{
d7e74731 258 fflush (m_file);
d9fcf2fb
JM
259}
260
d7e74731
PA
261long
262stdio_file::read (char *buf, long length_buf)
449092f6 263{
f0881b37
PA
264 /* Wait until at least one byte of data is available, or we get
265 interrupted with Control-C. */
ad960ed2 266 {
ad960ed2 267 fd_set readfds;
f0881b37 268
ad960ed2 269 FD_ZERO (&readfds);
d7e74731
PA
270 FD_SET (m_fd, &readfds);
271 if (interruptible_select (m_fd + 1, &readfds, NULL, NULL, NULL) == -1)
ad960ed2
DJ
272 return -1;
273 }
274
d7e74731 275 return ::read (m_fd, buf, length_buf);
449092f6
CV
276}
277
d7e74731
PA
278void
279stdio_file::write (const char *buf, long length_buf)
d9fcf2fb 280{
bf1d7d9c 281 /* Calling error crashes when we are called from the exception framework. */
d7e74731 282 if (fwrite (buf, length_buf, 1, m_file))
d4fb63e1
TT
283 {
284 /* Nothing. */
285 }
d9fcf2fb
JM
286}
287
d7e74731
PA
288void
289stdio_file::write_async_safe (const char *buf, long length_buf)
01124a23 290{
9f7bc587
DE
291 /* This is written the way it is to avoid a warning from gcc about not using the
292 result of write (since it can be declared with attribute warn_unused_result).
293 Alas casting to void doesn't work for this. */
d7e74731 294 if (::write (m_fd, buf, length_buf))
d4fb63e1
TT
295 {
296 /* Nothing. */
297 }
01124a23
DE
298}
299
d7e74731
PA
300void
301stdio_file::puts (const char *linebuffer)
d9fcf2fb 302{
e4adb939
EZ
303 /* This host-dependent function (with implementations in
304 posix-hdep.c and mingw-hdep.c) is given the opportunity to
305 process the output first in host-dependent way. If it does, it
306 should return non-zero, to avoid calling fputs below. */
307 if (gdb_console_fputs (linebuffer, m_file))
308 return;
bf1d7d9c 309 /* Calling error crashes when we are called from the exception framework. */
d7e74731 310 if (fputs (linebuffer, m_file))
d4fb63e1
TT
311 {
312 /* Nothing. */
313 }
d9fcf2fb
JM
314}
315
d7e74731
PA
316bool
317stdio_file::isatty ()
d9fcf2fb 318{
d7e74731 319 return ::isatty (m_fd);
d9fcf2fb
JM
320}
321
8a522c6c
PW
322/* See ui-file.h. */
323
324bool
325stdio_file::can_emit_style_escape ()
326{
6ec1d75e 327 return ((this == gdb_stdout || this == gdb_stderr)
8a522c6c
PW
328 && this->isatty ()
329 && term_cli_styling ());
330}
331
d7e74731 332\f
2a9d5ccf 333
d7e74731 334/* This is the implementation of ui_file method 'write' for stderr.
ffa4ac95
YQ
335 gdb_stdout is flushed before writing to gdb_stderr. */
336
d7e74731
PA
337void
338stderr_file::write (const char *buf, long length_buf)
ffa4ac95 339{
da5bd37e 340 gdb_stdout->flush ();
d7e74731 341 stdio_file::write (buf, length_buf);
ffa4ac95
YQ
342}
343
d7e74731 344/* This is the implementation of ui_file method 'puts' for stderr.
ffa4ac95
YQ
345 gdb_stdout is flushed before writing to gdb_stderr. */
346
d7e74731
PA
347void
348stderr_file::puts (const char *linebuffer)
ffa4ac95 349{
da5bd37e 350 gdb_stdout->flush ();
d7e74731 351 stdio_file::puts (linebuffer);
ffa4ac95 352}
ffa4ac95 353
d7e74731
PA
354stderr_file::stderr_file (FILE *stream)
355 : stdio_file (stream)
356{}
d9fcf2fb 357
d7e74731 358\f
e4c242d9 359
f3a09c80 360tee_file::tee_file (ui_file *one, ui_file_up &&two)
d7e74731 361 : m_one (one),
f3a09c80 362 m_two (std::move (two))
d7e74731 363{}
e4c242d9 364
d7e74731 365tee_file::~tee_file ()
e4c242d9 366{
e4c242d9
DJ
367}
368
d7e74731
PA
369void
370tee_file::flush ()
e4c242d9 371{
d7e74731
PA
372 m_one->flush ();
373 m_two->flush ();
e4c242d9
DJ
374}
375
d7e74731
PA
376void
377tee_file::write (const char *buf, long length_buf)
e4c242d9 378{
d7e74731
PA
379 m_one->write (buf, length_buf);
380 m_two->write (buf, length_buf);
e4c242d9
DJ
381}
382
d7e74731
PA
383void
384tee_file::write_async_safe (const char *buf, long length_buf)
e4c242d9 385{
d7e74731
PA
386 m_one->write_async_safe (buf, length_buf);
387 m_two->write_async_safe (buf, length_buf);
e4c242d9
DJ
388}
389
d7e74731
PA
390void
391tee_file::puts (const char *linebuffer)
e4c242d9 392{
d7e74731
PA
393 m_one->puts (linebuffer);
394 m_two->puts (linebuffer);
e4c242d9
DJ
395}
396
d7e74731
PA
397bool
398tee_file::isatty ()
e4c242d9 399{
d7e74731 400 return m_one->isatty ();
e4c242d9 401}
8a522c6c
PW
402
403/* See ui-file.h. */
404
405bool
406tee_file::term_out ()
407{
408 return m_one->term_out ();
409}
410
411/* See ui-file.h. */
412
413bool
414tee_file::can_emit_style_escape ()
415{
6ec1d75e 416 return ((this == gdb_stdout || this == gdb_stderr)
8a522c6c
PW
417 && m_one->term_out ()
418 && term_cli_styling ());
419}
0735b091
TT
420
421/* See ui-file.h. */
422
423void
424no_terminal_escape_file::write (const char *buf, long length_buf)
425{
426 std::string copy (buf, length_buf);
427 this->puts (copy.c_str ());
428}
429
430/* See ui-file.h. */
431
432void
433no_terminal_escape_file::puts (const char *buf)
434{
435 while (*buf != '\0')
436 {
437 const char *esc = strchr (buf, '\033');
438 if (esc == nullptr)
439 break;
440
441 int n_read = 0;
442 if (!skip_ansi_escape (esc, &n_read))
443 ++esc;
444
445 this->stdio_file::write (buf, esc - buf);
446 buf = esc + n_read;
447 }
448
449 if (*buf != '\0')
450 this->stdio_file::write (buf, strlen (buf));
451}