123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466 |
- /* 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);
- 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 ()
- {}
- /* 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
|