| /* UI_FILE - a generic STDIO like output stream. |
| Copyright (C) 1999-2020 Free Software Foundation, Inc. |
| |
| This file is part of GDB. |
| |
| This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 3 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
| |
| #ifndef UI_FILE_H |
| #define UI_FILE_H |
| |
| #include <string> |
| #include "ui-style.h" |
| |
| /* The abstract ui_file base class. */ |
| |
| class ui_file |
| { |
| public: |
| ui_file (); |
| virtual ~ui_file () = 0; |
| |
| /* Public non-virtual API. */ |
| |
| void printf (const char *, ...) ATTRIBUTE_PRINTF (2, 3); |
| |
| /* Print a string whose delimiter is QUOTER. Note that these |
| routines should only be called for printing things which are |
| independent of the language of the program being debugged. */ |
| void putstr (const char *str, int quoter); |
| |
| void putstrn (const char *str, int n, int quoter); |
| |
| int putc (int c); |
| |
| void vprintf (const char *, va_list) ATTRIBUTE_PRINTF (2, 0); |
| |
| /* Methods below are both public, and overridable by ui_file |
| subclasses. */ |
| |
| virtual void write (const char *buf, long length_buf) = 0; |
| |
| /* This version of "write" is safe for use in signal handlers. It's |
| not guaranteed that all existing output will have been flushed |
| first. Implementations are also free to ignore some or all of |
| the request. puts_async is not provided as the async versions |
| are rarely used, no point in having both for a rarely used |
| interface. */ |
| virtual void write_async_safe (const char *buf, long length_buf) |
| { gdb_assert_not_reached ("write_async_safe"); } |
| |
| /* Some ui_files override this to provide a efficient implementation |
| that avoids a strlen. */ |
| virtual void puts (const char *str) |
| { this->write (str, strlen (str)); } |
| |
| virtual long read (char *buf, long length_buf) |
| { gdb_assert_not_reached ("can't read from this file type"); } |
| |
| virtual bool isatty () |
| { return false; } |
| |
| /* true indicates terminal output behaviour such as cli_styling. |
| This default implementation indicates to do terminal output |
| behaviour if the UI_FILE is a tty. A derived class can override |
| TERM_OUT to have cli_styling behaviour without being a tty. */ |
| virtual bool term_out () |
| { return isatty (); } |
| |
| /* true if ANSI escapes can be used on STREAM. */ |
| virtual bool can_emit_style_escape () |
| { return false; } |
| |
| virtual void flush () |
| {} |
| }; |
| |
| typedef std::unique_ptr<ui_file> ui_file_up; |
| |
| /* A ui_file that writes to nowhere. */ |
| |
| class null_file : public ui_file |
| { |
| public: |
| void write (const char *buf, long length_buf) override; |
| void write_async_safe (const char *buf, long sizeof_buf) override; |
| void puts (const char *str) override; |
| }; |
| |
| /* A preallocated null_file stream. */ |
| extern null_file null_stream; |
| |
| extern void ui_file_flush (ui_file *); |
| |
| extern int ui_file_isatty (struct ui_file *); |
| |
| extern void ui_file_write (struct ui_file *file, const char *buf, |
| long length_buf); |
| |
| extern void ui_file_write_async_safe (struct ui_file *file, const char *buf, |
| long length_buf); |
| |
| extern long ui_file_read (struct ui_file *file, char *buf, long length_buf); |
| |
| extern void ui_file_puts (struct ui_file *file, const char *buf); |
| |
| extern int gdb_console_fputs (const char *, FILE *); |
| |
| /* A std::string-based ui_file. Can be used as a scratch buffer for |
| collecting output. */ |
| |
| class string_file : public ui_file |
| { |
| public: |
| /* Construct a string_file to collect 'raw' output, i.e. without |
| 'terminal' behaviour such as cli_styling. */ |
| string_file () : m_term_out (false) {}; |
| /* If TERM_OUT, construct a string_file with terminal output behaviour |
| such as cli_styling) |
| else collect 'raw' output like the previous constructor. */ |
| explicit string_file (bool term_out) : m_term_out (term_out) {}; |
| ~string_file () override; |
| |
| /* Override ui_file methods. */ |
| |
| void write (const char *buf, long length_buf) override; |
| |
| long read (char *buf, long length_buf) override |
| { gdb_assert_not_reached ("a string_file is not readable"); } |
| |
| bool term_out () override; |
| bool can_emit_style_escape () override; |
| |
| /* string_file-specific public API. */ |
| |
| /* Accesses the std::string containing the entire output collected |
| so far. |
| |
| Returns a non-const reference so that it's easy to move the |
| string contents out of the string_file. E.g.: |
| |
| string_file buf; |
| buf.printf (....); |
| buf.printf (....); |
| return std::move (buf.string ()); |
| */ |
| std::string &string () { return m_string; } |
| |
| /* Provide a few convenience methods with the same API as the |
| underlying std::string. */ |
| const char *data () const { return m_string.data (); } |
| const char *c_str () const { return m_string.c_str (); } |
| size_t size () const { return m_string.size (); } |
| bool empty () const { return m_string.empty (); } |
| void clear () { return m_string.clear (); } |
| |
| private: |
| /* The internal buffer. */ |
| std::string m_string; |
| |
| bool m_term_out; |
| }; |
| |
| /* A ui_file implementation that maps directly onto <stdio.h>'s FILE. |
| A stdio_file can either own its underlying file, or not. If it |
| owns the file, then destroying the stdio_file closes the underlying |
| file, otherwise it is left open. */ |
| |
| class stdio_file : public ui_file |
| { |
| public: |
| /* Create a ui_file from a previously opened FILE. CLOSE_P |
| indicates whether the underlying file should be closed when the |
| stdio_file is destroyed. */ |
| explicit stdio_file (FILE *file, bool close_p = false); |
| |
| /* Create an stdio_file that is not managing any file yet. Call |
| open to actually open something. */ |
| stdio_file (); |
| |
| ~stdio_file () override; |
| |
| /* Open NAME in mode MODE, and own the resulting file. Returns true |
| on success, false otherwise. If the stdio_file previously owned |
| a file, it is closed. */ |
| bool open (const char *name, const char *mode); |
| |
| void flush () override; |
| |
| void write (const char *buf, long length_buf) override; |
| |
| void write_async_safe (const char *buf, long length_buf) override; |
| |
| void puts (const char *) override; |
| |
| long read (char *buf, long length_buf) override; |
| |
| bool isatty () override; |
| |
| bool can_emit_style_escape () override; |
| |
| private: |
| /* Sets the internal stream to FILE, and saves the FILE's file |
| descriptor in M_FD. */ |
| void set_stream (FILE *file); |
| |
| /* The file. */ |
| FILE *m_file; |
| |
| /* The associated file descriptor is extracted ahead of time for |
| stdio_file::write_async_safe's benefit, in case fileno isn't |
| async-safe. */ |
| int m_fd; |
| |
| /* If true, M_FILE is closed on destruction. */ |
| bool m_close_p; |
| }; |
| |
| typedef std::unique_ptr<stdio_file> stdio_file_up; |
| |
| /* Like stdio_file, but specifically for stderr. |
| |
| This exists because there is no real line-buffering on Windows, see |
| <http://msdn.microsoft.com/en-us/library/86cebhfs%28v=vs.71%29.aspx> |
| so the stdout is either fully-buffered or non-buffered. We can't |
| make stdout non-buffered, because of two concerns: |
| |
| 1. Non-buffering hurts performance. |
| 2. Non-buffering may change GDB's behavior when it is interacting |
| with a front-end, such as Emacs. |
| |
| We leave stdout as fully buffered, but flush it first when |
| something is written to stderr. |
| |
| Note that the 'write_async_safe' method is not overridden, because |
| there's no way to flush a stream in an async-safe manner. |
| Fortunately, it doesn't really matter, because: |
| |
| 1. That method is only used for printing internal debug output |
| from signal handlers. |
| |
| 2. Windows hosts don't have a concept of async-safeness. Signal |
| handlers run in a separate thread, so they can call the regular |
| non-async-safe output routines freely. |
| */ |
| class stderr_file : public stdio_file |
| { |
| public: |
| explicit stderr_file (FILE *stream); |
| |
| /* Override the output routines to flush gdb_stdout before deferring |
| to stdio_file for the actual outputting. */ |
| void write (const char *buf, long length_buf) override; |
| void puts (const char *linebuffer) override; |
| }; |
| |
| /* A ui_file implementation that maps onto two ui-file objects. */ |
| |
| class tee_file : public ui_file |
| { |
| public: |
| /* Create a file which writes to both ONE and TWO. ONE will remain |
| open when this object is destroyed; but TWO will be closed. */ |
| tee_file (ui_file *one, ui_file_up &&two); |
| ~tee_file () override; |
| |
| void write (const char *buf, long length_buf) override; |
| void write_async_safe (const char *buf, long length_buf) override; |
| void puts (const char *) override; |
| |
| bool isatty () override; |
| bool term_out () override; |
| bool can_emit_style_escape () override; |
| void flush () override; |
| |
| private: |
| /* The two underlying ui_files. */ |
| ui_file *m_one; |
| ui_file_up m_two; |
| }; |
| |
| /* A ui_file implementation that filters out terminal escape |
| sequences. */ |
| |
| class no_terminal_escape_file : public stdio_file |
| { |
| public: |
| no_terminal_escape_file () |
| { |
| } |
| |
| /* Like the stdio_file methods, but these filter out terminal escape |
| sequences. */ |
| void write (const char *buf, long length_buf) override; |
| void puts (const char *linebuffer) override; |
| }; |
| |
| #endif |