xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/ui-file.h (revision f8cf1a9151c7af1cb0bd8b09c13c66bca599c027)
1 /* UI_FILE - a generic STDIO like output stream.
2    Copyright (C) 1999-2023 Free Software Foundation, Inc.
3 
4    This file is part of GDB.
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18 
19 #ifndef UI_FILE_H
20 #define UI_FILE_H
21 
22 #include <string>
23 #include "ui-style.h"
24 
25 /* The abstract ui_file base class.  */
26 
27 class ui_file
28 {
29 public:
30   ui_file ();
31   virtual ~ui_file () = 0;
32 
33   /* Public non-virtual API.  */
34 
35   void printf (const char *, ...) ATTRIBUTE_PRINTF (2, 3);
36 
37   /* Print a NUL-terminated string whose delimiter is QUOTER.  Note
38      that these routines should only be called for printing things
39      which are independent of the language of the program being
40      debugged.
41 
42      This will normally escape backslashes and instances of QUOTER.
43      If QUOTER is 0, it won't escape backslashes or any quoting
44      character.  As a side effect, if you pass the backslash character
45      as the QUOTER, this will escape backslashes as usual, but not any
46      other quoting character.  */
47   void putstr (const char *str, int quoter);
48 
49   /* Like putstr, but only print the first N characters of STR.  If
50      ASYNC_SAFE is true, then the output is done via the
51      write_async_safe method.  */
52   void putstrn (const char *str, int n, int quoter, bool async_safe = false);
53 
54   void putc (int c);
55 
56   void vprintf (const char *, va_list) ATTRIBUTE_PRINTF (2, 0);
57 
58   /* Methods below are both public, and overridable by ui_file
59      subclasses.  */
60 
61   virtual void write (const char *buf, long length_buf) = 0;
62 
63   /* This version of "write" is safe for use in signal handlers.  It's
64      not guaranteed that all existing output will have been flushed
65      first.  Implementations are also free to ignore some or all of
66      the request.  puts_async is not provided as the async versions
67      are rarely used, no point in having both for a rarely used
68      interface.  */
69   virtual void write_async_safe (const char *buf, long length_buf)
70   { gdb_assert_not_reached ("write_async_safe"); }
71 
72   /* Some ui_files override this to provide a efficient implementation
73      that avoids a strlen.  */
74   virtual void puts (const char *str)
75   { this->write (str, strlen (str)); }
76 
77   virtual long read (char *buf, long length_buf)
78   { gdb_assert_not_reached ("can't read from this file type"); }
79 
80   virtual bool isatty ()
81   { return false; }
82 
83   /* true indicates terminal output behaviour such as cli_styling.
84      This default implementation indicates to do terminal output
85      behaviour if the UI_FILE is a tty.  A derived class can override
86      TERM_OUT to have cli_styling behaviour without being a tty.  */
87   virtual bool term_out ()
88   { return isatty (); }
89 
90   /* true if ANSI escapes can be used on STREAM.  */
91   virtual bool can_emit_style_escape ()
92   { return false; }
93 
94   virtual void flush ()
95   {}
96 
97   /* If this object has an underlying file descriptor, then return it.
98      Otherwise, return -1.  */
99   virtual int fd () const
100   { return -1; }
101 
102   /* Indicate that if the next sequence of characters overflows the
103      line, a newline should be inserted here rather than when it hits
104      the end.  If INDENT is non-zero, it is a number of spaces to be
105      printed to indent the wrapped part on the next line.
106 
107      If the line is already overfull, we immediately print a newline and
108      the indentation, and disable further wrapping.
109 
110      If we don't know the width of lines, but we know the page height,
111      we must not wrap words, but should still keep track of newlines
112      that were explicitly printed.
113 
114      This routine is guaranteed to force out any output which has been
115      squirreled away in the wrap_buffer, so wrap_here (0) can be
116      used to force out output from the wrap_buffer.  */
117   virtual void wrap_here (int indent)
118   {
119   }
120 
121   /* Emit an ANSI style escape for STYLE.  */
122   virtual void emit_style_escape (const ui_file_style &style);
123 
124   /* Rest the current output style to the empty style.  */
125   virtual void reset_style ();
126 
127   /* Print STR, bypassing any paging that might be done by this
128      ui_file.  Note that nearly no code should call this -- it's
129      intended for use by gdb_printf, but nothing else.  */
130   virtual void puts_unfiltered (const char *str)
131   {
132     this->puts (str);
133   }
134 
135 protected:
136 
137   /* The currently applied style.  */
138   ui_file_style m_applied_style;
139 
140 private:
141 
142   /* Helper function for putstr and putstrn.  Print the character C on
143      this stream as part of the contents of a literal string whose
144      delimiter is QUOTER.  */
145   void printchar (int c, int quoter, bool async_safe);
146 };
147 
148 typedef std::unique_ptr<ui_file> ui_file_up;
149 
150 /* A ui_file that writes to nowhere.  */
151 
152 class null_file : public ui_file
153 {
154 public:
155   void write (const char *buf, long length_buf) override;
156   void write_async_safe (const char *buf, long sizeof_buf) override;
157   void puts (const char *str) override;
158 };
159 
160 /* A preallocated null_file stream.  */
161 extern null_file null_stream;
162 
163 extern int gdb_console_fputs (const char *, FILE *);
164 
165 /* A std::string-based ui_file.  Can be used as a scratch buffer for
166    collecting output.  */
167 
168 class string_file : public ui_file
169 {
170 public:
171   /* Construct a string_file to collect 'raw' output, i.e. without
172      'terminal' behaviour such as cli_styling.  */
173   string_file () : m_term_out (false) {};
174   /* If TERM_OUT, construct a string_file with terminal output behaviour
175      such as cli_styling)
176      else collect 'raw' output like the previous constructor.  */
177   explicit string_file (bool term_out) : m_term_out (term_out) {};
178   ~string_file () override;
179 
180   /* Override ui_file methods.  */
181 
182   void write (const char *buf, long length_buf) override;
183 
184   long read (char *buf, long length_buf) override
185   { gdb_assert_not_reached ("a string_file is not readable"); }
186 
187   bool term_out () override;
188   bool can_emit_style_escape () override;
189 
190   /* string_file-specific public API.  */
191 
192   /* Accesses the std::string containing the entire output collected
193      so far.  */
194   const std::string &string () { return m_string; }
195 
196   /* Return an std::string containing the entire output collected so far.
197 
198      The internal buffer is cleared, such that it's ready to build a new
199      string.  */
200   std::string release ()
201   {
202     std::string ret = std::move (m_string);
203     m_string.clear ();
204     return ret;
205   }
206 
207   /* Set the internal buffer contents to STR.  Any existing contents are
208      discarded.  */
209   string_file &operator= (std::string &&str)
210   {
211     m_string = std::move (str);
212     return *this;
213   }
214 
215   /* Provide a few convenience methods with the same API as the
216      underlying std::string.  */
217   const char *data () const { return m_string.data (); }
218   const char *c_str () const { return m_string.c_str (); }
219   size_t size () const { return m_string.size (); }
220   bool empty () const { return m_string.empty (); }
221   void clear () { return m_string.clear (); }
222 
223 private:
224   /* The internal buffer.  */
225   std::string m_string;
226 
227   bool m_term_out;
228 };
229 
230 /* A ui_file implementation that maps directly onto <stdio.h>'s FILE.
231    A stdio_file can either own its underlying file, or not.  If it
232    owns the file, then destroying the stdio_file closes the underlying
233    file, otherwise it is left open.  */
234 
235 class stdio_file : public ui_file
236 {
237 public:
238   /* Create a ui_file from a previously opened FILE.  CLOSE_P
239      indicates whether the underlying file should be closed when the
240      stdio_file is destroyed.  */
241   explicit stdio_file (FILE *file, bool close_p = false);
242 
243   /* Create an stdio_file that is not managing any file yet.  Call
244      open to actually open something.  */
245   stdio_file ();
246 
247   ~stdio_file () override;
248 
249   /* Open NAME in mode MODE, and own the resulting file.  Returns true
250      on success, false otherwise.  If the stdio_file previously owned
251      a file, it is closed.  */
252   bool open (const char *name, const char *mode);
253 
254   void flush () override;
255 
256   void write (const char *buf, long length_buf) override;
257 
258   void write_async_safe (const char *buf, long length_buf) override;
259 
260   void puts (const char *) override;
261 
262   long read (char *buf, long length_buf) override;
263 
264   bool isatty () override;
265 
266   bool can_emit_style_escape () override;
267 
268   /* Return the underlying file descriptor.  */
269   int fd () const override
270   { return m_fd; }
271 
272 private:
273   /* Sets the internal stream to FILE, and saves the FILE's file
274      descriptor in M_FD.  */
275   void set_stream (FILE *file);
276 
277   /* The file.  */
278   FILE *m_file;
279 
280   /* The associated file descriptor is extracted ahead of time for
281      stdio_file::write_async_safe's benefit, in case fileno isn't
282      async-safe.  */
283   int m_fd;
284 
285   /* If true, M_FILE is closed on destruction.  */
286   bool m_close_p;
287 };
288 
289 typedef std::unique_ptr<stdio_file> stdio_file_up;
290 
291 /* Like stdio_file, but specifically for stderr.
292 
293    This exists because there is no real line-buffering on Windows, see
294    <http://msdn.microsoft.com/en-us/library/86cebhfs%28v=vs.71%29.aspx>
295    so the stdout is either fully-buffered or non-buffered.  We can't
296    make stdout non-buffered, because of two concerns:
297 
298     1. Non-buffering hurts performance.
299     2. Non-buffering may change GDB's behavior when it is interacting
300        with a front-end, such as Emacs.
301 
302    We leave stdout as fully buffered, but flush it first when
303    something is written to stderr.
304 
305    Note that the 'write_async_safe' method is not overridden, because
306    there's no way to flush a stream in an async-safe manner.
307    Fortunately, it doesn't really matter, because:
308 
309     1. That method is only used for printing internal debug output
310        from signal handlers.
311 
312     2. Windows hosts don't have a concept of async-safeness.  Signal
313        handlers run in a separate thread, so they can call the regular
314        non-async-safe output routines freely.
315 */
316 class stderr_file : public stdio_file
317 {
318 public:
319   explicit stderr_file (FILE *stream);
320 
321   /* Override the output routines to flush gdb_stdout before deferring
322      to stdio_file for the actual outputting.  */
323   void write (const char *buf, long length_buf) override;
324   void puts (const char *linebuffer) override;
325 };
326 
327 /* A ui_file implementation that maps onto two ui-file objects.  */
328 
329 class tee_file : public ui_file
330 {
331 public:
332   /* Create a file which writes to both ONE and TWO.  Ownership of
333      both files is up to the user.  */
334   tee_file (ui_file *one, ui_file *two);
335   ~tee_file () override;
336 
337   void write (const char *buf, long length_buf) override;
338   void write_async_safe (const char *buf, long length_buf) override;
339   void puts (const char *) override;
340 
341   bool isatty () override;
342   bool term_out () override;
343   bool can_emit_style_escape () override;
344   void flush () override;
345 
346   void emit_style_escape (const ui_file_style &style) override
347   {
348     m_one->emit_style_escape (style);
349     m_two->emit_style_escape (style);
350   }
351 
352   void reset_style () override
353   {
354     m_one->reset_style ();
355     m_two->reset_style ();
356   }
357 
358   void puts_unfiltered (const char *str) override
359   {
360     m_one->puts_unfiltered (str);
361     m_two->puts_unfiltered (str);
362   }
363 
364 private:
365   /* The two underlying ui_files.  */
366   ui_file *m_one;
367   ui_file *m_two;
368 };
369 
370 /* A ui_file implementation that filters out terminal escape
371    sequences.  */
372 
373 class no_terminal_escape_file : public stdio_file
374 {
375 public:
376   no_terminal_escape_file ()
377   {
378   }
379 
380   /* Like the stdio_file methods, but these filter out terminal escape
381      sequences.  */
382   void write (const char *buf, long length_buf) override;
383   void puts (const char *linebuffer) override;
384 
385   void emit_style_escape (const ui_file_style &style) override
386   {
387   }
388 
389   void reset_style () override
390   {
391   }
392 };
393 
394 /* A base class for ui_file types that wrap another ui_file.  */
395 
396 class wrapped_file : public ui_file
397 {
398 public:
399 
400   bool isatty () override
401   { return m_stream->isatty (); }
402 
403   bool term_out () override
404   { return m_stream->term_out (); }
405 
406   bool can_emit_style_escape () override
407   { return m_stream->can_emit_style_escape (); }
408 
409   void flush () override
410   { m_stream->flush (); }
411 
412   void wrap_here (int indent) override
413   { m_stream->wrap_here (indent); }
414 
415   void emit_style_escape (const ui_file_style &style) override
416   { m_stream->emit_style_escape (style); }
417 
418   /* Rest the current output style to the empty style.  */
419   void reset_style () override
420   { m_stream->reset_style (); }
421 
422   int fd () const override
423   { return m_stream->fd (); }
424 
425   void puts_unfiltered (const char *str) override
426   { m_stream->puts_unfiltered (str); }
427 
428   void write_async_safe (const char *buf, long length_buf) override
429   { return m_stream->write_async_safe (buf, length_buf); }
430 
431 protected:
432 
433   /* Note that this class does not assume ownership of the stream.
434      However, a subclass may choose to, by adding a 'delete' to its
435      destructor.  */
436   explicit wrapped_file (ui_file *stream)
437     : m_stream (stream)
438   {
439   }
440 
441   /* The underlying stream.  */
442   ui_file *m_stream;
443 };
444 
445 /* A ui_file that optionally puts a timestamp at the start of each
446    line of output.  */
447 
448 class timestamped_file : public wrapped_file
449 {
450 public:
451   explicit timestamped_file (ui_file *stream)
452     : wrapped_file (stream)
453   {
454   }
455 
456   DISABLE_COPY_AND_ASSIGN (timestamped_file);
457 
458   void write (const char *buf, long len) override;
459 
460 private:
461 
462   /* True if the next output should be timestamped.  */
463   bool m_needs_timestamp = true;
464 };
465 
466 #endif
467