|  | /* UI_FILE - a generic STDIO like output stream. | 
|  | Copyright (C) 1999-2022 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 NUL-terminated 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. | 
|  |  | 
|  | This will normally escape backslashes and instances of QUOTER. | 
|  | If QUOTER is 0, it won't escape backslashes or any quoting | 
|  | character.  As a side effect, if you pass the backslash character | 
|  | as the QUOTER, this will escape backslashes as usual, but not any | 
|  | other quoting character.  */ | 
|  | void putstr (const char *str, int quoter); | 
|  |  | 
|  | /* Like putstr, but only print the first N characters of STR.  If | 
|  | ASYNC_SAFE is true, then the output is done via the | 
|  | write_async_safe method.  */ | 
|  | void putstrn (const char *str, int n, int quoter, bool async_safe = false); | 
|  |  | 
|  | void 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 () | 
|  | {} | 
|  |  | 
|  | /* If this object has an underlying file descriptor, then return it. | 
|  | Otherwise, return -1.  */ | 
|  | virtual int fd () const | 
|  | { return -1; } | 
|  |  | 
|  | /* Indicate that if the next sequence of characters overflows the | 
|  | line, a newline should be inserted here rather than when it hits | 
|  | the end.  If INDENT is non-zero, it is a number of spaces to be | 
|  | printed to indent the wrapped part on the next line. | 
|  |  | 
|  | If the line is already overfull, we immediately print a newline and | 
|  | the indentation, and disable further wrapping. | 
|  |  | 
|  | If we don't know the width of lines, but we know the page height, | 
|  | we must not wrap words, but should still keep track of newlines | 
|  | that were explicitly printed. | 
|  |  | 
|  | This routine is guaranteed to force out any output which has been | 
|  | squirreled away in the wrap_buffer, so wrap_here (0) can be | 
|  | used to force out output from the wrap_buffer.  */ | 
|  | virtual void wrap_here (int indent) | 
|  | { | 
|  | } | 
|  |  | 
|  | /* Emit an ANSI style escape for STYLE.  */ | 
|  | virtual void emit_style_escape (const ui_file_style &style); | 
|  |  | 
|  | /* Rest the current output style to the empty style.  */ | 
|  | virtual void reset_style (); | 
|  |  | 
|  | /* Print STR, bypassing any paging that might be done by this | 
|  | ui_file.  Note that nearly no code should call this -- it's | 
|  | intended for use by gdb_printf, but nothing else.  */ | 
|  | virtual void puts_unfiltered (const char *str) | 
|  | { | 
|  | this->puts (str); | 
|  | } | 
|  |  | 
|  | protected: | 
|  |  | 
|  | /* The currently applied style.  */ | 
|  | ui_file_style m_applied_style; | 
|  |  | 
|  | private: | 
|  |  | 
|  | /* Helper function for putstr and putstrn.  Print the character C on | 
|  | this stream as part of the contents of a literal string whose | 
|  | delimiter is QUOTER.  */ | 
|  | void printchar (int c, int quoter, bool async_safe); | 
|  | }; | 
|  |  | 
|  | 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 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.  */ | 
|  | const std::string &string () { return m_string; } | 
|  |  | 
|  | /* Return an std::string containing the entire output collected so far. | 
|  |  | 
|  | The internal buffer is cleared, such that it's ready to build a new | 
|  | string.  */ | 
|  | std::string release () | 
|  | { | 
|  | std::string ret = std::move (m_string); | 
|  | m_string.clear (); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | /* Set the internal buffer contents to STR.  Any existing contents are | 
|  | discarded.  */ | 
|  | string_file &operator= (std::string &&str) | 
|  | { | 
|  | m_string = std::move (str); | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | /* 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; | 
|  |  | 
|  | /* Return the underlying file descriptor.  */ | 
|  | int fd () const override | 
|  | { return m_fd; } | 
|  |  | 
|  | 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; | 
|  |  | 
|  | void emit_style_escape (const ui_file_style &style) override | 
|  | { | 
|  | m_one->emit_style_escape (style); | 
|  | m_two->emit_style_escape (style); | 
|  | } | 
|  |  | 
|  | void reset_style () override | 
|  | { | 
|  | m_one->reset_style (); | 
|  | m_two->reset_style (); | 
|  | } | 
|  |  | 
|  | void puts_unfiltered (const char *str) override | 
|  | { | 
|  | m_one->puts_unfiltered (str); | 
|  | m_two->puts_unfiltered (str); | 
|  | } | 
|  |  | 
|  | 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; | 
|  |  | 
|  | void emit_style_escape (const ui_file_style &style) override | 
|  | { | 
|  | } | 
|  |  | 
|  | void reset_style () override | 
|  | { | 
|  | } | 
|  | }; | 
|  |  | 
|  | /* A base class for ui_file types that wrap another ui_file.  */ | 
|  |  | 
|  | class wrapped_file : public ui_file | 
|  | { | 
|  | public: | 
|  |  | 
|  | bool isatty () override | 
|  | { return m_stream->isatty (); } | 
|  |  | 
|  | bool term_out () override | 
|  | { return m_stream->term_out (); } | 
|  |  | 
|  | bool can_emit_style_escape () override | 
|  | { return m_stream->can_emit_style_escape (); } | 
|  |  | 
|  | void flush () override | 
|  | { m_stream->flush (); } | 
|  |  | 
|  | void wrap_here (int indent) override | 
|  | { m_stream->wrap_here (indent); } | 
|  |  | 
|  | void emit_style_escape (const ui_file_style &style) override | 
|  | { m_stream->emit_style_escape (style); } | 
|  |  | 
|  | /* Rest the current output style to the empty style.  */ | 
|  | void reset_style () override | 
|  | { m_stream->reset_style (); } | 
|  |  | 
|  | int fd () const override | 
|  | { return m_stream->fd (); } | 
|  |  | 
|  | void puts_unfiltered (const char *str) override | 
|  | { m_stream->puts_unfiltered (str); } | 
|  |  | 
|  | void write_async_safe (const char *buf, long length_buf) override | 
|  | { return m_stream->write_async_safe (buf, length_buf); } | 
|  |  | 
|  | protected: | 
|  |  | 
|  | /* Note that this class does not assume ownership of the stream. | 
|  | However, a subclass may choose to, by adding a 'delete' to its | 
|  | destructor.  */ | 
|  | explicit wrapped_file (ui_file *stream) | 
|  | : m_stream (stream) | 
|  | { | 
|  | } | 
|  |  | 
|  | /* The underlying stream.  */ | 
|  | ui_file *m_stream; | 
|  | }; | 
|  |  | 
|  | /* A ui_file that optionally puts a timestamp at the start of each | 
|  | line of output.  */ | 
|  |  | 
|  | class timestamped_file : public wrapped_file | 
|  | { | 
|  | public: | 
|  | explicit timestamped_file (ui_file *stream) | 
|  | : wrapped_file (stream) | 
|  | { | 
|  | } | 
|  |  | 
|  | DISABLE_COPY_AND_ASSIGN (timestamped_file); | 
|  |  | 
|  | void write (const char *buf, long len) override; | 
|  |  | 
|  | private: | 
|  |  | 
|  | /* True if the next output should be timestamped.  */ | 
|  | bool m_needs_timestamp = true; | 
|  | }; | 
|  |  | 
|  | #endif |